masster 0.4.0__py3-none-any.whl → 0.4.1__py3-none-any.whl
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.
- masster/__init__.py +8 -8
- masster/_version.py +1 -1
- masster/chromatogram.py +3 -9
- masster/data/libs/README.md +1 -1
- masster/data/libs/ccm.csv +120 -120
- masster/data/libs/ccm.py +116 -62
- masster/data/libs/central_carbon_README.md +1 -1
- masster/data/libs/urine.py +161 -65
- masster/data/libs/urine_metabolites.csv +4693 -4693
- masster/data/wiff/2025_01_14_VW_7600_LpMx_DBS_CID_2min_TOP15_030msecMS1_005msecReac_CE35_DBS-ON_3.mzML +2 -2
- masster/logger.py +43 -78
- masster/sample/__init__.py +1 -1
- masster/sample/adducts.py +264 -338
- masster/sample/defaults/find_adducts_def.py +8 -21
- masster/sample/defaults/find_features_def.py +1 -6
- masster/sample/defaults/get_spectrum_def.py +1 -5
- masster/sample/defaults/sample_def.py +1 -5
- masster/sample/h5.py +282 -561
- masster/sample/helpers.py +75 -131
- masster/sample/lib.py +17 -42
- masster/sample/load.py +17 -31
- masster/sample/parameters.py +2 -6
- masster/sample/plot.py +27 -88
- masster/sample/processing.py +87 -117
- masster/sample/quant.py +51 -57
- masster/sample/sample.py +90 -103
- masster/sample/sample5_schema.json +44 -44
- masster/sample/save.py +12 -35
- masster/sample/sciex.py +19 -66
- masster/spectrum.py +20 -58
- masster/study/__init__.py +1 -1
- masster/study/defaults/align_def.py +1 -5
- masster/study/defaults/fill_chrom_def.py +1 -5
- masster/study/defaults/fill_def.py +1 -5
- masster/study/defaults/integrate_chrom_def.py +1 -5
- masster/study/defaults/integrate_def.py +1 -5
- masster/study/defaults/study_def.py +25 -58
- masster/study/export.py +207 -233
- masster/study/h5.py +136 -470
- masster/study/helpers.py +202 -495
- masster/study/helpers_optimized.py +13 -40
- masster/study/id.py +110 -213
- masster/study/load.py +143 -230
- masster/study/plot.py +257 -518
- masster/study/processing.py +257 -469
- masster/study/save.py +5 -15
- masster/study/study.py +276 -379
- masster/study/study5_schema.json +96 -96
- {masster-0.4.0.dist-info → masster-0.4.1.dist-info}/METADATA +1 -1
- masster-0.4.1.dist-info/RECORD +67 -0
- masster-0.4.0.dist-info/RECORD +0 -67
- {masster-0.4.0.dist-info → masster-0.4.1.dist-info}/WHEEL +0 -0
- {masster-0.4.0.dist-info → masster-0.4.1.dist-info}/entry_points.txt +0 -0
- {masster-0.4.0.dist-info → masster-0.4.1.dist-info}/licenses/LICENSE +0 -0
masster/sample/load.py
CHANGED
|
@@ -47,10 +47,10 @@ import pyopenms as oms
|
|
|
47
47
|
|
|
48
48
|
from tqdm import tqdm
|
|
49
49
|
|
|
50
|
-
from
|
|
50
|
+
from masster.chromatogram import Chromatogram
|
|
51
51
|
|
|
52
52
|
# Parameters removed - using hardcoded defaults
|
|
53
|
-
from
|
|
53
|
+
from masster.spectrum import Spectrum
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
def load(
|
|
@@ -177,7 +177,7 @@ def load_study(
|
|
|
177
177
|
):
|
|
178
178
|
"""
|
|
179
179
|
Backward compatibility alias for load_noms1().
|
|
180
|
-
|
|
180
|
+
|
|
181
181
|
This method is deprecated. Use load_noms1() instead.
|
|
182
182
|
"""
|
|
183
183
|
return self.load_noms1(filename=filename, ondisk=ondisk, type=type, label=label)
|
|
@@ -263,16 +263,12 @@ def _load_mzML(
|
|
|
263
263
|
energy = None
|
|
264
264
|
else:
|
|
265
265
|
prec_mz = s.getPrecursors()[0].getMZ()
|
|
266
|
-
precursorIsolationWindowLowerMZ = s.getPrecursors()[
|
|
267
|
-
|
|
268
|
-
].getIsolationWindowLowerOffset()
|
|
269
|
-
precursorIsolationWindowUpperMZ = s.getPrecursors()[
|
|
270
|
-
0
|
|
271
|
-
].getIsolationWindowUpperOffset()
|
|
266
|
+
precursorIsolationWindowLowerMZ = s.getPrecursors()[0].getIsolationWindowLowerOffset()
|
|
267
|
+
precursorIsolationWindowUpperMZ = s.getPrecursors()[0].getIsolationWindowUpperOffset()
|
|
272
268
|
prec_intyensity = s.getPrecursors()[0].getIntensity()
|
|
273
269
|
# Try to get collision energy from meta values first, fallback to getActivationEnergy()
|
|
274
270
|
try:
|
|
275
|
-
energy = s.getPrecursors()[0].getMetaValue(
|
|
271
|
+
energy = s.getPrecursors()[0].getMetaValue('collision energy')
|
|
276
272
|
if energy is None or energy == 0.0:
|
|
277
273
|
energy = s.getPrecursors()[0].getActivationEnergy()
|
|
278
274
|
except Exception:
|
|
@@ -556,12 +552,12 @@ def _load_wiff(
|
|
|
556
552
|
filename=None,
|
|
557
553
|
):
|
|
558
554
|
try:
|
|
559
|
-
# Use
|
|
560
|
-
from
|
|
555
|
+
# Use masster's own implementation first
|
|
556
|
+
from masster.sample.sciex import SciexWiffData as MassterSciexWiffData
|
|
561
557
|
|
|
562
|
-
SciexWiffDataClass =
|
|
558
|
+
SciexWiffDataClass = MassterSciexWiffData
|
|
563
559
|
except ImportError:
|
|
564
|
-
# Fallback to alpharaw if
|
|
560
|
+
# Fallback to alpharaw if masster implementation fails
|
|
565
561
|
from alpharaw.sciex import SciexWiffData as AlpharawSciexWiffData
|
|
566
562
|
|
|
567
563
|
SciexWiffDataClass = AlpharawSciexWiffData
|
|
@@ -972,8 +968,8 @@ def index_file(self):
|
|
|
972
968
|
try:
|
|
973
969
|
from alpharaw.sciex import SciexWiffData
|
|
974
970
|
except ImportError:
|
|
975
|
-
# Fallback to
|
|
976
|
-
from
|
|
971
|
+
# Fallback to masster's own implementation
|
|
972
|
+
from masster.sample.sciex import SciexWiffData
|
|
977
973
|
|
|
978
974
|
raw_data = SciexWiffData(centroided=False)
|
|
979
975
|
raw_data.keep_k_peaks_per_spec = self.parameters.max_points_per_spectrum
|
|
@@ -989,9 +985,7 @@ def index_file(self):
|
|
|
989
985
|
self.logger.info("Index raw data...")
|
|
990
986
|
raw_data.import_raw(self.file_source)
|
|
991
987
|
self.file_obj = raw_data
|
|
992
|
-
elif os.path.exists(self.file_source) and self.file_source.lower().endswith(
|
|
993
|
-
".mzml",
|
|
994
|
-
):
|
|
988
|
+
elif os.path.exists(self.file_source) and self.file_source.lower().endswith(".mzml"):
|
|
995
989
|
self.file_interface = "oms"
|
|
996
990
|
omsexp: oms.OnDiscMSExperiment | oms.MSExperiment
|
|
997
991
|
if self.ondisk:
|
|
@@ -1001,9 +995,7 @@ def index_file(self):
|
|
|
1001
995
|
omsexp = oms.MSExperiment()
|
|
1002
996
|
oms.MzMLFile().load(self.file_source, omsexp)
|
|
1003
997
|
self.file_obj = omsexp
|
|
1004
|
-
elif os.path.exists(self.file_source) and self.file_source.lower().endswith(
|
|
1005
|
-
".sample5",
|
|
1006
|
-
):
|
|
998
|
+
elif os.path.exists(self.file_source) and self.file_source.lower().endswith(".sample5"):
|
|
1007
999
|
# this is an old save, try to see if
|
|
1008
1000
|
if os.path.exists(self.file_source.replace(".sample5", ".wiff")):
|
|
1009
1001
|
self.set_source(self.file_source.replace(".sample5", ".wiff"))
|
|
@@ -1017,9 +1009,7 @@ def index_file(self):
|
|
|
1017
1009
|
)
|
|
1018
1010
|
self.index_file()
|
|
1019
1011
|
else:
|
|
1020
|
-
raise FileNotFoundError(
|
|
1021
|
-
f"File {self.file_source} not found. Did the path change? Consider running source().",
|
|
1022
|
-
)
|
|
1012
|
+
raise FileNotFoundError(f"File {self.file_source} not found. Did the path change? Consider running source().")
|
|
1023
1013
|
|
|
1024
1014
|
|
|
1025
1015
|
def _load_ms2data(
|
|
@@ -1224,9 +1214,7 @@ def chrom_extract(
|
|
|
1224
1214
|
scan_uid = trace["scan_uid"]
|
|
1225
1215
|
# find all ms1 data with scan_uid and mz between q1-mz_tol and q1+mz_tol
|
|
1226
1216
|
d = self.ms1_df.filter(
|
|
1227
|
-
(pl.col("scan_uid").is_in(scan_uid))
|
|
1228
|
-
& (pl.col("mz") >= q1 - mz_tol)
|
|
1229
|
-
& (pl.col("mz") <= q1 + mz_tol),
|
|
1217
|
+
(pl.col("scan_uid").is_in(scan_uid)) & (pl.col("mz") >= q1 - mz_tol) & (pl.col("mz") <= q1 + mz_tol),
|
|
1230
1218
|
)
|
|
1231
1219
|
# for all unique rt values, find the maximum inty
|
|
1232
1220
|
eic_rt = d.group_by("rt").agg(pl.col("inty").max())
|
|
@@ -1245,9 +1233,7 @@ def chrom_extract(
|
|
|
1245
1233
|
scan_uid = trace["scan_uid"]
|
|
1246
1234
|
# find all ms2 data with scan_uid and mz between q3-mz_tol and q3+mz_tol
|
|
1247
1235
|
d = self.ms2data.filter(
|
|
1248
|
-
(pl.col("scan_uid").is_in(scan_uid))
|
|
1249
|
-
& (pl.col("mz") >= q3 - mz_tol)
|
|
1250
|
-
& (pl.col("mz") <= q3 + mz_tol),
|
|
1236
|
+
(pl.col("scan_uid").is_in(scan_uid)) & (pl.col("mz") >= q3 - mz_tol) & (pl.col("mz") <= q3 + mz_tol),
|
|
1251
1237
|
)
|
|
1252
1238
|
# for all unique rt values, find the maximum inty
|
|
1253
1239
|
eic_rt = d.group_by("rt").agg(pl.col("inty").max())
|
masster/sample/parameters.py
CHANGED
|
@@ -53,11 +53,7 @@ def get_parameters(self, keys):
|
|
|
53
53
|
if keys[0] == "sample":
|
|
54
54
|
if len(keys) == 1:
|
|
55
55
|
# Return the whole sample_defaults object as dict
|
|
56
|
-
return (
|
|
57
|
-
self.parameters.to_dict()
|
|
58
|
-
if hasattr(self.parameters, "to_dict")
|
|
59
|
-
else None
|
|
60
|
-
)
|
|
56
|
+
return self.parameters.to_dict() if hasattr(self.parameters, "to_dict") else None
|
|
61
57
|
else:
|
|
62
58
|
# Get specific parameter from sample_defaults object
|
|
63
59
|
param_name = keys[1]
|
|
@@ -89,7 +85,7 @@ def update_parameters(self, **kwargs):
|
|
|
89
85
|
- Individual parameter names and values (see sample_defaults for details)
|
|
90
86
|
"""
|
|
91
87
|
# Import here to avoid circular imports
|
|
92
|
-
from
|
|
88
|
+
from masster.sample.defaults.sample_def import (
|
|
93
89
|
sample_defaults as SampleDefaults,
|
|
94
90
|
)
|
|
95
91
|
|
masster/sample/plot.py
CHANGED
|
@@ -144,7 +144,7 @@ def _display_plot(plot_object, layout=None):
|
|
|
144
144
|
def _handle_sample_plot_output(self, plot_obj, filename=None, plot_type="bokeh"):
|
|
145
145
|
"""
|
|
146
146
|
Helper function to handle consistent save/display behavior for sample plots.
|
|
147
|
-
|
|
147
|
+
|
|
148
148
|
Parameters:
|
|
149
149
|
plot_obj: The plot object (bokeh figure, holoviews layout, or panel object)
|
|
150
150
|
filename: Optional filename to save the plot
|
|
@@ -153,24 +153,21 @@ def _handle_sample_plot_output(self, plot_obj, filename=None, plot_type="bokeh")
|
|
|
153
153
|
if filename is not None:
|
|
154
154
|
# Convert relative paths to absolute paths using sample folder as base
|
|
155
155
|
import os
|
|
156
|
-
|
|
157
|
-
if hasattr(self, "folder") and self.folder and not os.path.isabs(filename):
|
|
156
|
+
if hasattr(self, 'folder') and self.folder and not os.path.isabs(filename):
|
|
158
157
|
filename = os.path.join(self.folder, filename)
|
|
159
|
-
|
|
158
|
+
|
|
160
159
|
# Convert to absolute path for logging
|
|
161
160
|
abs_filename = os.path.abspath(filename)
|
|
162
|
-
|
|
161
|
+
|
|
163
162
|
if filename.endswith(".html"):
|
|
164
163
|
if plot_type == "panel":
|
|
165
164
|
plot_obj.save(filename, embed=True) # type: ignore[attr-defined]
|
|
166
165
|
elif plot_type == "holoviews":
|
|
167
166
|
import panel
|
|
168
|
-
|
|
169
167
|
panel.panel(plot_obj).save(filename, embed=True) # type: ignore[attr-defined]
|
|
170
168
|
elif plot_type == "bokeh":
|
|
171
169
|
from bokeh.plotting import output_file
|
|
172
170
|
from bokeh.io import save
|
|
173
|
-
|
|
174
171
|
output_file(filename)
|
|
175
172
|
save(plot_obj)
|
|
176
173
|
self.logger.info(f"Plot saved to: {abs_filename}")
|
|
@@ -178,75 +175,61 @@ def _handle_sample_plot_output(self, plot_obj, filename=None, plot_type="bokeh")
|
|
|
178
175
|
try:
|
|
179
176
|
if plot_type == "bokeh":
|
|
180
177
|
from bokeh.io.export import export_png
|
|
181
|
-
|
|
182
178
|
export_png(plot_obj, filename=filename)
|
|
183
179
|
elif plot_type in ["panel", "holoviews"]:
|
|
184
180
|
import holoviews as hv
|
|
185
|
-
|
|
186
181
|
hv.save(plot_obj, filename, fmt="png")
|
|
187
182
|
self.logger.info(f"Plot saved to: {abs_filename}")
|
|
188
183
|
except Exception:
|
|
189
184
|
# Fall back to HTML if PNG export not available
|
|
190
|
-
html_filename = filename.replace(
|
|
185
|
+
html_filename = filename.replace('.png', '.html')
|
|
191
186
|
abs_html_filename = os.path.abspath(html_filename)
|
|
192
187
|
if plot_type == "panel":
|
|
193
188
|
plot_obj.save(html_filename, embed=True) # type: ignore[attr-defined]
|
|
194
189
|
elif plot_type == "holoviews":
|
|
195
190
|
import panel
|
|
196
|
-
|
|
197
191
|
panel.panel(plot_obj).save(html_filename, embed=True) # type: ignore[attr-defined]
|
|
198
192
|
elif plot_type == "bokeh":
|
|
199
193
|
from bokeh.plotting import output_file
|
|
200
194
|
from bokeh.io import save
|
|
201
|
-
|
|
202
195
|
output_file(html_filename)
|
|
203
196
|
save(plot_obj)
|
|
204
|
-
self.logger.warning(
|
|
205
|
-
f"PNG export not available, saved as HTML instead: {abs_html_filename}",
|
|
206
|
-
)
|
|
197
|
+
self.logger.warning(f"PNG export not available, saved as HTML instead: {abs_html_filename}")
|
|
207
198
|
elif filename.endswith(".pdf"):
|
|
208
199
|
# Try to save as PDF, fall back to HTML if not available
|
|
209
200
|
try:
|
|
210
201
|
if plot_type == "bokeh":
|
|
211
202
|
from bokeh.io.export import export_pdf
|
|
212
|
-
|
|
213
203
|
export_pdf(plot_obj, filename=filename)
|
|
214
204
|
elif plot_type in ["panel", "holoviews"]:
|
|
215
205
|
import holoviews as hv
|
|
216
|
-
|
|
217
206
|
hv.save(plot_obj, filename, fmt="pdf")
|
|
218
207
|
self.logger.info(f"Plot saved to: {abs_filename}")
|
|
219
208
|
except ImportError:
|
|
220
209
|
# Fall back to HTML if PDF export not available
|
|
221
|
-
html_filename = filename.replace(
|
|
210
|
+
html_filename = filename.replace('.pdf', '.html')
|
|
222
211
|
abs_html_filename = os.path.abspath(html_filename)
|
|
223
212
|
if plot_type == "panel":
|
|
224
213
|
plot_obj.save(html_filename, embed=True) # type: ignore[attr-defined]
|
|
225
214
|
elif plot_type == "holoviews":
|
|
226
215
|
import panel
|
|
227
|
-
|
|
228
216
|
panel.panel(plot_obj).save(html_filename, embed=True) # type: ignore[attr-defined]
|
|
229
217
|
elif plot_type == "bokeh":
|
|
230
218
|
from bokeh.plotting import output_file
|
|
231
219
|
from bokeh.io import save
|
|
232
|
-
|
|
233
220
|
output_file(html_filename)
|
|
234
221
|
save(plot_obj)
|
|
235
|
-
self.logger.warning(
|
|
236
|
-
f"PDF export not available, saved as HTML instead: {abs_html_filename}",
|
|
237
|
-
)
|
|
222
|
+
self.logger.warning(f"PDF export not available, saved as HTML instead: {abs_html_filename}")
|
|
238
223
|
else:
|
|
239
224
|
# Default to HTML for unknown extensions
|
|
240
225
|
if plot_type == "panel":
|
|
241
226
|
plot_obj.save(filename, embed=True) # type: ignore[attr-defined]
|
|
242
227
|
elif plot_type == "holoviews":
|
|
243
228
|
import panel
|
|
244
|
-
|
|
245
229
|
panel.panel(plot_obj).save(filename, embed=True) # type: ignore[attr-defined]
|
|
246
230
|
elif plot_type == "bokeh":
|
|
247
231
|
from bokeh.plotting import output_file
|
|
248
232
|
from bokeh.io import save
|
|
249
|
-
|
|
250
233
|
output_file(filename)
|
|
251
234
|
save(plot_obj)
|
|
252
235
|
self.logger.info(f"Plot saved to: {abs_filename}")
|
|
@@ -256,11 +239,9 @@ def _handle_sample_plot_output(self, plot_obj, filename=None, plot_type="bokeh")
|
|
|
256
239
|
plot_obj.show() # type: ignore[attr-defined]
|
|
257
240
|
elif plot_type == "holoviews":
|
|
258
241
|
import panel
|
|
259
|
-
|
|
260
242
|
return panel.panel(plot_obj)
|
|
261
243
|
elif plot_type == "bokeh":
|
|
262
244
|
from bokeh.plotting import show
|
|
263
|
-
|
|
264
245
|
show(plot_obj)
|
|
265
246
|
|
|
266
247
|
|
|
@@ -318,9 +299,7 @@ def plot_chrom(
|
|
|
318
299
|
if isinstance(feature_uids, int):
|
|
319
300
|
feature_uids = [feature_uids]
|
|
320
301
|
# select only the features with feature_uid in feature_uids
|
|
321
|
-
feats = self.features_df[
|
|
322
|
-
self.features_df["feature_uid"].is_in(feature_uids)
|
|
323
|
-
].clone()
|
|
302
|
+
feats = self.features_df[self.features_df["feature_uid"].is_in(feature_uids)].clone()
|
|
324
303
|
|
|
325
304
|
# make sure feature_uid is a list of integers
|
|
326
305
|
|
|
@@ -396,7 +375,7 @@ def plot_chrom(
|
|
|
396
375
|
|
|
397
376
|
layout = layout.cols(1)
|
|
398
377
|
layout = panel.Column(layout)
|
|
399
|
-
|
|
378
|
+
|
|
400
379
|
# Use consistent save/display behavior
|
|
401
380
|
self._handle_sample_plot_output(layout, filename, "panel")
|
|
402
381
|
|
|
@@ -494,13 +473,9 @@ def plot_2d(
|
|
|
494
473
|
# keep only rt, mz, and inty
|
|
495
474
|
spectradf = spectradf.select(["rt", "mz", "inty"])
|
|
496
475
|
if mz_range is not None:
|
|
497
|
-
spectradf = spectradf.filter(
|
|
498
|
-
(pl.col("mz") >= mz_range[0]) & (pl.col("mz") <= mz_range[1]),
|
|
499
|
-
)
|
|
476
|
+
spectradf = spectradf.filter((pl.col("mz") >= mz_range[0]) & (pl.col("mz") <= mz_range[1]))
|
|
500
477
|
if rt_range is not None:
|
|
501
|
-
spectradf = spectradf.filter(
|
|
502
|
-
(pl.col("rt") >= rt_range[0]) & (pl.col("rt") <= rt_range[1]),
|
|
503
|
-
)
|
|
478
|
+
spectradf = spectradf.filter((pl.col("rt") >= rt_range[0]) & (pl.col("rt") <= rt_range[1]))
|
|
504
479
|
maxrt = spectradf["rt"].max()
|
|
505
480
|
minrt = spectradf["rt"].min()
|
|
506
481
|
maxmz = spectradf["mz"].max()
|
|
@@ -532,11 +507,7 @@ def plot_2d(
|
|
|
532
507
|
def dynamic_sizing_hook(plot, element):
|
|
533
508
|
"""Hook to convert size-based markers to radius-based for dynamic behavior"""
|
|
534
509
|
try:
|
|
535
|
-
if (
|
|
536
|
-
use_dynamic_sizing
|
|
537
|
-
and hasattr(plot, "state")
|
|
538
|
-
and hasattr(plot.state, "renderers")
|
|
539
|
-
):
|
|
510
|
+
if use_dynamic_sizing and hasattr(plot, "state") and hasattr(plot.state, "renderers"):
|
|
540
511
|
from bokeh.models import Circle
|
|
541
512
|
|
|
542
513
|
for renderer in plot.state.renderers:
|
|
@@ -847,38 +818,20 @@ def plot_2d(
|
|
|
847
818
|
|
|
848
819
|
if feature_points_4 is not None:
|
|
849
820
|
updated_points_4 = feature_points_4.opts(size=size_val)
|
|
850
|
-
feature_overlay =
|
|
851
|
-
updated_points_4
|
|
852
|
-
if feature_overlay is None
|
|
853
|
-
else feature_overlay * updated_points_4
|
|
854
|
-
)
|
|
821
|
+
feature_overlay = updated_points_4 if feature_overlay is None else feature_overlay * updated_points_4
|
|
855
822
|
if feature_points_3 is not None:
|
|
856
823
|
updated_points_3 = feature_points_3.opts(size=size_val)
|
|
857
|
-
feature_overlay =
|
|
858
|
-
updated_points_3
|
|
859
|
-
if feature_overlay is None
|
|
860
|
-
else feature_overlay * updated_points_3
|
|
861
|
-
)
|
|
824
|
+
feature_overlay = updated_points_3 if feature_overlay is None else feature_overlay * updated_points_3
|
|
862
825
|
if feature_points_1 is not None:
|
|
863
826
|
updated_points_1 = feature_points_1.opts(size=size_val)
|
|
864
|
-
feature_overlay =
|
|
865
|
-
updated_points_1
|
|
866
|
-
if feature_overlay is None
|
|
867
|
-
else feature_overlay * updated_points_1
|
|
868
|
-
)
|
|
827
|
+
feature_overlay = updated_points_1 if feature_overlay is None else feature_overlay * updated_points_1
|
|
869
828
|
if not show_only_features_with_ms2 and feature_points_2 is not None:
|
|
870
829
|
updated_points_2 = feature_points_2.opts(size=size_val)
|
|
871
|
-
feature_overlay =
|
|
872
|
-
updated_points_2
|
|
873
|
-
if feature_overlay is None
|
|
874
|
-
else feature_overlay * updated_points_2
|
|
875
|
-
)
|
|
830
|
+
feature_overlay = updated_points_2 if feature_overlay is None else feature_overlay * updated_points_2
|
|
876
831
|
if feature_points_iso is not None:
|
|
877
832
|
updated_points_iso = feature_points_iso.opts(size=size_val)
|
|
878
833
|
feature_overlay = (
|
|
879
|
-
updated_points_iso
|
|
880
|
-
if feature_overlay is None
|
|
881
|
-
else feature_overlay * updated_points_iso
|
|
834
|
+
updated_points_iso if feature_overlay is None else feature_overlay * updated_points_iso
|
|
882
835
|
)
|
|
883
836
|
|
|
884
837
|
# Combine with the static raster background
|
|
@@ -908,12 +861,7 @@ def plot_2d(
|
|
|
908
861
|
|
|
909
862
|
# Create the slider widget row with clear styling
|
|
910
863
|
slider_widget = on.Row(
|
|
911
|
-
on.pane.HTML(
|
|
912
|
-
"<b>Marker Size Control:</b>",
|
|
913
|
-
width=150,
|
|
914
|
-
height=40,
|
|
915
|
-
margin=(5, 10),
|
|
916
|
-
),
|
|
864
|
+
on.pane.HTML("<b>Marker Size Control:</b>", width=150, height=40, margin=(5, 10)),
|
|
917
865
|
size_slider,
|
|
918
866
|
height=60,
|
|
919
867
|
margin=10,
|
|
@@ -979,7 +927,7 @@ def plot_2d(
|
|
|
979
927
|
layout = panel.Column(overlay)
|
|
980
928
|
|
|
981
929
|
if filename is not None:
|
|
982
|
-
# Use consistent save/display behavior
|
|
930
|
+
# Use consistent save/display behavior
|
|
983
931
|
self._handle_sample_plot_output(layout, filename, "panel")
|
|
984
932
|
return None
|
|
985
933
|
else:
|
|
@@ -1060,13 +1008,9 @@ def plot_2d_oracle(
|
|
|
1060
1008
|
# keep only rt, mz, and inty
|
|
1061
1009
|
spectradf = spectradf[["rt", "mz", "inty"]]
|
|
1062
1010
|
if mz_range is not None:
|
|
1063
|
-
spectradf = spectradf[
|
|
1064
|
-
(spectradf["mz"] >= mz_range[0]) & (spectradf["mz"] <= mz_range[1])
|
|
1065
|
-
]
|
|
1011
|
+
spectradf = spectradf[(spectradf["mz"] >= mz_range[0]) & (spectradf["mz"] <= mz_range[1])]
|
|
1066
1012
|
if rt_range is not None:
|
|
1067
|
-
spectradf = spectradf[
|
|
1068
|
-
(spectradf["rt"] >= rt_range[0]) & (spectradf["rt"] <= rt_range[1])
|
|
1069
|
-
]
|
|
1013
|
+
spectradf = spectradf[(spectradf["rt"] >= rt_range[0]) & (spectradf["rt"] <= rt_range[1])]
|
|
1070
1014
|
|
|
1071
1015
|
maxrt = spectradf["rt"].max()
|
|
1072
1016
|
minrt = spectradf["rt"].min()
|
|
@@ -1189,8 +1133,7 @@ def plot_2d_oracle(
|
|
|
1189
1133
|
# iterate over the rows and find the feature_uid in feats by looking at the closest rt and mz
|
|
1190
1134
|
for i, row in oracle_data.iterrows():
|
|
1191
1135
|
candidates = feats[
|
|
1192
|
-
(abs(feats["rt"] - row["rt"]) < 1)
|
|
1193
|
-
& (abs(feats["mz"] - row["precursor"]) < 0.005)
|
|
1136
|
+
(abs(feats["rt"] - row["rt"]) < 1) & (abs(feats["mz"] - row["precursor"]) < 0.005)
|
|
1194
1137
|
].copy()
|
|
1195
1138
|
if len(candidates) > 0:
|
|
1196
1139
|
# sort by delta rt
|
|
@@ -1236,9 +1179,7 @@ def plot_2d_oracle(
|
|
|
1236
1179
|
cmap_provider = "colorcet"
|
|
1237
1180
|
cm = process_cmap(cmap, ncolors=num_colors, provider=cmap_provider)
|
|
1238
1181
|
colors = [
|
|
1239
|
-
rgb2hex(cm[int(i * (len(cm) - 1) / (num_colors - 1))])
|
|
1240
|
-
if num_colors > 1
|
|
1241
|
-
else rgb2hex(cm[0])
|
|
1182
|
+
rgb2hex(cm[int(i * (len(cm) - 1) / (num_colors - 1))]) if num_colors > 1 else rgb2hex(cm[0])
|
|
1242
1183
|
for i in range(num_colors)
|
|
1243
1184
|
]
|
|
1244
1185
|
# assign color to each row based on id_class. If id_class is null, assign 'black'
|
|
@@ -1868,9 +1809,7 @@ def plot_ms2_q1(
|
|
|
1868
1809
|
scans = self.scans_df.filter(pl.col("cycle") == cycle)
|
|
1869
1810
|
scans = scans.filter(pl.col("ms_level") == 2)
|
|
1870
1811
|
# find the scan in cycle whose 'prec_mz' is the closest to the feature['mz']
|
|
1871
|
-
scan_uid = scans[(scans["prec_mz"] - feature["mz"]).abs().arg_sort()[:1]][
|
|
1872
|
-
"scan_uid"
|
|
1873
|
-
][0]
|
|
1812
|
+
scan_uid = scans[(scans["prec_mz"] - feature["mz"]).abs().arg_sort()[:1]]["scan_uid"][0]
|
|
1874
1813
|
# get q1_width scans before and after the scan_uid
|
|
1875
1814
|
scans = self.scans_df.filter(pl.col("scan_uid") >= scan_uid - q1_width)
|
|
1876
1815
|
scans = scans.filter(pl.col("scan_uid") <= scan_uid + q1_width)
|
|
@@ -2134,7 +2073,7 @@ def plot_tic(
|
|
|
2134
2073
|
return
|
|
2135
2074
|
|
|
2136
2075
|
# Import helper locally to avoid circular imports
|
|
2137
|
-
from
|
|
2076
|
+
from masster.study.helpers import get_tic
|
|
2138
2077
|
|
|
2139
2078
|
# Delegate TIC computation to study helper which handles ms1_df and scans_df fallbacks
|
|
2140
2079
|
try:
|
|
@@ -2189,7 +2128,7 @@ def plot_bpc(
|
|
|
2189
2128
|
return
|
|
2190
2129
|
|
|
2191
2130
|
# Import helper locally to avoid circular imports
|
|
2192
|
-
from
|
|
2131
|
+
from masster.study.helpers import get_bpc
|
|
2193
2132
|
|
|
2194
2133
|
# Delegate BPC computation to study helper
|
|
2195
2134
|
try:
|