openms-insight 0.1.8__tar.gz → 0.1.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openms_insight-0.1.8 → openms_insight-0.1.9}/PKG-INFO +1 -1
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/rendering/bridge.py +55 -15
- {openms_insight-0.1.8 → openms_insight-0.1.9}/pyproject.toml +1 -1
- {openms_insight-0.1.8 → openms_insight-0.1.9}/.gitignore +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/LICENSE +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/README.md +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/__init__.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/components/__init__.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/components/heatmap.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/components/lineplot.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/components/sequenceview.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/components/table.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/components/volcanoplot.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/core/__init__.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/core/base.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/core/cache.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/core/registry.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/core/state.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/core/subprocess_preprocess.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/js-component/dist/assets/index.css +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/js-component/dist/assets/index.js +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/js-component/dist/assets/materialdesignicons-webfont.eot +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/js-component/dist/assets/materialdesignicons-webfont.ttf +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/js-component/dist/assets/materialdesignicons-webfont.woff +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/js-component/dist/assets/materialdesignicons-webfont.woff2 +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/js-component/dist/index.html +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/preprocessing/__init__.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/preprocessing/compression.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/preprocessing/filtering.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/preprocessing/scatter.py +0 -0
- {openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/rendering/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openms-insight
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.9
|
|
4
4
|
Summary: Interactive visualization components for mass spectrometry data in Streamlit
|
|
5
5
|
Project-URL: Homepage, https://github.com/t0mdavid-m/OpenMS-Insight
|
|
6
6
|
Project-URL: Documentation, https://github.com/t0mdavid-m/OpenMS-Insight#readme
|
|
@@ -130,10 +130,27 @@ def clear_component_annotations() -> None:
|
|
|
130
130
|
st.session_state[_COMPONENT_ANNOTATIONS_KEY].clear()
|
|
131
131
|
|
|
132
132
|
|
|
133
|
+
def _compute_annotation_hash(component: "BaseComponent") -> Optional[str]:
|
|
134
|
+
"""
|
|
135
|
+
Compute hash of component's dynamic annotations, if any.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
component: The component to check for annotations
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
Short hash string if annotations exist, None otherwise
|
|
142
|
+
"""
|
|
143
|
+
annotations = getattr(component, "_dynamic_annotations", None)
|
|
144
|
+
if annotations is None:
|
|
145
|
+
return None
|
|
146
|
+
# Hash the sorted keys (sufficient for change detection)
|
|
147
|
+
return hashlib.md5(str(sorted(annotations.keys())).encode()).hexdigest()[:8]
|
|
148
|
+
|
|
149
|
+
|
|
133
150
|
def _get_cached_vue_data(
|
|
134
151
|
component_id: str,
|
|
135
152
|
filter_state_hashable: Tuple[Tuple[str, Any], ...],
|
|
136
|
-
) -> Optional[Tuple[Dict[str, Any], str]]:
|
|
153
|
+
) -> Optional[Tuple[Dict[str, Any], str, Optional[str]]]:
|
|
137
154
|
"""
|
|
138
155
|
Get cached Vue data for component if filter state matches.
|
|
139
156
|
|
|
@@ -145,13 +162,19 @@ def _get_cached_vue_data(
|
|
|
145
162
|
filter_state_hashable: Current filter state (for cache validation)
|
|
146
163
|
|
|
147
164
|
Returns:
|
|
148
|
-
Tuple of (vue_data, data_hash) if cache hit, None otherwise
|
|
165
|
+
Tuple of (vue_data, data_hash, annotation_hash) if cache hit, None otherwise
|
|
149
166
|
"""
|
|
150
167
|
cache = _get_component_cache()
|
|
151
168
|
if component_id in cache:
|
|
152
|
-
|
|
169
|
+
entry = cache[component_id]
|
|
170
|
+
# Support both old (3-tuple) and new (4-tuple) format
|
|
171
|
+
if len(entry) == 4:
|
|
172
|
+
cached_state, vue_data, data_hash, ann_hash = entry
|
|
173
|
+
else:
|
|
174
|
+
cached_state, vue_data, data_hash = entry
|
|
175
|
+
ann_hash = None
|
|
153
176
|
if cached_state == filter_state_hashable:
|
|
154
|
-
return (vue_data, data_hash)
|
|
177
|
+
return (vue_data, data_hash, ann_hash)
|
|
155
178
|
return None
|
|
156
179
|
|
|
157
180
|
|
|
@@ -160,6 +183,7 @@ def _set_cached_vue_data(
|
|
|
160
183
|
filter_state_hashable: Tuple[Tuple[str, Any], ...],
|
|
161
184
|
vue_data: Dict[str, Any],
|
|
162
185
|
data_hash: str,
|
|
186
|
+
ann_hash: Optional[str] = None,
|
|
163
187
|
) -> None:
|
|
164
188
|
"""
|
|
165
189
|
Cache Vue data for component, replacing any previous entry.
|
|
@@ -171,9 +195,10 @@ def _set_cached_vue_data(
|
|
|
171
195
|
filter_state_hashable: Current filter state
|
|
172
196
|
vue_data: Data to cache
|
|
173
197
|
data_hash: Hash of the data
|
|
198
|
+
ann_hash: Hash of dynamic annotations (if any)
|
|
174
199
|
"""
|
|
175
200
|
cache = _get_component_cache()
|
|
176
|
-
cache[component_id] = (filter_state_hashable, vue_data, data_hash)
|
|
201
|
+
cache[component_id] = (filter_state_hashable, vue_data, data_hash, ann_hash)
|
|
177
202
|
|
|
178
203
|
|
|
179
204
|
def _prepare_vue_data_cached(
|
|
@@ -217,7 +242,7 @@ def _prepare_vue_data_cached(
|
|
|
217
242
|
)
|
|
218
243
|
|
|
219
244
|
if cached is not None:
|
|
220
|
-
cached_data, cached_hash = cached
|
|
245
|
+
cached_data, cached_hash, _ = cached # Ignore cached annotation hash here
|
|
221
246
|
|
|
222
247
|
if has_dynamic_annotations:
|
|
223
248
|
# Cache hit but need to re-apply annotations (they may have changed)
|
|
@@ -240,6 +265,9 @@ def _prepare_vue_data_cached(
|
|
|
240
265
|
# Cache miss - compute data
|
|
241
266
|
vue_data = component._prepare_vue_data(state_dict)
|
|
242
267
|
|
|
268
|
+
# Compute annotation hash for cache storage
|
|
269
|
+
ann_hash = _compute_annotation_hash(component)
|
|
270
|
+
|
|
243
271
|
if has_dynamic_annotations:
|
|
244
272
|
# Store BASE data (without dynamic annotation columns) in cache
|
|
245
273
|
if hasattr(component, "_strip_dynamic_columns"):
|
|
@@ -248,7 +276,7 @@ def _prepare_vue_data_cached(
|
|
|
248
276
|
# Fallback: store without _plotConfig (may have stale column refs)
|
|
249
277
|
base_data = {k: v for k, v in vue_data.items() if k != "_plotConfig"}
|
|
250
278
|
base_hash = _hash_data(base_data)
|
|
251
|
-
_set_cached_vue_data(component_id, filter_state_hashable, base_data, base_hash)
|
|
279
|
+
_set_cached_vue_data(component_id, filter_state_hashable, base_data, base_hash, ann_hash)
|
|
252
280
|
|
|
253
281
|
# Return full data with annotations
|
|
254
282
|
data_hash = _hash_data(vue_data)
|
|
@@ -256,7 +284,7 @@ def _prepare_vue_data_cached(
|
|
|
256
284
|
else:
|
|
257
285
|
# Store complete data in cache
|
|
258
286
|
data_hash = _hash_data(vue_data)
|
|
259
|
-
_set_cached_vue_data(component_id, filter_state_hashable, vue_data, data_hash)
|
|
287
|
+
_set_cached_vue_data(component_id, filter_state_hashable, vue_data, data_hash, ann_hash)
|
|
260
288
|
return vue_data, data_hash
|
|
261
289
|
|
|
262
290
|
|
|
@@ -377,16 +405,28 @@ def render_component(
|
|
|
377
405
|
# Check if cached data is VALID for current state
|
|
378
406
|
# KEY FIX: Only send data when cache matches current state
|
|
379
407
|
# - Before: Always sent cached data, even if stale (page 38 when Vue wants page 1)
|
|
380
|
-
# - Now: Only send if cache matches current state
|
|
408
|
+
# - Now: Only send if cache matches current state AND annotation state matches
|
|
381
409
|
cache_valid = False
|
|
410
|
+
current_ann_hash = _compute_annotation_hash(component)
|
|
411
|
+
|
|
382
412
|
if cached_entry is not None:
|
|
383
|
-
|
|
384
|
-
|
|
413
|
+
# Support both old (3-tuple) and new (4-tuple) cache format
|
|
414
|
+
if len(cached_entry) == 4:
|
|
415
|
+
cached_state, cached_data, cached_hash, cached_ann_hash = cached_entry
|
|
416
|
+
else:
|
|
417
|
+
cached_state, cached_data, cached_hash = cached_entry
|
|
418
|
+
cached_ann_hash = None
|
|
419
|
+
|
|
420
|
+
# Cache valid only if BOTH filter state AND annotation state match
|
|
421
|
+
filter_state_matches = (cached_state == current_filter_state)
|
|
422
|
+
ann_state_matches = (cached_ann_hash == current_ann_hash)
|
|
423
|
+
cache_valid = filter_state_matches and ann_state_matches
|
|
424
|
+
|
|
385
425
|
if _DEBUG_STATE_SYNC:
|
|
386
426
|
_logger.warning(
|
|
387
427
|
f"[Bridge:{component._cache_id}] Phase1: cache_valid={cache_valid}, "
|
|
388
|
-
f"
|
|
389
|
-
f"
|
|
428
|
+
f"filter_match={filter_state_matches}, ann_match={ann_state_matches}, "
|
|
429
|
+
f"cached_ann={cached_ann_hash}, current_ann={current_ann_hash}"
|
|
390
430
|
)
|
|
391
431
|
|
|
392
432
|
# Build payload - only send data if cache is valid for current state
|
|
@@ -538,8 +578,8 @@ def render_component(
|
|
|
538
578
|
else:
|
|
539
579
|
converted_data[data_key] = value
|
|
540
580
|
|
|
541
|
-
# Store in cache for next render
|
|
542
|
-
cache[component_id] = (filter_state_hashable, converted_data, data_hash)
|
|
581
|
+
# Store in cache for next render (include annotation hash for validity check)
|
|
582
|
+
cache[component_id] = (filter_state_hashable, converted_data, data_hash, current_ann_hash)
|
|
543
583
|
|
|
544
584
|
# If cache was invalid at Phase 1, we didn't send data to Vue (dataChanged=False).
|
|
545
585
|
# Trigger a rerun so the newly cached data gets sent on the next render.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/js-component/dist/assets/index.css
RENAMED
|
File without changes
|
{openms_insight-0.1.8 → openms_insight-0.1.9}/openms_insight/js-component/dist/assets/index.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|