openms-insight 0.1.10__tar.gz → 0.1.12__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.
Files changed (31) hide show
  1. {openms_insight-0.1.10 → openms_insight-0.1.12}/PKG-INFO +21 -1
  2. {openms_insight-0.1.10 → openms_insight-0.1.12}/README.md +20 -0
  3. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/__init__.py +1 -1
  4. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/components/heatmap.py +24 -6
  5. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/components/table.py +12 -1
  6. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/js-component/dist/assets/index.css +1 -1
  7. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/js-component/dist/assets/index.js +3 -3
  8. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/preprocessing/compression.py +9 -4
  9. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/rendering/bridge.py +31 -9
  10. {openms_insight-0.1.10 → openms_insight-0.1.12}/pyproject.toml +1 -1
  11. {openms_insight-0.1.10 → openms_insight-0.1.12}/.gitignore +0 -0
  12. {openms_insight-0.1.10 → openms_insight-0.1.12}/LICENSE +0 -0
  13. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/components/__init__.py +0 -0
  14. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/components/lineplot.py +0 -0
  15. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/components/sequenceview.py +0 -0
  16. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/components/volcanoplot.py +0 -0
  17. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/core/__init__.py +0 -0
  18. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/core/base.py +0 -0
  19. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/core/cache.py +0 -0
  20. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/core/registry.py +0 -0
  21. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/core/state.py +0 -0
  22. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/core/subprocess_preprocess.py +0 -0
  23. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/js-component/dist/assets/materialdesignicons-webfont.eot +0 -0
  24. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/js-component/dist/assets/materialdesignicons-webfont.ttf +0 -0
  25. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/js-component/dist/assets/materialdesignicons-webfont.woff +0 -0
  26. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/js-component/dist/assets/materialdesignicons-webfont.woff2 +0 -0
  27. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/js-component/dist/index.html +0 -0
  28. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/preprocessing/__init__.py +0 -0
  29. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/preprocessing/filtering.py +0 -0
  30. {openms_insight-0.1.10 → openms_insight-0.1.12}/openms_insight/preprocessing/scatter.py +0 -0
  31. {openms_insight-0.1.10 → openms_insight-0.1.12}/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.10
3
+ Version: 0.1.12
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
@@ -243,7 +243,9 @@ Heatmap(
243
243
  - `min_points`: Target size for downsampling (default: 20000)
244
244
  - `x_bins`, `y_bins`: Grid resolution for spatial binning
245
245
  - `colorscale`: Plotly colorscale name (default: 'Portland')
246
+ - `reversescale`: Invert colorscale direction (default: False)
246
247
  - `log_scale`: Use log10 color mapping (default: True). Set to False for linear.
248
+ - `low_values_on_top`: Prioritize low values during downsampling and display them on top (default: False). Use for scores where lower = better (e.g., e-values, PEP, q-values).
247
249
  - `intensity_label`: Custom colorbar label (default: 'Intensity')
248
250
 
249
251
  **Linear scale example:**
@@ -260,6 +262,24 @@ Heatmap(
260
262
  )
261
263
  ```
262
264
 
265
+ **Low values on top (PSM scores):**
266
+ For identification results where lower scores indicate better matches (e.g., e-values, PEP, q-values), use `low_values_on_top=True` to preserve low-scoring points during downsampling and display them on top of high-scoring points:
267
+
268
+ ```python
269
+ Heatmap(
270
+ cache_id="psm_evalue",
271
+ data_path="psm_data.parquet",
272
+ x_column='rt',
273
+ y_column='mz',
274
+ intensity_column='e_value',
275
+ log_scale=True, # Log scale for e-values
276
+ low_values_on_top=True, # Keep/show low e-values (best hits)
277
+ reversescale=True, # Bright color = low value = best
278
+ intensity_label='E-value',
279
+ colorscale='Portland',
280
+ )
281
+ ```
282
+
263
283
  **Categorical mode:**
264
284
  Use `category_column` for discrete coloring by category instead of continuous intensity colorscale:
265
285
 
@@ -208,7 +208,9 @@ Heatmap(
208
208
  - `min_points`: Target size for downsampling (default: 20000)
209
209
  - `x_bins`, `y_bins`: Grid resolution for spatial binning
210
210
  - `colorscale`: Plotly colorscale name (default: 'Portland')
211
+ - `reversescale`: Invert colorscale direction (default: False)
211
212
  - `log_scale`: Use log10 color mapping (default: True). Set to False for linear.
213
+ - `low_values_on_top`: Prioritize low values during downsampling and display them on top (default: False). Use for scores where lower = better (e.g., e-values, PEP, q-values).
212
214
  - `intensity_label`: Custom colorbar label (default: 'Intensity')
213
215
 
214
216
  **Linear scale example:**
@@ -225,6 +227,24 @@ Heatmap(
225
227
  )
226
228
  ```
227
229
 
230
+ **Low values on top (PSM scores):**
231
+ For identification results where lower scores indicate better matches (e.g., e-values, PEP, q-values), use `low_values_on_top=True` to preserve low-scoring points during downsampling and display them on top of high-scoring points:
232
+
233
+ ```python
234
+ Heatmap(
235
+ cache_id="psm_evalue",
236
+ data_path="psm_data.parquet",
237
+ x_column='rt',
238
+ y_column='mz',
239
+ intensity_column='e_value',
240
+ log_scale=True, # Log scale for e-values
241
+ low_values_on_top=True, # Keep/show low e-values (best hits)
242
+ reversescale=True, # Bright color = low value = best
243
+ intensity_label='E-value',
244
+ colorscale='Portland',
245
+ )
246
+ ```
247
+
228
248
  **Categorical mode:**
229
249
  Use `category_column` for discrete coloring by category instead of continuous intensity colorscale:
230
250
 
@@ -16,7 +16,7 @@ from .core.registry import get_component_class, register_component
16
16
  from .core.state import StateManager
17
17
  from .rendering.bridge import clear_component_annotations, get_component_annotations
18
18
 
19
- __version__ = "0.1.7"
19
+ __version__ = "0.1.11"
20
20
 
21
21
  __all__ = [
22
22
  # Core
@@ -93,6 +93,7 @@ class Heatmap(BaseComponent):
93
93
  category_column: Optional[str] = None,
94
94
  category_colors: Optional[Dict[str, str]] = None,
95
95
  log_scale: bool = True,
96
+ low_values_on_top: bool = False,
96
97
  intensity_label: Optional[str] = None,
97
98
  **kwargs,
98
99
  ):
@@ -148,6 +149,11 @@ class Heatmap(BaseComponent):
148
149
  If not provided, default Plotly colors will be used.
149
150
  log_scale: If True (default), apply log10 transformation to intensity
150
151
  values for color mapping. Set to False for linear color mapping.
152
+ low_values_on_top: If True, invert the intensity priority for both downsampling
153
+ and display order. Default False keeps high-intensity points during
154
+ downsampling and draws them on top. Set to True when lower values are
155
+ "better" (e.g., e-values, PEP scores, q-values) so that low values are
156
+ preserved during downsampling and appear on top of high values.
151
157
  intensity_label: Custom label for the colorbar. Default is "Intensity".
152
158
  Useful when displaying non-intensity values like scores or counts.
153
159
  **kwargs: Additional configuration options
@@ -169,6 +175,7 @@ class Heatmap(BaseComponent):
169
175
  self._category_column = category_column
170
176
  self._category_colors = category_colors or {}
171
177
  self._log_scale = log_scale
178
+ self._low_values_on_top = low_values_on_top
172
179
  self._intensity_label = intensity_label
173
180
  self._use_streaming = use_streaming
174
181
  self._categorical_filters = categorical_filters or []
@@ -228,6 +235,7 @@ class Heatmap(BaseComponent):
228
235
  "colorscale": self._colorscale,
229
236
  "category_column": self._category_column,
230
237
  "log_scale": self._log_scale,
238
+ "low_values_on_top": self._low_values_on_top,
231
239
  "intensity_label": self._intensity_label,
232
240
  # Note: category_colors is render-time styling, doesn't affect cache
233
241
  }
@@ -253,6 +261,7 @@ class Heatmap(BaseComponent):
253
261
  self._colorscale = config.get("colorscale", "Portland")
254
262
  self._category_column = config.get("category_column")
255
263
  self._log_scale = config.get("log_scale", True)
264
+ self._low_values_on_top = config.get("low_values_on_top", False)
256
265
  self._intensity_label = config.get("intensity_label")
257
266
  # category_colors is not stored in cache (render-time styling)
258
267
 
@@ -352,6 +361,7 @@ class Heatmap(BaseComponent):
352
361
  current_source,
353
362
  max_points=target_size,
354
363
  intensity_column=self._intensity_column,
364
+ descending=not self._low_values_on_top,
355
365
  )
356
366
  else:
357
367
  level = downsample_2d_streaming(
@@ -364,6 +374,7 @@ class Heatmap(BaseComponent):
364
374
  y_bins=self._y_bins,
365
375
  x_range=x_range,
366
376
  y_range=y_range,
377
+ descending=not self._low_values_on_top,
367
378
  )
368
379
 
369
380
  # Sort and save immediately
@@ -1028,25 +1039,29 @@ class Heatmap(BaseComponent):
1028
1039
  columns=columns_to_select,
1029
1040
  filter_defaults=self._filter_defaults,
1030
1041
  )
1031
- # Sort by intensity ascending so high-intensity points are drawn on top (scattergl)
1042
+ # Sort for render order (last drawn = on top in scattergl)
1043
+ # Default: ascending (high on top). low_values_on_top: descending (low on top)
1032
1044
  if (
1033
1045
  self._intensity_column
1034
1046
  and self._intensity_column in df_pandas.columns
1035
1047
  ):
1036
1048
  df_pandas = df_pandas.sort_values(
1037
- self._intensity_column, ascending=True
1049
+ self._intensity_column, ascending=not self._low_values_on_top
1038
1050
  ).reset_index(drop=True)
1039
1051
  else:
1040
1052
  # No filters to apply - levels already filtered by categorical filter
1041
1053
  schema_names = data.collect_schema().names()
1042
1054
  available_cols = [c for c in columns_to_select if c in schema_names]
1043
1055
  df_polars = data.select(available_cols).collect()
1044
- # Sort by intensity ascending so high-intensity points are drawn on top (scattergl)
1056
+ # Sort for render order (last drawn = on top in scattergl)
1057
+ # Default: ascending (high on top). low_values_on_top: descending (low on top)
1045
1058
  if (
1046
1059
  self._intensity_column
1047
1060
  and self._intensity_column in df_polars.columns
1048
1061
  ):
1049
- df_polars = df_polars.sort(self._intensity_column)
1062
+ df_polars = df_polars.sort(
1063
+ self._intensity_column, descending=self._low_values_on_top
1064
+ )
1050
1065
  data_hash = compute_dataframe_hash(df_polars)
1051
1066
  df_pandas = df_polars.to_pandas()
1052
1067
  else:
@@ -1058,9 +1073,12 @@ class Heatmap(BaseComponent):
1058
1073
  # Select only needed columns
1059
1074
  available_cols = [c for c in columns_to_select if c in df_polars.columns]
1060
1075
  df_polars = df_polars.select(available_cols)
1061
- # Sort by intensity ascending so high-intensity points are drawn on top (scattergl)
1076
+ # Sort for render order (last drawn = on top in scattergl)
1077
+ # Default: ascending (high on top). low_values_on_top: descending (low on top)
1062
1078
  if self._intensity_column and self._intensity_column in df_polars.columns:
1063
- df_polars = df_polars.sort(self._intensity_column)
1079
+ df_polars = df_polars.sort(
1080
+ self._intensity_column, descending=self._low_values_on_top
1081
+ )
1064
1082
  print(
1065
1083
  f"[HEATMAP] Selected {len(df_polars)} pts for zoom, levels={level_sizes}",
1066
1084
  file=sys.stderr,
@@ -650,8 +650,19 @@ class Table(BaseComponent):
650
650
 
651
651
  # Apply server-side sort
652
652
  if sort_column:
653
+ # User-applied sort from pagination state takes precedence
653
654
  descending = sort_dir == "desc"
654
- data = data.sort(sort_column, descending=descending)
655
+ data = data.sort(sort_column, descending=descending, maintain_order=True)
656
+ elif self._initial_sort:
657
+ # Fall back to initial_sort configuration on initial load
658
+ # initial_sort is a list of dicts: [{"column": "mass", "dir": "desc"}, ...]
659
+ sort_columns = [s["column"] for s in self._initial_sort]
660
+ sort_descending = [
661
+ s.get("dir", "asc") == "desc" for s in self._initial_sort
662
+ ]
663
+ data = data.sort(
664
+ sort_columns, descending=sort_descending, maintain_order=True
665
+ )
655
666
 
656
667
  # Get total row count (after filters, before pagination)
657
668
  total_rows = data.select(pl.len()).collect().item()