masster 0.2.4__py3-none-any.whl → 0.3.0__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.

Potentially problematic release.


This version of masster might be problematic. Click here for more details.

Files changed (55) hide show
  1. masster/__init__.py +27 -27
  2. masster/_version.py +17 -17
  3. masster/chromatogram.py +497 -503
  4. masster/data/examples/2025_01_14_VW_7600_LpMx_DBS_CID_2min_TOP15_030msecMS1_005msecReac_CE35_DBS-ON_3.featureXML +199787 -0
  5. masster/data/examples/2025_01_14_VW_7600_LpMx_DBS_CID_2min_TOP15_030msecMS1_005msecReac_CE35_DBS-ON_3.sample5 +0 -0
  6. masster/logger.py +318 -244
  7. masster/sample/__init__.py +9 -9
  8. masster/sample/defaults/__init__.py +15 -15
  9. masster/sample/defaults/find_adducts_def.py +325 -325
  10. masster/sample/defaults/find_features_def.py +366 -366
  11. masster/sample/defaults/find_ms2_def.py +285 -285
  12. masster/sample/defaults/get_spectrum_def.py +314 -318
  13. masster/sample/defaults/sample_def.py +374 -378
  14. masster/sample/h5.py +1321 -1297
  15. masster/sample/helpers.py +833 -364
  16. masster/sample/lib.py +762 -0
  17. masster/sample/load.py +1220 -1187
  18. masster/sample/parameters.py +131 -131
  19. masster/sample/plot.py +1610 -1622
  20. masster/sample/processing.py +1402 -1416
  21. masster/sample/quant.py +209 -0
  22. masster/sample/sample.py +391 -387
  23. masster/sample/sample5_schema.json +181 -181
  24. masster/sample/save.py +737 -719
  25. masster/sample/sciex.py +1213 -0
  26. masster/spectrum.py +1287 -1319
  27. masster/study/__init__.py +9 -9
  28. masster/study/defaults/__init__.py +21 -19
  29. masster/study/defaults/align_def.py +267 -267
  30. masster/study/defaults/export_def.py +41 -40
  31. masster/study/defaults/fill_chrom_def.py +264 -264
  32. masster/study/defaults/fill_def.py +260 -0
  33. masster/study/defaults/find_consensus_def.py +256 -256
  34. masster/study/defaults/find_ms2_def.py +163 -163
  35. masster/study/defaults/integrate_chrom_def.py +225 -225
  36. masster/study/defaults/integrate_def.py +221 -0
  37. masster/study/defaults/merge_def.py +256 -0
  38. masster/study/defaults/study_def.py +272 -269
  39. masster/study/export.py +674 -287
  40. masster/study/h5.py +1398 -886
  41. masster/study/helpers.py +1650 -433
  42. masster/study/helpers_optimized.py +317 -0
  43. masster/study/load.py +1201 -1078
  44. masster/study/parameters.py +99 -99
  45. masster/study/plot.py +632 -645
  46. masster/study/processing.py +1057 -1046
  47. masster/study/save.py +149 -134
  48. masster/study/study.py +606 -522
  49. masster/study/study5_schema.json +247 -241
  50. {masster-0.2.4.dist-info → masster-0.3.0.dist-info}/METADATA +15 -10
  51. masster-0.3.0.dist-info/RECORD +59 -0
  52. {masster-0.2.4.dist-info → masster-0.3.0.dist-info}/licenses/LICENSE +661 -661
  53. masster-0.2.4.dist-info/RECORD +0 -50
  54. {masster-0.2.4.dist-info → masster-0.3.0.dist-info}/WHEEL +0 -0
  55. {masster-0.2.4.dist-info → masster-0.3.0.dist-info}/entry_points.txt +0 -0
@@ -1,325 +1,325 @@
1
- """
2
- Find Adducts Parameters Module
3
-
4
- This module defines parameters for adduct detection in mass spectrometry data.
5
- It consolidates all parameters used in the find_adducts() method with type checking,
6
- validation, and comprehensive descriptions.
7
-
8
- Classes:
9
- find_adducts_defaults: Configuration parameters for the find_adducts() method.
10
- """
11
-
12
- from __future__ import annotations
13
-
14
- from dataclasses import dataclass, field
15
- from typing import Any
16
-
17
-
18
- @dataclass
19
- class find_adducts_defaults:
20
- """
21
- Parameters for mass spectrometry adduct detection using OpenMS MetaboliteFeatureDeconvolution.
22
-
23
- This class consolidates all parameters used in the find_adducts() method including
24
- potential adducts, charge constraints, and retention time tolerances.
25
- It provides type checking, validation, and comprehensive parameter descriptions.
26
-
27
- Adduct Detection Parameters:
28
- adducts: List of potential adducts or ionization mode string.
29
- charge_min: Minimal possible charge state.
30
- charge_max: Maximal possible charge state.
31
- charge_span_max: Maximum span between different charge states.
32
- retention_max_diff: Maximum retention time difference for adduct grouping.
33
- retention_max_diff_local: Maximum local retention time difference.
34
-
35
- Available Methods:
36
- - validate(param_name, value): Validate a single parameter value
37
- - validate_all(): Validate all parameters at once
38
- - to_dict(): Convert parameters to dictionary
39
- - set_from_dict(param_dict, validate=True): Update multiple parameters from dict
40
- - set(param_name, value, validate=True): Set parameter value with validation
41
- - get(param_name): Get parameter value
42
- - get_description(param_name): Get parameter description
43
- - get_info(param_name): Get full parameter metadata
44
- - list_parameters(): Get list of all parameter names
45
- - get_openms_adducts(): Get processed adducts list for OpenMS
46
- """
47
-
48
- # Adduct specification
49
- adducts: list[str] | str | None = None
50
-
51
- # Charge constraints
52
- charge_min: int = 1
53
- charge_max: int = 2
54
- charge_span_max: int = 2
55
-
56
- # Retention time constraints
57
- retention_max_diff: float = 1.0
58
- retention_max_diff_local: float = 1.0
59
-
60
- # Parameter metadata for validation and description
61
- _param_metadata: dict[str, dict[str, Any]] = field(
62
- default_factory=lambda: {
63
- "adducts": {
64
- "dtype": "Union[List[str], str, None]",
65
- "description": "List of potential adducts or ionization mode ('pos', 'neg', 'positive', 'negative')",
66
- "allowed_values": ["pos", "neg", "positive", "negative"],
67
- },
68
- "charge_min": {
69
- "dtype": int,
70
- "description": "Minimal possible charge state for adduct detection",
71
- "min_value": 1,
72
- "max_value": 10,
73
- },
74
- "charge_max": {
75
- "dtype": int,
76
- "description": "Maximal possible charge state for adduct detection",
77
- "min_value": 1,
78
- "max_value": 10,
79
- },
80
- "charge_span_max": {
81
- "dtype": int,
82
- "description": "Maximum span between different charge states in the same adduct group",
83
- "min_value": 1,
84
- "max_value": 5,
85
- },
86
- "retention_max_diff": {
87
- "dtype": float,
88
- "description": "Maximum retention time difference (in minutes) for global adduct grouping",
89
- "min_value": 0.1,
90
- "max_value": 10.0,
91
- },
92
- "retention_max_diff_local": {
93
- "dtype": float,
94
- "description": "Maximum local retention time difference (in minutes) for adduct grouping",
95
- "min_value": 0.1,
96
- "max_value": 10.0,
97
- },
98
- },
99
- )
100
-
101
- def get_info(self, param_name: str) -> dict[str, Any]:
102
- """
103
- Get information about a specific parameter.
104
-
105
- Args:
106
- param_name: Name of the parameter
107
-
108
- Returns:
109
- Dictionary containing parameter metadata
110
-
111
- Raises:
112
- KeyError: If parameter name is not found
113
- """
114
- if param_name not in self._param_metadata:
115
- raise KeyError(f"Parameter '{param_name}' not found")
116
- return self._param_metadata[param_name]
117
-
118
- def get_description(self, param_name: str) -> str:
119
- """
120
- Get description for a specific parameter.
121
-
122
- Args:
123
- param_name: Name of the parameter
124
-
125
- Returns:
126
- Parameter description string
127
- """
128
- return str(self.get_info(param_name)["description"])
129
-
130
- def validate(self, param_name: str, value: Any) -> bool:
131
- """
132
- Validate a parameter value against its constraints.
133
-
134
- Args:
135
- param_name: Name of the parameter
136
- value: Value to validate
137
-
138
- Returns:
139
- True if value is valid, False otherwise
140
- """
141
- if param_name not in self._param_metadata:
142
- return False
143
-
144
- metadata = self._param_metadata[param_name]
145
- expected_dtype = metadata["dtype"]
146
-
147
- # Handle Union types for adducts parameter
148
- if param_name == "adducts":
149
- if value is None:
150
- return True
151
- if isinstance(value, str):
152
- # Check if it's a valid ionization mode
153
- allowed_values = metadata.get("allowed_values", [])
154
- return value in allowed_values
155
- elif isinstance(value, list):
156
- # Check if all elements are strings
157
- return all(isinstance(item, str) for item in value)
158
- else:
159
- return False
160
-
161
- # Type checking for non-Union types
162
- if expected_dtype is int:
163
- if not isinstance(value, int):
164
- try:
165
- value = int(value)
166
- except (ValueError, TypeError):
167
- return False
168
- elif expected_dtype is float:
169
- if not isinstance(value, (int, float)):
170
- try:
171
- value = float(value)
172
- except (ValueError, TypeError):
173
- return False
174
-
175
- # Range validation for numeric types
176
- if expected_dtype in (int, float):
177
- if "min_value" in metadata and value < metadata["min_value"]:
178
- return False
179
- if "max_value" in metadata and value > metadata["max_value"]:
180
- return False
181
-
182
- return True
183
-
184
- def set(self, param_name: str, value: Any, validate: bool = True) -> bool:
185
- """
186
- Set a parameter value with optional validation.
187
-
188
- Args:
189
- param_name: Name of the parameter
190
- value: New value for the parameter
191
- validate: Whether to validate the value before setting
192
-
193
- Returns:
194
- True if parameter was set successfully, False otherwise
195
- """
196
- if not hasattr(self, param_name):
197
- return False
198
-
199
- if validate and not self.validate(param_name, value):
200
- return False
201
-
202
- # Convert to expected type if needed
203
- if param_name in self._param_metadata:
204
- expected_dtype = self._param_metadata[param_name]["dtype"]
205
- if expected_dtype is int and not isinstance(value, int):
206
- try:
207
- value = int(value)
208
- except (ValueError, TypeError):
209
- if validate:
210
- return False
211
- elif expected_dtype is float and not isinstance(value, float):
212
- try:
213
- value = float(value)
214
- except (ValueError, TypeError):
215
- if validate:
216
- return False
217
-
218
- setattr(self, param_name, value)
219
-
220
- # Trigger dynamic calculation if this is the adducts parameter
221
- if param_name == "adducts":
222
- self._update_openms_adducts()
223
-
224
- return True
225
-
226
- def get(self, param_name: str) -> Any:
227
- """
228
- Get the value of a parameter by name.
229
-
230
- Args:
231
- param_name: Name of the parameter
232
-
233
- Returns:
234
- Current value of the parameter
235
- """
236
- if not hasattr(self, param_name):
237
- raise KeyError(f"Parameter '{param_name}' not found")
238
- return getattr(self, param_name)
239
-
240
- def set_from_dict(
241
- self,
242
- param_dict: dict[str, Any],
243
- validate: bool = True,
244
- ) -> list[str]:
245
- """
246
- Update multiple parameters from a dictionary.
247
-
248
- Args:
249
- param_dict: Dictionary of parameter names and values
250
- validate: Whether to validate values before setting
251
-
252
- Returns:
253
- List of parameter names that could not be set
254
- """
255
- failed_params = []
256
-
257
- for param_name, value in param_dict.items():
258
- if not self.set(param_name, value, validate):
259
- failed_params.append(param_name)
260
-
261
- return failed_params
262
-
263
- def to_dict(self) -> dict[str, Any]:
264
- """
265
- Convert parameters to dictionary, excluding metadata.
266
-
267
- Returns:
268
- Dictionary of parameter names and values
269
- """
270
- return {k: v for k, v in self.__dict__.items() if not k.startswith("_")}
271
-
272
- def list_parameters(self) -> list[str]:
273
- """
274
- Get list of all parameter names.
275
-
276
- Returns:
277
- List of parameter names
278
- """
279
- return [k for k in self.__dict__.keys() if not k.startswith("_")]
280
-
281
- def validate_all(self) -> tuple[bool, list[str]]:
282
- """
283
- Validate all parameters in the instance.
284
-
285
- Returns:
286
- Tuple of (all_valid, list_of_invalid_params)
287
- - all_valid: True if all parameters are valid, False otherwise
288
- - list_of_invalid_params: List of parameter names that failed validation
289
- """
290
- invalid_params = []
291
-
292
- for param_name in self.list_parameters():
293
- if param_name in self._param_metadata:
294
- current_value = getattr(self, param_name)
295
- if not self.validate(param_name, current_value):
296
- invalid_params.append(param_name)
297
-
298
- return len(invalid_params) == 0, invalid_params
299
-
300
- def _update_openms_adducts(self) -> None:
301
- """
302
- Update the internal OpenMS adducts list when adducts parameter changes.
303
- This is called automatically when the adducts parameter is set.
304
- """
305
- # This will update the internal state that get_openms_adducts() uses
306
- pass
307
-
308
- def get_openms_adducts(self) -> list[str]:
309
- """
310
- Get the processed adducts list for OpenMS MetaboliteFeatureDeconvolution.
311
-
312
- Returns:
313
- List of adduct strings formatted for OpenMS
314
- """
315
- adducts = self.adducts
316
-
317
- if adducts is None or adducts in ["pos", "positive"]:
318
- return ["H:+:0.4", "Na:+:0.3", "NH4:+:0.3"]
319
- elif adducts in ["neg", "negative"]:
320
- return ["H-1:-:1", "CH2O2:0:0.5"]
321
- elif isinstance(adducts, list):
322
- return adducts
323
- else:
324
- # Fallback to positive mode if unexpected format
325
- return ["H:+:0.4", "Na:+:0.3", "NH4:+:0.3"]
1
+ """
2
+ Find Adducts Parameters Module
3
+
4
+ This module defines parameters for adduct detection in mass spectrometry data.
5
+ It consolidates all parameters used in the find_adducts() method with type checking,
6
+ validation, and comprehensive descriptions.
7
+
8
+ Classes:
9
+ find_adducts_defaults: Configuration parameters for the find_adducts() method.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from dataclasses import dataclass, field
15
+ from typing import Any
16
+
17
+
18
+ @dataclass
19
+ class find_adducts_defaults:
20
+ """
21
+ Parameters for mass spectrometry adduct detection using OpenMS MetaboliteFeatureDeconvolution.
22
+
23
+ This class consolidates all parameters used in the find_adducts() method including
24
+ potential adducts, charge constraints, and retention time tolerances.
25
+ It provides type checking, validation, and comprehensive parameter descriptions.
26
+
27
+ Adduct Detection Parameters:
28
+ adducts: List of potential adducts or ionization mode string.
29
+ charge_min: Minimal possible charge state.
30
+ charge_max: Maximal possible charge state.
31
+ charge_span_max: Maximum span between different charge states.
32
+ retention_max_diff: Maximum retention time difference for adduct grouping.
33
+ retention_max_diff_local: Maximum local retention time difference.
34
+
35
+ Available Methods:
36
+ - validate(param_name, value): Validate a single parameter value
37
+ - validate_all(): Validate all parameters at once
38
+ - to_dict(): Convert parameters to dictionary
39
+ - set_from_dict(param_dict, validate=True): Update multiple parameters from dict
40
+ - set(param_name, value, validate=True): Set parameter value with validation
41
+ - get(param_name): Get parameter value
42
+ - get_description(param_name): Get parameter description
43
+ - get_info(param_name): Get full parameter metadata
44
+ - list_parameters(): Get list of all parameter names
45
+ - get_openms_adducts(): Get processed adducts list for OpenMS
46
+ """
47
+
48
+ # Adduct specification
49
+ adducts: list[str] | str | None = None
50
+
51
+ # Charge constraints
52
+ charge_min: int = 1
53
+ charge_max: int = 2
54
+ charge_span_max: int = 2
55
+
56
+ # Retention time constraints
57
+ retention_max_diff: float = 1.0
58
+ retention_max_diff_local: float = 1.0
59
+
60
+ # Parameter metadata for validation and description
61
+ _param_metadata: dict[str, dict[str, Any]] = field(
62
+ default_factory=lambda: {
63
+ "adducts": {
64
+ "dtype": "Union[List[str], str, None]",
65
+ "description": "List of potential adducts or ionization mode ('pos', 'neg', 'positive', 'negative')",
66
+ "allowed_values": ["pos", "neg", "positive", "negative"],
67
+ },
68
+ "charge_min": {
69
+ "dtype": int,
70
+ "description": "Minimal possible charge state for adduct detection",
71
+ "min_value": 1,
72
+ "max_value": 10,
73
+ },
74
+ "charge_max": {
75
+ "dtype": int,
76
+ "description": "Maximal possible charge state for adduct detection",
77
+ "min_value": 1,
78
+ "max_value": 10,
79
+ },
80
+ "charge_span_max": {
81
+ "dtype": int,
82
+ "description": "Maximum span between different charge states in the same adduct group",
83
+ "min_value": 1,
84
+ "max_value": 5,
85
+ },
86
+ "retention_max_diff": {
87
+ "dtype": float,
88
+ "description": "Maximum retention time difference (in minutes) for global adduct grouping",
89
+ "min_value": 0.1,
90
+ "max_value": 10.0,
91
+ },
92
+ "retention_max_diff_local": {
93
+ "dtype": float,
94
+ "description": "Maximum local retention time difference (in minutes) for adduct grouping",
95
+ "min_value": 0.1,
96
+ "max_value": 10.0,
97
+ },
98
+ },
99
+ )
100
+
101
+ def get_info(self, param_name: str) -> dict[str, Any]:
102
+ """
103
+ Get information about a specific parameter.
104
+
105
+ Args:
106
+ param_name: Name of the parameter
107
+
108
+ Returns:
109
+ Dictionary containing parameter metadata
110
+
111
+ Raises:
112
+ KeyError: If parameter name is not found
113
+ """
114
+ if param_name not in self._param_metadata:
115
+ raise KeyError(f"Parameter '{param_name}' not found")
116
+ return self._param_metadata[param_name]
117
+
118
+ def get_description(self, param_name: str) -> str:
119
+ """
120
+ Get description for a specific parameter.
121
+
122
+ Args:
123
+ param_name: Name of the parameter
124
+
125
+ Returns:
126
+ Parameter description string
127
+ """
128
+ return str(self.get_info(param_name)["description"])
129
+
130
+ def validate(self, param_name: str, value: Any) -> bool:
131
+ """
132
+ Validate a parameter value against its constraints.
133
+
134
+ Args:
135
+ param_name: Name of the parameter
136
+ value: Value to validate
137
+
138
+ Returns:
139
+ True if value is valid, False otherwise
140
+ """
141
+ if param_name not in self._param_metadata:
142
+ return False
143
+
144
+ metadata = self._param_metadata[param_name]
145
+ expected_dtype = metadata["dtype"]
146
+
147
+ # Handle Union types for adducts parameter
148
+ if param_name == "adducts":
149
+ if value is None:
150
+ return True
151
+ if isinstance(value, str):
152
+ # Check if it's a valid ionization mode
153
+ allowed_values = metadata.get("allowed_values", [])
154
+ return value in allowed_values
155
+ elif isinstance(value, list):
156
+ # Check if all elements are strings
157
+ return all(isinstance(item, str) for item in value)
158
+ else:
159
+ return False
160
+
161
+ # Type checking for non-Union types
162
+ if expected_dtype is int:
163
+ if not isinstance(value, int):
164
+ try:
165
+ value = int(value)
166
+ except (ValueError, TypeError):
167
+ return False
168
+ elif expected_dtype is float:
169
+ if not isinstance(value, (int, float)):
170
+ try:
171
+ value = float(value)
172
+ except (ValueError, TypeError):
173
+ return False
174
+
175
+ # Range validation for numeric types
176
+ if expected_dtype in (int, float):
177
+ if "min_value" in metadata and value < metadata["min_value"]:
178
+ return False
179
+ if "max_value" in metadata and value > metadata["max_value"]:
180
+ return False
181
+
182
+ return True
183
+
184
+ def set(self, param_name: str, value: Any, validate: bool = True) -> bool:
185
+ """
186
+ Set a parameter value with optional validation.
187
+
188
+ Args:
189
+ param_name: Name of the parameter
190
+ value: New value for the parameter
191
+ validate: Whether to validate the value before setting
192
+
193
+ Returns:
194
+ True if parameter was set successfully, False otherwise
195
+ """
196
+ if not hasattr(self, param_name):
197
+ return False
198
+
199
+ if validate and not self.validate(param_name, value):
200
+ return False
201
+
202
+ # Convert to expected type if needed
203
+ if param_name in self._param_metadata:
204
+ expected_dtype = self._param_metadata[param_name]["dtype"]
205
+ if expected_dtype is int and not isinstance(value, int):
206
+ try:
207
+ value = int(value)
208
+ except (ValueError, TypeError):
209
+ if validate:
210
+ return False
211
+ elif expected_dtype is float and not isinstance(value, float):
212
+ try:
213
+ value = float(value)
214
+ except (ValueError, TypeError):
215
+ if validate:
216
+ return False
217
+
218
+ setattr(self, param_name, value)
219
+
220
+ # Trigger dynamic calculation if this is the adducts parameter
221
+ if param_name == "adducts":
222
+ self._update_openms_adducts()
223
+
224
+ return True
225
+
226
+ def get(self, param_name: str) -> Any:
227
+ """
228
+ Get the value of a parameter by name.
229
+
230
+ Args:
231
+ param_name: Name of the parameter
232
+
233
+ Returns:
234
+ Current value of the parameter
235
+ """
236
+ if not hasattr(self, param_name):
237
+ raise KeyError(f"Parameter '{param_name}' not found")
238
+ return getattr(self, param_name)
239
+
240
+ def set_from_dict(
241
+ self,
242
+ param_dict: dict[str, Any],
243
+ validate: bool = True,
244
+ ) -> list[str]:
245
+ """
246
+ Update multiple parameters from a dictionary.
247
+
248
+ Args:
249
+ param_dict: Dictionary of parameter names and values
250
+ validate: Whether to validate values before setting
251
+
252
+ Returns:
253
+ List of parameter names that could not be set
254
+ """
255
+ failed_params = []
256
+
257
+ for param_name, value in param_dict.items():
258
+ if not self.set(param_name, value, validate):
259
+ failed_params.append(param_name)
260
+
261
+ return failed_params
262
+
263
+ def to_dict(self) -> dict[str, Any]:
264
+ """
265
+ Convert parameters to dictionary, excluding metadata.
266
+
267
+ Returns:
268
+ Dictionary of parameter names and values
269
+ """
270
+ return {k: v for k, v in self.__dict__.items() if not k.startswith("_")}
271
+
272
+ def list_parameters(self) -> list[str]:
273
+ """
274
+ Get list of all parameter names.
275
+
276
+ Returns:
277
+ List of parameter names
278
+ """
279
+ return [k for k in self.__dict__.keys() if not k.startswith("_")]
280
+
281
+ def validate_all(self) -> tuple[bool, list[str]]:
282
+ """
283
+ Validate all parameters in the instance.
284
+
285
+ Returns:
286
+ Tuple of (all_valid, list_of_invalid_params)
287
+ - all_valid: True if all parameters are valid, False otherwise
288
+ - list_of_invalid_params: List of parameter names that failed validation
289
+ """
290
+ invalid_params = []
291
+
292
+ for param_name in self.list_parameters():
293
+ if param_name in self._param_metadata:
294
+ current_value = getattr(self, param_name)
295
+ if not self.validate(param_name, current_value):
296
+ invalid_params.append(param_name)
297
+
298
+ return len(invalid_params) == 0, invalid_params
299
+
300
+ def _update_openms_adducts(self) -> None:
301
+ """
302
+ Update the internal OpenMS adducts list when adducts parameter changes.
303
+ This is called automatically when the adducts parameter is set.
304
+ """
305
+ # This will update the internal state that get_openms_adducts() uses
306
+ pass
307
+
308
+ def get_openms_adducts(self) -> list[str]:
309
+ """
310
+ Get the processed adducts list for OpenMS MetaboliteFeatureDeconvolution.
311
+
312
+ Returns:
313
+ List of adduct strings formatted for OpenMS
314
+ """
315
+ adducts = self.adducts
316
+
317
+ if adducts is None or adducts in ["pos", "positive"]:
318
+ return ["H:+:0.4", "Na:+:0.3", "NH4:+:0.3"]
319
+ elif adducts in ["neg", "negative"]:
320
+ return ["H-1:-:1", "CH2O2:0:0.5"]
321
+ elif isinstance(adducts, list):
322
+ return adducts
323
+ else:
324
+ # Fallback to positive mode if unexpected format
325
+ return ["H:+:0.4", "Na:+:0.3", "NH4:+:0.3"]