yxi8's picture
Upload 7 files
8dff354 verified
Raw
History Blame Contribute Delete
4.45 kB
#!/usr/bin/env python3
import os, sys, subprocess, shutil, importlib
import gradio as gr
TARGET_DIR = "/home/user/app/external_core"
def run(cmd, **kw):
subprocess.check_call(cmd, **kw)
def git_probe(url):
try:
subprocess.check_output(["git", "ls-remote", "--heads", url], stderr=subprocess.STDOUT)
return True
except subprocess.CalledProcessError:
return False
def build_authed_url(repo_url, token):
if repo_url.startswith("https://github.com/"):
return repo_url.replace("https://github.com/", f"https://x-access-token:{token}@github.com/")
if repo_url.startswith("https://"):
return "https://x-access-token:{}@{}".format(token, repo_url.split("https://",1)[1])
return repo_url
def ensure_private_core():
REPO_URL = os.getenv("CORE_REPO_URL")
BRANCH = os.getenv("CORE_BRANCH")
TOKEN = os.getenv("GIT_TOKEN")
def fresh_clone(url):
if os.path.isdir(TARGET_DIR):
shutil.rmtree(TARGET_DIR)
run(["git", "clone", "--depth", "1", "-b", BRANCH, url, TARGET_DIR])
if git_probe(REPO_URL):
fresh_clone(REPO_URL)
else:
if not TOKEN:
raise RuntimeError("Repo requires auth but GIT_TOKEN is missing.")
authed = build_authed_url(REPO_URL, TOKEN)
if not git_probe(authed):
raise RuntimeError("Git auth probe failed for the provided token/permissions.")
fresh_clone(authed)
return TARGET_DIR
def import_callable_from_entry(entry, base_path):
if base_path not in sys.path:
sys.path.insert(0, base_path)
module_name, func_name = entry.split(":", 1)
mod = importlib.import_module(module_name)
return getattr(mod, func_name)
CORE_DIR = ensure_private_core() # returns TARGET_DIR
ENTRY = os.getenv("CORE_ENTRY", "kinetics_core:simulate")
simulate_fn = import_callable_from_entry(ENTRY, CORE_DIR)
# -------- Gradio UI --------
with gr.Blocks(title="Kinetics Simulator — Solver") as demo:
gr.Markdown("## Kinetics Simulator — Solver")
# Centered reaction scheme at 30% width
gr.HTML("""
<style>
/* Center the image container and scale to 30% of the app width */
#rxn_img { display: flex; justify-content: center; }
#rxn_img img { width: 30% !important; height: auto !important; margin: auto; }
</style>
""")
gr.Image(value="./reaction.png", show_label=False, interactive=False, elem_id="rxn_img")
rtol_state = gr.State(1e-8)
atol_state = gr.State(1e-14)
ceil_state = gr.State(1e30)
with gr.Row():
with gr.Column():
S0 = gr.Number(value=5e-1, label="Initial S (M)")
I10 = gr.Number(value=0.0, label="Initial I-1 (M)")
I20 = gr.Number(value=0.0, label="Initial I-2 (M)")
P0 = gr.Number(value=0.0, label="Initial P (M)")
A = gr.Number(value=2e-13, label="A (M)")
HD = gr.Number(value=1e-1, label="HD (M)")
kHAA1 = gr.Number(value=1e9, label="kHAA1 (M^-1 s^-1)")
kHAD1 = gr.Number(value=1e7, label="kHAD1 (M^-1 s^-1)")
kHAA2 = gr.Number(value=4e9, label="kHAA2 (M^-1 s^-1)")
kHAD2 = gr.Number(value=2e7, label="kHAD2 (M^-1 s^-1)")
krearr1 = gr.Number(value=1e6, label="krearr1 (s^-1)")
krearr2 = gr.Number(value=1e4, label="krearr2 (s^-1)")
T = gr.Number(value=1e5, label="Duration (s)")
Npts = gr.Number(value=200, label="Points (t_eval)")
run_btn = gr.Button("Run Simulation", variant="primary")
with gr.Column():
plot = gr.Plot(label="Concentration evolution")
stats = gr.JSON(label="Summary")
def run_sim(S0, I10, I20, P0, A, HD,
kHAA1, kHAD1, kHAA2, kHAD2, krearr1, krearr2,
T, Npts, rtol, atol, ceil):
return simulate_fn(
S0, I10, I20, P0, A, HD,
kHAA1, kHAD1, kHAA2, kHAD2, krearr1, krearr2,
T, int(Npts),
rtol=float(rtol), atol=float(atol), ceil=float(ceil)
)
run_btn.click(
run_sim,
inputs=[S0, I10, I20, P0, A, HD, kHAA1, kHAD1, kHAA2, kHAD2, krearr1, krearr2, T, Npts, rtol_state, atol_state, ceil_state],
outputs=[plot, stats],
api_name="simulate"
)
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=int(os.getenv("PORT", "7860")))