ode-pump-dashboard / deploy.py
pandeydigant31's picture
Upload folder using huggingface_hub
ed65aea verified
Raw
History Blame Contribute Delete
7.2 kB
#!/usr/bin/env python3
"""
Deploy script for DR MURPHY ODE Dashboard to HuggingFace Spaces.
Run this from any directory:
python3 /path/to/hf_ode_space/deploy.py
Steps:
1. Copy source files from the project tree into this flat directory
2. Patch sys.path imports for flat structure
3. Fix run_sweep_unified argument mismatch
4. Test import chain
5. Deploy to HuggingFace
"""
import shutil
import os
import sys
import re
HERE = os.path.dirname(os.path.abspath(__file__))
SRC_BASE = os.path.dirname(os.path.dirname(HERE)) # cycle2mdot_acceleration/
def step1_copy_files():
"""Copy all source files into the flat deployment directory."""
print("Step 1: Copying source files...")
# Dashboard files
dash = os.path.join(SRC_BASE, 'ode_reformulation/dashboard')
for f in ['scenario_gui.py', 'scenario_analyzer.py', 'sweep_cache.py', 'pump_animation.js']:
src = os.path.join(dash, f)
dst = os.path.join(HERE, f)
shutil.copy2(src, dst)
print(f" Copied dashboard/{f}")
# ODE engine files
ode = os.path.join(SRC_BASE, 'ode_reformulation')
for f in ['cycle2mdot_ode_v2.py', 'cycle2mdot_10var_njit.py']:
shutil.copy2(os.path.join(ode, f), os.path.join(HERE, f))
print(f" Copied ode_reformulation/{f}")
# Project root files
for f in ['cycle2mdot_fast.py', 'cycle2mdot_cached.py', 'h2_ps_lut.npz']:
shutil.copy2(os.path.join(SRC_BASE, f), os.path.join(HERE, f))
print(f" Copied {f}")
# break_coolprop directory
bc_src = os.path.join(SRC_BASE, 'break_coolprop')
bc_dst = os.path.join(HERE, 'break_coolprop')
os.makedirs(bc_dst, exist_ok=True)
for f in ['__init__.py', 'helmholtz_h2.py', 'lut_ps.py', 'h2_props.py', 'cycle2mdot_break.py']:
shutil.copy2(os.path.join(bc_src, f), os.path.join(bc_dst, f))
print(f" Copied break_coolprop/{f}")
# sweep_analysis.py is already created by the Write tool
# engine_bridge.py, app.py, README.md, requirements.txt are already present
print(" Done.")
def step2_patch_imports():
"""Patch sys.path hacks in copied engine files for flat structure."""
print("\nStep 2: Patching imports for flat structure...")
# cycle2mdot_ode_v2.py: change sys.path.insert to use current dir
_patch_sys_path(os.path.join(HERE, 'cycle2mdot_ode_v2.py'))
# cycle2mdot_10var_njit.py: same
_patch_sys_path(os.path.join(HERE, 'cycle2mdot_10var_njit.py'))
print(" Done.")
def _patch_sys_path(filepath):
"""Replace sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
with sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))"""
with open(filepath, 'r') as f:
content = f.read()
# Replace grandparent path with current directory path
old_pattern = "sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))"
new_pattern = "sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))"
if old_pattern in content:
content = content.replace(old_pattern, new_pattern)
with open(filepath, 'w') as f:
f.write(content)
print(f" Patched {os.path.basename(filepath)}: sys.path -> current dir")
else:
print(f" {os.path.basename(filepath)}: no sys.path patch needed")
def step3_fix_sweep_args():
"""Fix run_sweep_unified to accept the engine argument from sr_all_inputs."""
print("\nStep 3: Fixing run_sweep_unified argument mismatch...")
gui_path = os.path.join(HERE, 'scenario_gui.py')
with open(gui_path, 'r') as f:
content = f.read()
# Find the function signature and add engine parameter
old_sig = " fill_type, vsnubber, vchss, aov140f, rodia,\n num_cycles=1):"
new_sig = " fill_type, vsnubber, vchss, aov140f, rodia,\n num_cycles=1, engine='njit_10var'):"
if old_sig in content and "def run_sweep_unified" in content:
content = content.replace(old_sig, new_sig, 1)
with open(gui_path, 'w') as f:
f.write(content)
print(" Added 'engine' parameter to run_sweep_unified()")
else:
print(" run_sweep_unified already has engine param or signature changed")
print(" Done.")
def step4_test_imports():
"""Test that the import chain works in the flat structure."""
print("\nStep 4: Testing import chain...")
# Add this directory to path
if HERE not in sys.path:
sys.path.insert(0, HERE)
try:
import engine_bridge
print(f" engine_bridge: OK (engines: {engine_bridge.ENGINES})")
except Exception as e:
print(f" engine_bridge: FAILED - {e}")
return False
try:
import scenario_analyzer
print(" scenario_analyzer: OK")
except Exception as e:
print(f" scenario_analyzer: FAILED - {e}")
return False
try:
import sweep_analysis
print(" sweep_analysis: OK")
except Exception as e:
print(f" sweep_analysis: FAILED - {e}")
return False
try:
import sweep_cache
print(" sweep_cache: OK")
except Exception as e:
print(f" sweep_cache: FAILED - {e}")
return False
print(" All imports OK!")
return True
def step5_deploy():
"""Deploy to HuggingFace Spaces."""
print("\nStep 5: Deploying to HuggingFace...")
try:
from huggingface_hub import HfApi
except ImportError:
print(" huggingface_hub not installed. Installing...")
os.system(f"{sys.executable} -m pip install huggingface_hub")
from huggingface_hub import HfApi
api = HfApi()
# Create the repo (or verify it exists)
try:
api.create_repo("csh2/ode-pump-dashboard", repo_type="space",
space_sdk="gradio", exist_ok=True)
print(" Repository csh2/ode-pump-dashboard created/verified.")
except Exception as e:
print(f" Error creating repo: {e}")
print(" You may need to run: huggingface-cli login")
return False
# Upload the folder (exclude deploy.py, __pycache__, .db files)
try:
api.upload_folder(
folder_path=HERE,
repo_id="csh2/ode-pump-dashboard",
repo_type="space",
ignore_patterns=["deploy.py", "__pycache__", "*.db", "*.db-shm", "*.db-wal",
".DS_Store", "*.pyc"],
)
print(" Upload complete!")
print(" Space URL: https://huggingface.co/spaces/csh2/ode-pump-dashboard")
except Exception as e:
print(f" Upload failed: {e}")
print(" You may need to run: huggingface-cli login")
return False
return True
def main():
print("=" * 60)
print("DR MURPHY ODE -- HuggingFace Space Deployment")
print("=" * 60)
step1_copy_files()
step2_patch_imports()
step3_fix_sweep_args()
ok = step4_test_imports()
if not ok:
print("\nImport test failed. Fix errors before deploying.")
sys.exit(1)
step5_deploy()
print("\n" + "=" * 60)
print("Deployment complete!")
print("=" * 60)
if __name__ == "__main__":
main()