Spaces:
Running on Zero
Running on Zero
Download trajectory_frames.py from kys-sheng/TheorySpaceNavigationBARTL: direct link, hf CLI and curl.
- Browser
- Download file 4.36 kB
-
https://huggingface.co/spaces/kys-sheng/TheorySpaceNavigationBARTL/resolve/main/trajectory_frames.py
- Command line
-
hf download hf://spaces/kys-sheng/TheorySpaceNavigationBARTL/trajectory_frames.py
-
curl -L -o trajectory_frames.py https://huggingface.co/spaces/kys-sheng/TheorySpaceNavigationBARTL/resolve/main/trajectory_frames.py
4.36 kB
| """ | |
| Discovers pre-exported steering-trajectory frame PNGs (one per alpha value) | |
| and the corresponding assembled GIF, per case: | |
| assets/trajectory_frames/<case>/frame_NNN_alphaX.XX.png | |
| assets/trajectory_gifs/<case>.gif | |
| Both produced by the physics_gif() function in | |
| steering_paper_v2/notebooks/v3/02_paper_results.ipynb. No Gradio dependency. | |
| """ | |
| import os | |
| import re | |
| ASSETS_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets") | |
| FRAMES_DIR = os.path.join(ASSETS_DIR, "trajectory_frames") | |
| GIFS_DIR = os.path.join(ASSETS_DIR, "trajectory_gifs") | |
| _FRAME_RE = re.compile(r"alpha([\d.]+)\.png$") | |
| # case key -> human-readable label (from PHYSICS_GIF_LABELS in | |
| # 02_paper_results.ipynb, LaTeX stripped down to plain text since Gradio | |
| # Dropdown choices don't render LaTeX). | |
| CASE_LABELS = { | |
| "s2r": "phi -> psi_R (scalar to right-handed fermion)", | |
| "s2l": "phi -> psi_L (scalar to left-handed fermion)", | |
| "r2l": "psi_R -> psi_L", | |
| "su3_1to3": "SU(3): 1 -> 3", | |
| "su3_1to3bar": "SU(3): 1 -> 3-bar", | |
| "su3_3_to_3bar": "SU(3): 3 -> 3-bar", | |
| "su2_1to2": "SU(2): 1 -> 2", | |
| "su2_1to3": "SU(2): 1 -> 3", | |
| "su2_1toany": "SU(2) extension (rep. size ambiguous)", | |
| "modintq_div2": "U(1): Q_int -> Q_int / 2", | |
| "u1_b2c": "Enforce U(1) charge conservation", | |
| "susy_all": "SUSY: 1-3 fields (unrestricted)", | |
| "susy_1f": "SUSY: 1 field", | |
| "susy_2f": "SUSY: 2 fields", | |
| "add_s2r_r2l_e1": "(phi -> psi_R) + (psi_R -> psi_L), additive", | |
| "susy_1f_s": "SUSY: 1 scalar field (scalar source)", | |
| "acc_rel": "Gauge anomaly-free: by field extension", | |
| "acc_abs": "Gauge anomaly-free: by field extension (absolute scaling)", | |
| "acc_3f": "Gauge anomaly-free: by delta-Q", | |
| "wit_uniq": "Witten anomaly-free", | |
| } | |
| # Cases present on disk (assets/trajectory_frames/<case>/) but deliberately | |
| # left out of the dropdown — data stays put, just not shown. | |
| EXCLUDED_CASES = {"acc_abs"} | |
| # Dropdown order, matching HEADLINE_CASES in 02_paper_results.ipynb (the | |
| # table behind the paper's combined headline plots) — grouped by family: | |
| # Lorentz -> SU(3) -> SU(2) -> U(1) -> Theory extension -> Anomaly. Any | |
| # case not listed here (e.g. a new one added before this list is updated) | |
| # falls back to alphabetical, appended after the ordered ones. | |
| CASE_ORDER = [ | |
| "s2r", "s2l", "r2l", "add_s2r_r2l_e1", | |
| "su3_1to3", "su3_1to3bar", "su3_3_to_3bar", | |
| "su2_1to2", "su2_1to3", | |
| "modintq_div2", "u1_b2c", | |
| "susy_1f", "susy_1f_s", "susy_2f", "susy_all", "su2_1toany", | |
| "acc_rel", "acc_3f", "wit_uniq", | |
| ] | |
| def _discover_cases(): | |
| if not os.path.isdir(FRAMES_DIR): | |
| return [] | |
| found = { | |
| d for d in os.listdir(FRAMES_DIR) | |
| if os.path.isdir(os.path.join(FRAMES_DIR, d)) and d not in EXCLUDED_CASES | |
| } | |
| ordered = [c for c in CASE_ORDER if c in found] | |
| leftover = sorted(found - set(CASE_ORDER)) | |
| return ordered + leftover | |
| def _discover_frames(case_dir): | |
| alphas_to_path = {} | |
| for fname in os.listdir(case_dir): | |
| m = _FRAME_RE.search(fname) | |
| if m: | |
| alphas_to_path[float(m.group(1))] = os.path.join(case_dir, fname) | |
| if not alphas_to_path: | |
| raise ValueError(f"No frame_*_alpha*.png files found in {case_dir}") | |
| return dict(sorted(alphas_to_path.items())) | |
| CASES = _discover_cases() | |
| # case key -> {alpha: frame_path}, sorted by alpha | |
| CASE_FRAMES = {case: _discover_frames(os.path.join(FRAMES_DIR, case)) for case in CASES} | |
| # case key -> [(alpha, path), ...] sorted by alpha, for index-based access — | |
| # most cases have a uniform alpha step, but at least one (acc_abs) doesn't, | |
| # so the slider indexes into this list by position rather than by alpha | |
| # value directly. | |
| CASE_FRAME_LIST = {case: sorted(frames.items()) for case, frames in CASE_FRAMES.items()} | |
| # dropdown choices as (label, value) pairs, falling back to the raw key | |
| CASE_CHOICES = [(CASE_LABELS.get(case, case), case) for case in CASES] | |
| def n_frames(case): | |
| return len(CASE_FRAME_LIST[case]) | |
| def frame_by_index(case, index): | |
| frames = CASE_FRAME_LIST[case] | |
| index = max(0, min(index, len(frames) - 1)) | |
| alpha, path = frames[index] | |
| return alpha, path | |
| def gif_path(case): | |
| path = os.path.join(GIFS_DIR, f"{case}.gif") | |
| if not os.path.isfile(path): | |
| raise ValueError(f"No assembled GIF found for case {case!r} at {path}") | |
| return path | |