ga11en commited on
Commit
de60a33
·
verified ·
1 Parent(s): fa641c4

Keep basis-family name out of the client config (neutralize Fitting radio value)

Browse files
Files changed (3) hide show
  1. .gitignore +4 -0
  2. app.py +9 -2
  3. 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, degree=int(degree), segment_length=int(segment_length),
 
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", "chebyshev")],
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
  )