| |
| 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() |
| ENTRY = os.getenv("CORE_ENTRY", "kinetics_core:simulate") |
| simulate_fn = import_callable_from_entry(ENTRY, CORE_DIR) |
|
|
| |
| with gr.Blocks(title="Kinetics Simulator — Solver") as demo: |
| gr.Markdown("## Kinetics Simulator — Solver") |
|
|
| |
| 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"))) |
|
|