Spaces:
Sleeping
Sleeping
Keep basis-family name out of the client config (neutralize Fitting radio value)
Browse files- .gitignore +4 -0
- app.py +9 -2
- demo_core.py +10 -1
.gitignore
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Vendored wheel is gitignored (rebuildable). Build with build-nuitka.sh in a
|
| 2 |
+
# linux/amd64 container; see the Dockerfile and README.md in this dir.
|
| 3 |
+
*.whl
|
| 4 |
+
__pycache__/
|
app.py
CHANGED
|
@@ -107,10 +107,17 @@ feature vectors, and a per-window anomaly score for free.</div>
|
|
| 107 |
""".strip()
|
| 108 |
|
| 109 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
def run(sample_name: str, csv_file, fitting: str, degree: int, segment_length: int):
|
| 111 |
signal = _load_signal(sample_name, csv_file)
|
| 112 |
r = demo_core.run_demo(
|
| 113 |
-
signal, basis_mode=fitting,
|
|
|
|
| 114 |
)
|
| 115 |
return _summary(r), plots.fig_reconstruction(r), plots.fig_sigma(r), plots.fig_sizes(r)
|
| 116 |
|
|
@@ -126,7 +133,7 @@ def build_ui() -> gr.Blocks:
|
|
| 126 |
)
|
| 127 |
csv = gr.File(label="...or upload a numeric CSV", file_types=[".csv"])
|
| 128 |
fitting = gr.Radio(
|
| 129 |
-
choices=[("MDL adaptive selection", "auto"), ("Single fixed basis", "
|
| 130 |
value="auto",
|
| 131 |
label="Fitting",
|
| 132 |
)
|
|
|
|
| 107 |
""".strip()
|
| 108 |
|
| 109 |
|
| 110 |
+
# The Fitting radio's backing values stay generic ("auto" / "single") so no
|
| 111 |
+
# basis-family name is shipped to the browser in the gradio config or API
|
| 112 |
+
# schema. Map the UI value to the SDK basis mode here, at the server boundary.
|
| 113 |
+
_FITTING_TO_BASIS = {"auto": "auto", "single": "chebyshev"}
|
| 114 |
+
|
| 115 |
+
|
| 116 |
def run(sample_name: str, csv_file, fitting: str, degree: int, segment_length: int):
|
| 117 |
signal = _load_signal(sample_name, csv_file)
|
| 118 |
r = demo_core.run_demo(
|
| 119 |
+
signal, basis_mode=_FITTING_TO_BASIS.get(fitting, "auto"),
|
| 120 |
+
degree=int(degree), segment_length=int(segment_length),
|
| 121 |
)
|
| 122 |
return _summary(r), plots.fig_reconstruction(r), plots.fig_sigma(r), plots.fig_sizes(r)
|
| 123 |
|
|
|
|
| 133 |
)
|
| 134 |
csv = gr.File(label="...or upload a numeric CSV", file_types=[".csv"])
|
| 135 |
fitting = gr.Radio(
|
| 136 |
+
choices=[("MDL adaptive selection", "auto"), ("Single fixed basis", "single")],
|
| 137 |
value="auto",
|
| 138 |
label="Fitting",
|
| 139 |
)
|
demo_core.py
CHANGED
|
@@ -27,7 +27,14 @@ SCALE = 1000
|
|
| 27 |
|
| 28 |
|
| 29 |
def _basis_name(basis_id: int) -> str:
|
| 30 |
-
"""Human label for a segment's chosen basis family.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
if basis_id == 0:
|
| 32 |
return "Chebyshev" # explicit (non-MDL) path stores basis_id 0
|
| 33 |
cls = BASIS_REGISTRY.get(basis_id)
|
|
@@ -131,6 +138,8 @@ def run_demo(
|
|
| 131 |
|
| 132 |
sigma_r = np.array([float(m.sigma_r) for m in metas], dtype=float)
|
| 133 |
seg_starts = np.array([int(m.start) for m in metas], dtype=int)
|
|
|
|
|
|
|
| 134 |
bases_used = dict(
|
| 135 |
sorted(Counter(_basis_name(m.basis_id) for m in metas).items(), key=lambda kv: -kv[1]),
|
| 136 |
)
|
|
|
|
| 27 |
|
| 28 |
|
| 29 |
def _basis_name(basis_id: int) -> str:
|
| 30 |
+
"""Human label for a segment's chosen basis family.
|
| 31 |
+
|
| 32 |
+
IP guard: the return value names a basis family (Chebyshev, and via the
|
| 33 |
+
registry the MDL-selected families). It feeds ``bases_used`` in the result
|
| 34 |
+
dict, which is kept for server-side use only. Never render ``bases_used``
|
| 35 |
+
(or any value from this function) into the UI summary, the plots, or any
|
| 36 |
+
other client-served output: the basis-family selection is the moat.
|
| 37 |
+
"""
|
| 38 |
if basis_id == 0:
|
| 39 |
return "Chebyshev" # explicit (non-MDL) path stores basis_id 0
|
| 40 |
cls = BASIS_REGISTRY.get(basis_id)
|
|
|
|
| 138 |
|
| 139 |
sigma_r = np.array([float(m.sigma_r) for m in metas], dtype=float)
|
| 140 |
seg_starts = np.array([int(m.start) for m in metas], dtype=int)
|
| 141 |
+
# IP guard: server-side only. Names basis families; never surface to the
|
| 142 |
+
# client (see _basis_name). Kept for local debugging / verify_local.py.
|
| 143 |
bases_used = dict(
|
| 144 |
sorted(Counter(_basis_name(m.basis_id) for m in metas).items(), key=lambda kv: -kv[1]),
|
| 145 |
)
|