screamlab 0.1.0__py3-none-any.whl → 0.3.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.
Binary file
Binary file
Binary file
screamlab/dataset.py CHANGED
@@ -12,8 +12,10 @@ Classes:
12
12
 
13
13
  """
14
14
 
15
+ import sys
15
16
  from datetime import datetime
16
17
  import numpy as np
18
+ from lmfit import Parameters
17
19
  from screamlab import io, utils, settings, functions
18
20
 
19
21
 
@@ -66,12 +68,17 @@ class Dataset:
66
68
  print(
67
69
  f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: Start buildup fit."
68
70
  )
71
+
69
72
  self._start_buildup_fit()
70
73
  print(
71
74
  f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: "
72
75
  f"Start generating result files. ({self.props.output_folder})"
73
76
  )
74
77
  self._print_all()
78
+ print(
79
+ f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: "
80
+ f"Finished with {self.props.path_to_experiment}"
81
+ )
75
82
 
76
83
  def _start_buildup_fit_from_spectra(self):
77
84
  """Starts buildup fitting using data imported from spectra CSV files."""
@@ -86,6 +93,7 @@ class Dataset:
86
93
  fitting_type="voigt",
87
94
  peak_sign="-",
88
95
  line_broadening=None,
96
+ integration_range=None,
89
97
  ):
90
98
  """
91
99
  Adds a peak to the ds.
@@ -94,7 +102,7 @@ class Dataset:
94
102
  ----------
95
103
  center_of_peak (float): Peak position in ppm (chemical shift).
96
104
  peak_label (str, optional): Custom label. Defaults to "Peak_at_<ppm>_ppm".
97
- fitting_type (str, optional): Peak shape: "gauss", "lorentz", or "voigt" (default).
105
+ fitting_type (str, optional): Peak shape: "gauss", "lorentz", or "voigt" (default).
98
106
  peak_sign (str, optional): "+" for upward, "-" for downward peaks. Defaults to "+".
99
107
  line_broadening (dict, optional): Dict with "sigma" and "gamma" keys for line width.
100
108
  Defaults to {"sigma": {"min": 0, "max": 3}, "gamma": {"min": 0, "max": 3}}.
@@ -109,6 +117,7 @@ class Dataset:
109
117
  peak.fitting_type = fitting_type
110
118
  peak.peak_sign = peak_sign
111
119
  peak.line_broadening = line_broadening
120
+ peak.integration_range = integration_range
112
121
 
113
122
  def _read_in_data_from_topspin(self):
114
123
  """Reads and imports data from TopSpin."""
@@ -132,7 +141,7 @@ class Dataset:
132
141
 
133
142
  def _calculate_peak_intensities(self):
134
143
  """Calculates peak intensities based on fitting methods."""
135
- if self.props.prefit:
144
+ if self.props.prefit and self.props.spectrum_fit_type != "numint":
136
145
  print(
137
146
  f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: Start prefit."
138
147
  )
@@ -148,7 +157,7 @@ class Dataset:
148
157
  result = self.fitter.fit()
149
158
  self.lmfit_result_handler.global_fit = result
150
159
  self._get_intensities(result)
151
- if "global" == self.props.spectrum_fit_type:
160
+ elif "global" == self.props.spectrum_fit_type:
152
161
  print(
153
162
  f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: Start global fit."
154
163
  )
@@ -156,6 +165,15 @@ class Dataset:
156
165
  result = self.fitter.fit()
157
166
  self.lmfit_result_handler.global_fit = result
158
167
  self._get_intensities(result)
168
+ elif "numint" == self.props.spectrum_fit_type:
169
+ print(
170
+ f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: Start integration."
171
+ )
172
+ self._set_integration_calc()
173
+ result = self.fitter.fit()
174
+ self._get_intensities(result)
175
+ else:
176
+ sys.exit()
159
177
 
160
178
  def _start_buildup_fit(self):
161
179
  """Performs buildup fitting using the appropriate fitter classes."""
@@ -164,7 +182,9 @@ class Dataset:
164
182
  "biexponential_with_offset": utils.BiexpFitterWithOffset,
165
183
  "exponential": utils.ExpFitter,
166
184
  "exponential_with_offset": utils.ExpFitterWithOffset,
167
- "streched_exponential": utils.StrechedExponentialFitter,
185
+ "stretched_exponential": utils.StrechedExponentialFitter,
186
+ "exponential_decay": utils.ExpDecayFitter,
187
+ "exponential_decay_with_offset": utils.ExpDecayFitterWithOffset,
168
188
  }
169
189
 
170
190
  for b_type in self.props.buildup_types:
@@ -187,10 +207,18 @@ class Dataset:
187
207
  """Sets up a global fitter for all spectra."""
188
208
  self.fitter = utils.GlobalFitter(self)
189
209
 
210
+ def _set_integration_calc(self):
211
+ self.fitter = utils.NumericalIntegration(self)
212
+
190
213
  def _get_intensities(self, result):
191
214
  """Extracts intensity values from the fitting results."""
192
215
  if isinstance(
193
- self.fitter, (utils.IndependentFitter, utils.GlobalFitter)
216
+ self.fitter,
217
+ (
218
+ utils.IndependentFitter,
219
+ utils.GlobalFitter,
220
+ utils.NumericalIntegration,
221
+ ),
194
222
  ):
195
223
  for peak in self.peak_list:
196
224
  peak.buildup_vals = (result, self.spectra)
@@ -213,6 +241,21 @@ class Dataset:
213
241
  if f"{peak.peak_label}_{lw}_0" in result.params
214
242
  }
215
243
 
244
+ def _transform_result_format(self, results):
245
+ print(results)
246
+ params_new = Parameters()
247
+ for result in results:
248
+ for name, par in result.params.items():
249
+ params_new.add(
250
+ name,
251
+ value=par.value,
252
+ vary=par.vary,
253
+ min=par.min,
254
+ max=par.max,
255
+ expr=par.expr,
256
+ )
257
+ return params_new
258
+
216
259
 
217
260
  class Spectra:
218
261
  """
@@ -257,6 +300,7 @@ class Peak:
257
300
  self._line_broadening = None
258
301
  self._line_broadening_init = None
259
302
  self._buildup_vals = None
303
+ self._integration_range = None
260
304
 
261
305
  def __str__(self):
262
306
  """
@@ -277,6 +321,34 @@ class Peak:
277
321
  f" {self._format_fitting_range('')}"
278
322
  )
279
323
 
324
+ def to_string(self, spectrum_fit_type):
325
+ """
326
+ Returns a string representation of the peak.
327
+
328
+ If `spectrum_fit_type` is "numint", detailed peak information
329
+ is returned, including center, label, sign, and integration range.
330
+ Otherwise, the default string representation of the object is returned.
331
+
332
+ Args:
333
+ spectrum_fit_type (str): The type of spectrum fitting.
334
+ Supports "numint" for numerical integration.
335
+
336
+ Returns
337
+ -------
338
+ str: A formatted string with peak information, or the default
339
+ string representation of the object.
340
+
341
+
342
+ """
343
+ if spectrum_fit_type == "numint":
344
+ return (
345
+ f"Peak center: {self.peak_center} ppm\n"
346
+ f"Peak label: {self.peak_label}\n"
347
+ f"Peak sign: {self.peak_sign}\n"
348
+ f"Numerical integration range: {self.integration_range} ppm\n"
349
+ )
350
+ return str(self)
351
+
280
352
  def _format_fitting_range(self, fit_type):
281
353
  a_max = "0 and inf" if self.peak_sign == "+" else "-inf and 0"
282
354
  lb = ""
@@ -297,6 +369,34 @@ class Peak:
297
369
  f"{lb}"
298
370
  )
299
371
 
372
+ @property
373
+ def integration_range(self) -> list:
374
+ """
375
+ Gets the integration range.
376
+
377
+ :return:
378
+ """
379
+ return self._integration_range
380
+
381
+ @integration_range.setter
382
+ def integration_range(self, args):
383
+ """
384
+ Sets the integration range.
385
+
386
+ :param args: List containing the integration range for numerical integragtion.
387
+ """
388
+ if args is not None:
389
+ if (
390
+ not isinstance(args, list)
391
+ or len(args) != 2
392
+ or not all(isinstance(e, (int, float)) for e in args)
393
+ ):
394
+ raise TypeError(
395
+ "Integration range must be a list of two numbers or None."
396
+ )
397
+
398
+ self._integration_range = args
399
+
300
400
  @property
301
401
  def buildup_vals(self) -> list:
302
402
  """
@@ -315,7 +415,10 @@ class Peak:
315
415
  """
316
416
  result, spectra = args
317
417
  self._buildup_vals = BuildupList()
318
- self._buildup_vals.set_vals(result, spectra, self.peak_label)
418
+ if isinstance(result, dict):
419
+ self._buildup_vals.set_num_int_vals(result[self], spectra)
420
+ else:
421
+ self._buildup_vals.set_vals(result, spectra, self.peak_label)
319
422
 
320
423
  @property
321
424
  def line_broadening(self) -> str:
@@ -600,6 +703,21 @@ class BuildupList:
600
703
  self._set_intensity(result, label, spectra)
601
704
  self._sort_lists()
602
705
 
706
+ def set_num_int_vals(self, result, spectra):
707
+ """
708
+ Sets buildup values from numerical integration.
709
+
710
+ Attributes
711
+ ----------
712
+ result (list): Intensity values
713
+ spectra (list): Spectrum objects used with result to compute buildup.
714
+ label (str): Peak label used to filter relevant parameters in result.
715
+
716
+ """
717
+ self._set_tpol(spectra)
718
+ self.intensity = result
719
+ self._sort_lists()
720
+
603
721
  def _set_tpol(self, spectra):
604
722
  self.tpol = [s.tpol for s in spectra]
605
723
 
@@ -607,20 +725,26 @@ class BuildupList:
607
725
  last_digid = None
608
726
  self.intensity = []
609
727
  val_list = []
610
- for param in result.params:
611
- if label in param:
612
- if last_digid != param.split("_")[-1]:
613
- if val_list:
614
- self.intensity.append(
615
- self._calc_integral(
616
- val_list, spectra[int(last_digid)]
728
+ res_list = []
729
+ if not isinstance(result, list):
730
+ res_list.append(result)
731
+ else:
732
+ res_list = result
733
+ for single_result in res_list:
734
+ for param in single_result.params:
735
+ if label in param:
736
+ if last_digid != param.split("_")[-1]:
737
+ if val_list:
738
+ self.intensity.append(
739
+ self._calc_integral(
740
+ val_list, spectra[int(last_digid)]
741
+ )
617
742
  )
618
- )
619
- last_digid = param.split("_")[-1]
620
- val_list = []
621
- val_list.append(float(result.params[param].value))
622
- if param.split("_")[-2] == "gamma":
623
- val_list.append("gamma")
743
+ last_digid = param.split("_")[-1]
744
+ val_list = []
745
+ val_list.append(float(single_result.params[param].value))
746
+ if param.split("_")[-2] == "gamma":
747
+ val_list.append("gamma")
624
748
  self.intensity.append(
625
749
  self._calc_integral(val_list, spectra[int(last_digid)])
626
750
  )
@@ -641,6 +765,8 @@ class BuildupList:
641
765
  """
642
766
  simspec = [0 for _ in range(len(spectrum.x_axis))]
643
767
  simspec = functions.calc_peak(spectrum.x_axis, simspec, val_list)
768
+ if hasattr(np, "trapezoid"):
769
+ return np.trapezoid(simspec)
644
770
  return np.trapz(simspec)
645
771
 
646
772
  def _sort_lists(self):
screamlab/functions.py CHANGED
@@ -169,6 +169,48 @@ def calc_stretched_exponential(time_vals, param):
169
169
  )
170
170
 
171
171
 
172
+ def calc_expdecay(time_vals, param):
173
+ """
174
+ Compute values of an exponential growth function over time.
175
+
176
+ The function models the equation:
177
+ I(t) = A * exp(-t / t)
178
+
179
+ where:
180
+ - I(t) : The output value at time t
181
+ - A : Amplitude (maximum value the function approaches)
182
+ - t : Time constant (controls the rate of decay)
183
+
184
+ Returns
185
+ -------
186
+ list: Exponential profile evaluated at t.
187
+
188
+ """
189
+ return list(param[0] * np.exp(-np.asarray(time_vals) / param[1]))
190
+
191
+
192
+ def calc_expdecaywithoffset(time_vals, param):
193
+ """
194
+ Compute values of an exponential growth function over time.
195
+
196
+ The function models the equation:
197
+ I(t) = A * exp(-t / t) + I0
198
+
199
+ where:
200
+ - I(t) : The output value at time t
201
+ - A : Amplitude (maximum value the function approaches)
202
+ - t : Time constant (controls the rate of decay)
203
+
204
+ Returns
205
+ -------
206
+ list: Exponential profile evaluated at t.
207
+
208
+ """
209
+ return list(
210
+ param[0] * np.exp(-np.asarray(time_vals) / param[1]) + param[2]
211
+ )
212
+
213
+
172
214
  def calc_biexponential(time_vals, param):
173
215
  """
174
216
  Compute values of a biexponential growth function over time.
@@ -245,7 +287,7 @@ def calc_biexponential_with_offset(time_vals, param):
245
287
  )
246
288
 
247
289
 
248
- def generate_spectra_param_dict(params):
290
+ def generate_spectra_param_dict_global(params):
249
291
  """
250
292
  Generate a dictionary of spectral parameters from a list of parameter names.
251
293
 
@@ -278,6 +320,40 @@ def generate_spectra_param_dict(params):
278
320
  return param_dict
279
321
 
280
322
 
323
+ def generate_spectra_param_dict_individual(params):
324
+ """
325
+ Generate a dictionary of spectral parameters from a list of parameter names.
326
+
327
+ :param params: Dictionary of parameter names and values.
328
+ :return: Dictionary of structured parameter values.
329
+ """
330
+ param_dict = {}
331
+ dict_index = -1
332
+ for list_element in params:
333
+ prefix, lastfix = None, None
334
+ param_value_list = []
335
+ for param in list_element.params:
336
+ parts = re.split(r"_(cen|amp|sigma|gamma)_", param)
337
+ if prefix != parts[0]:
338
+ if param_value_list:
339
+ param_dict[dict_index].append(param_value_list)
340
+ prefix = parts[0]
341
+ param_value_list = []
342
+ if lastfix != parts[2]:
343
+ if param_value_list:
344
+ param_dict[dict_index].append(param_value_list)
345
+ param_value_list = []
346
+ lastfix = parts[2]
347
+ dict_index += 1
348
+ if dict_index not in param_dict:
349
+ param_dict[dict_index] = []
350
+ param_value_list.append(float(list_element.params[param].value))
351
+ if parts[1] == "gamma":
352
+ param_value_list.append("gam")
353
+ param_dict[dict_index].append(param_value_list)
354
+ return param_dict
355
+
356
+
281
357
  def calc_peak(x_axis, simspec, val):
282
358
  """Simulates spectra based on given parameters."""
283
359
  if len(val) == 5:
@@ -303,8 +379,9 @@ def format_mapping():
303
379
  "Sf",
304
380
  "---",
305
381
  "---",
382
+ "---",
306
383
  ],
307
- "streched_exponential": [
384
+ "stretched_exponential": [
308
385
  "Af",
309
386
  "tf",
310
387
  "---",
@@ -315,6 +392,7 @@ def format_mapping():
315
392
  "Sf",
316
393
  "---",
317
394
  "beta",
395
+ "---",
318
396
  ],
319
397
  "exponential_with_offset": [
320
398
  "Af",
@@ -327,6 +405,7 @@ def format_mapping():
327
405
  "Sf",
328
406
  "---",
329
407
  "---",
408
+ "---",
330
409
  ],
331
410
  "biexponential": [
332
411
  "Af",
@@ -339,6 +418,7 @@ def format_mapping():
339
418
  "Sf",
340
419
  "Ss",
341
420
  "---",
421
+ "---",
342
422
  ],
343
423
  "biexponential_with_offset": [
344
424
  "Af",
@@ -351,6 +431,33 @@ def format_mapping():
351
431
  "Sf",
352
432
  "Ss",
353
433
  "---",
434
+ "---",
435
+ ],
436
+ "exponential_decay": [
437
+ "Af",
438
+ "tf",
439
+ "---",
440
+ "---",
441
+ "---",
442
+ "Rf",
443
+ "---",
444
+ "Sf",
445
+ "---",
446
+ "---",
447
+ "---",
448
+ ],
449
+ "exponential_decay_with_offset": [
450
+ "Af",
451
+ "tf",
452
+ "---",
453
+ "---",
454
+ "---",
455
+ "Rf",
456
+ "---",
457
+ "Sf",
458
+ "---",
459
+ "---",
460
+ "I0",
354
461
  ],
355
462
  }
356
463
 
@@ -368,7 +475,8 @@ def buildup_header():
368
475
  "Rs / 1/s",
369
476
  "Sensitivity1 (Af/sqrt(tf))",
370
477
  "Sensitivity2 (As/sqrt(ts))",
371
- "beta",
478
+ "beta / a.u.",
479
+ "I0 / a.u.",
372
480
  ]
373
481
 
374
482
 
@@ -395,7 +503,9 @@ def return_func_map():
395
503
  "biexponential": calc_biexponential,
396
504
  "exponential_with_offset": calc_exponential_with_offset,
397
505
  "biexponential_with_offset": calc_biexponential_with_offset,
398
- "streched_exponential": calc_stretched_exponential,
506
+ "stretched_exponential": calc_stretched_exponential,
507
+ "exponential_decay": calc_expdecay,
508
+ "exponential_decay_with_offset": calc_expdecaywithoffset,
399
509
  }
400
510
 
401
511
 
screamlab/io.py CHANGED
@@ -113,6 +113,13 @@ class TopspinImporter:
113
113
  ]
114
114
  return path_list
115
115
 
116
+ def _gen_subspectrum(self):
117
+ self._dataset.spectra[-1].x_axis, self._dataset.spectra[-1].y_axis = (
118
+ screamlab.functions.generate_subspec(
119
+ self._dataset.spectra[-1], self._dataset.props.subspec
120
+ )
121
+ )
122
+
116
123
 
117
124
  class ScreamImporter(TopspinImporter):
118
125
  """
@@ -124,15 +131,6 @@ class ScreamImporter(TopspinImporter):
124
131
 
125
132
  """
126
133
 
127
- def _set_number_of_scans(self):
128
- """Set the number of scans for the last spectrum in the ds."""
129
- with open(rf"{self.file}/acqu", "r", encoding="utf-8") as acqu_file:
130
- for acqu_line in acqu_file:
131
- if "##$NS=" in acqu_line:
132
- self._dataset.spectra[-1].number_of_scans = int(
133
- acqu_line.strip().split(" ")[-1]
134
- )
135
-
136
134
  def import_topspin_data(self):
137
135
  """Import NMR data from TopSpin and process it."""
138
136
  files = self._generate_path_to_experiment()
@@ -142,6 +140,15 @@ class ScreamImporter(TopspinImporter):
142
140
  self._set_values()
143
141
  self._sort_xy_lists()
144
142
 
143
+ def _set_number_of_scans(self):
144
+ """Set the number of scans for the last spectrum in the ds."""
145
+ with open(rf"{self.file}/acqus", "r", encoding="utf-8") as acqu_file:
146
+ for acqu_line in acqu_file:
147
+ if "##$NS=" in acqu_line:
148
+ self._dataset.spectra[-1].number_of_scans = int(
149
+ acqu_line.strip().split(" ")[-1]
150
+ )
151
+
145
152
  def _set_buildup_time(self):
146
153
  """Set the buildup time for the last spectrum in the ds."""
147
154
  delay = self._extract_params_from_acqus("##$D= (0..63)", 64)
@@ -204,16 +211,49 @@ class ScreamImporter(TopspinImporter):
204
211
  self._dataset.spectra[-1].number_of_scans,
205
212
  )
206
213
 
207
- def _gen_subspectrum(self):
208
- self._dataset.spectra[-1].x_axis, self._dataset.spectra[-1].y_axis = (
209
- screamlab.functions.generate_subspec(
210
- self._dataset.spectra[-1], self._dataset.props.subspec
211
- )
212
- )
213
-
214
214
 
215
215
  class Pseudo2DImporter(TopspinImporter):
216
- """Not implemented yet."""
216
+ """
217
+ Class for importing and processing Pseudo2D data based on VD list.
218
+
219
+ Automatically reads information about x- and y-axis (chemical shift and intensitys),
220
+ polarization times (t_pol) and the number of scans used for the respective experiment.
221
+ Automatically normalizes the intensitys to the number of scans.
222
+
223
+ """
224
+
225
+ def import_topspin_data(self):
226
+ """Import pseudo 2D NMR data from TopSpin and process it."""
227
+ files = self._generate_path_to_experiment()
228
+ self.file = files[0]
229
+ self._set_values()
230
+
231
+ def _set_values(self):
232
+ """Set internal values including scans, buildup time, x and y data."""
233
+ dic, data = ng.bruker.read_pdata(
234
+ f"{self.file}/pdata/{self._dataset.props.procno}"
235
+ )
236
+ uc = ng.bruker.guess_udic(dic, data)
237
+ vdlist = self._get_vdvals()
238
+ for spectrum_nr in range(data.shape[0]):
239
+ self._add_spectrum()
240
+ self._dataset.spectra[-1].number_of_scans = int(
241
+ dic.get("acqus", {}).get("NS", None)
242
+ )
243
+ self._dataset.spectra[-1].tpol = vdlist[spectrum_nr]
244
+ self._dataset.spectra[-1].x_axis = ng.fileiobase.uc_from_udic(
245
+ uc, dim=1
246
+ ).ppm_scale()
247
+ self._dataset.spectra[-1].y_axis = data[spectrum_nr, :]
248
+ if len(self._dataset.props.subspec) == 2:
249
+ self._gen_subspectrum()
250
+
251
+ def _get_vdvals(self):
252
+ vdvals = []
253
+ with open(rf"{self.file}/vdlist", "r", encoding="utf-8") as vdlist:
254
+ for vdline in vdlist:
255
+ vdvals.append(float(vdline.strip()))
256
+ return vdvals
217
257
 
218
258
 
219
259
  class Exporter:
@@ -258,18 +298,29 @@ class Exporter:
258
298
  """
259
299
  self._print_report()
260
300
  self._plot_topspin_data()
261
- self._plot_global_all_together()
262
- if self.dataset.props.prefit:
301
+ if self.dataset.props.spectrum_fit_type != "numint":
302
+ self._plot_global_all_together()
303
+ if (
304
+ self.dataset.props.prefit
305
+ and self.dataset.props.spectrum_fit_type != "numint"
306
+ ):
263
307
  self._plot_prefit()
264
308
  self._print_lmfit_prefit_report()
265
- if "global" in self.dataset.props.spectrum_fit_type:
309
+ if (
310
+ "global" in self.dataset.props.spectrum_fit_type
311
+ and self.dataset.props.spectrum_fit_type != "numint"
312
+ ):
266
313
  self._plot_global_each_individual()
267
- if "individual" in self.dataset.props.spectrum_fit_type:
314
+ if (
315
+ "individual" in self.dataset.props.spectrum_fit_type
316
+ and self.dataset.props.spectrum_fit_type != "numint"
317
+ ):
268
318
  self._plot_global_each_individual()
269
319
  for buildup_type in self.dataset.props.buildup_types:
270
320
  self._plot_buildup(buildup_type)
271
- self._write_global_fit_results_to_semicolon_separated_file()
272
- self._write_buildup_fit_to_semicolon_separated_file()
321
+ if self.dataset.props.spectrum_fit_type != "numint":
322
+ self._write_global_fit_results_to_semicolon_separated_file()
323
+ self._write_buildup_fit_to_semicolon_separated_file()
273
324
  self._csv_output()
274
325
 
275
326
  def _plot_topspin_data(self):
@@ -321,7 +372,7 @@ class Exporter:
321
372
  self.dataset.props.spectrum_for_prefit
322
373
  ]
323
374
  x_axis, y_axis = spectrum.x_axis, spectrum.y_axis
324
- valdict = screamlab.functions.generate_spectra_param_dict(
375
+ valdict = screamlab.functions.generate_spectra_param_dict_global(
325
376
  self.dataset.lmfit_result_handler.prefit.params
326
377
  )
327
378
  simspec = [0] * len(y_axis)
@@ -430,9 +481,19 @@ class Exporter:
430
481
 
431
482
  def _plot_global_each_individual(self):
432
483
  output_dir = self._generate_output_dir("spectral_deconvolution_plots")
433
- param_dict = screamlab.functions.generate_spectra_param_dict(
434
- self.dataset.lmfit_result_handler.global_fit.params
435
- )
484
+ param_dict = None
485
+ if self.dataset.props.spectrum_fit_type == "global":
486
+ param_dict = (
487
+ screamlab.functions.generate_spectra_param_dict_global(
488
+ self.dataset.lmfit_result_handler.global_fit.params
489
+ )
490
+ )
491
+ elif self.dataset.props.spectrum_fit_type == "individual":
492
+ param_dict = (
493
+ screamlab.functions.generate_spectra_param_dict_individual(
494
+ self.dataset.lmfit_result_handler.global_fit
495
+ )
496
+ )
436
497
 
437
498
  for key, param_list in param_dict.items():
438
499
  spectrum = self.dataset.spectra[key]
@@ -484,10 +545,19 @@ class Exporter:
484
545
 
485
546
  def _plot_global_all_together(self):
486
547
  output_dir = self._generate_output_dir("spectral_deconvolution_plots")
487
-
488
- param_dict = screamlab.functions.generate_spectra_param_dict(
489
- self.dataset.lmfit_result_handler.global_fit.params
490
- )
548
+ param_dict = None
549
+ if self.dataset.props.spectrum_fit_type == "global":
550
+ param_dict = (
551
+ screamlab.functions.generate_spectra_param_dict_global(
552
+ self.dataset.lmfit_result_handler.global_fit.params
553
+ )
554
+ )
555
+ elif self.dataset.props.spectrum_fit_type == "individual":
556
+ param_dict = (
557
+ screamlab.functions.generate_spectra_param_dict_individual(
558
+ self.dataset.lmfit_result_handler.global_fit
559
+ )
560
+ )
491
561
 
492
562
  num_spectra = len(param_dict)
493
563
  cols = 3
@@ -572,15 +642,23 @@ class Exporter:
572
642
  f.write("[[Peaks]]\n")
573
643
  for peak_nr, peak in enumerate(self.dataset.peak_list):
574
644
  f.write(f"[Peak {peak_nr + 1}]\n")
575
- f.write(str(peak))
645
+ f.write(peak.to_string(self.dataset.props.spectrum_fit_type))
576
646
  f.write("[[Prefit]]\n")
577
- if self.dataset.props.prefit:
647
+ if (
648
+ self.dataset.props.prefit
649
+ and self.dataset.props.spectrum_fit_type != "numint"
650
+ ):
578
651
  self._get_prefit_string(f)
579
652
  else:
580
653
  f.write("No prefit performed.\n")
581
654
 
582
- f.write("[[Global fit results]]\n")
583
- self._print_global_fit_results(f)
655
+ if self.dataset.props.spectrum_fit_type != "numint":
656
+ f.write("[[Spectral deconvolution results]]\n")
657
+ self._print_global_fit_results(f)
658
+
659
+ else:
660
+ f.write("[[Numerical integration results]]\n")
661
+ self._print_global_fit_results_numint(f)
584
662
  f.write("[[Buildup fit results]]\n")
585
663
  self._print_buildup(f)
586
664
 
@@ -588,7 +666,7 @@ class Exporter:
588
666
  for buildup_type in self.dataset.props.buildup_types:
589
667
  f.write(f"[{buildup_type}]\n")
590
668
  header = screamlab.functions.buildup_header()
591
- column_widths = [20, 15, 10, 15, 10, 15, 15, 15, 35, 35, 10]
669
+ column_widths = [20, 15, 10, 15, 10, 15, 15, 15, 35, 35, 20, 15]
592
670
  f.write(
593
671
  "".join(h.ljust(w) for h, w in zip(header, column_widths))
594
672
  + "\n"
@@ -614,12 +692,42 @@ class Exporter:
614
692
  + "\n"
615
693
  )
616
694
 
617
- def _print_global_fit_results(self, f):
618
- valdict = screamlab.functions.generate_spectra_param_dict(
619
- self.dataset.lmfit_result_handler.global_fit.params
695
+ def _print_global_fit_results_numint(self, f):
696
+ header = ["Label", "Time", "Integral"]
697
+ column_widths = [25, 12, 10]
698
+ f.write(
699
+ "".join(f"{h:<{w}}" for h, w in zip(header, column_widths)) + "\n"
620
700
  )
701
+ for peak in self.dataset.peak_list:
702
+ for integral_nr, integral in enumerate(
703
+ peak.buildup_vals.intensity
704
+ ):
705
+ line = []
706
+ if integral_nr == 0:
707
+ line.append(peak.peak_label)
708
+ else:
709
+ line.append(" ")
710
+ line.append(peak.buildup_vals.tpol[integral_nr])
711
+ line.append(round(integral, 4))
712
+ f.write(
713
+ "".join(f"{h:<{w}}" for h, w in zip(line, column_widths))
714
+ + "\n"
715
+ )
716
+
717
+ def _print_global_fit_results(self, f):
718
+ valdict = None
719
+ if self.dataset.props.spectrum_fit_type == "global":
720
+ valdict = screamlab.functions.generate_spectra_param_dict_global(
721
+ self.dataset.lmfit_result_handler.global_fit.params
722
+ )
723
+ elif self.dataset.props.spectrum_fit_type == "individual":
724
+ valdict = (
725
+ screamlab.functions.generate_spectra_param_dict_individual(
726
+ self.dataset.lmfit_result_handler.global_fit
727
+ )
728
+ )
621
729
  header = screamlab.functions.spectrum_fit_header()
622
- column_widths = [25, 12, 15, 20, 15, 15, 22, 20, 20, 10]
730
+ column_widths = [25, 12, 15, 20, 15, 15, 22, 20, 20, 20, 15]
623
731
  f.write(
624
732
  "".join(f"{h:<{w}}" for h, w in zip(header, column_widths)) + "\n"
625
733
  )
@@ -633,7 +741,7 @@ class Exporter:
633
741
  )
634
742
 
635
743
  def _get_prefit_string(self, f):
636
- valdict = screamlab.functions.generate_spectra_param_dict(
744
+ valdict = screamlab.functions.generate_spectra_param_dict_global(
637
745
  self.dataset.lmfit_result_handler.prefit.params
638
746
  )
639
747
  widths = [25, 18, 20, 15, 15]
@@ -764,9 +872,18 @@ class Exporter:
764
872
  )
765
873
 
766
874
  with open(output_file_path, "w", encoding="utf-8") as f:
767
- valdict = screamlab.functions.generate_spectra_param_dict(
768
- self.dataset.lmfit_result_handler.global_fit.params
769
- )
875
+ valdict = None
876
+ if self.dataset.props.spectrum_fit_type == "global":
877
+ valdict = (
878
+ screamlab.functions.generate_spectra_param_dict_global(
879
+ self.dataset.lmfit_result_handler.global_fit.params
880
+ )
881
+ )
882
+ elif self.dataset.props.spectrum_fit_type == "individual":
883
+ valdict = screamlab.functions.generate_spectra_param_dict_individual(
884
+ self.dataset.lmfit_result_handler.global_fit
885
+ )
886
+
770
887
  header = screamlab.functions.spectrum_fit_header()
771
888
  f.write(";".join(str(item) for item in header) + "\n")
772
889
  for delay_time in range(0, len(valdict[0])):
@@ -859,6 +976,7 @@ class Exporter:
859
976
  return row
860
977
 
861
978
  def _gen_voigt_output(self, values, delay_time, val_nr):
979
+
862
980
  return [
863
981
  (
864
982
  self.dataset.peak_list[delay_time].peak_label
screamlab/settings.py CHANGED
@@ -80,12 +80,20 @@ class Properties:
80
80
  return self._subspec
81
81
 
82
82
  @subspec.setter
83
- def subspec(self, value: Any):
84
- """Sets list for subspectrum"""
85
- if value is not None:
86
- self._subspec = value
87
- else:
83
+ def subspec(self, value):
84
+ if value is None:
88
85
  self._subspec = []
86
+ return
87
+
88
+ try:
89
+ self._subspec = [float(v) for v in value]
90
+ except (TypeError, ValueError) as exc:
91
+ raise ValueError(
92
+ "subspec must be a sequence of two floats"
93
+ ) from exc
94
+
95
+ if len(self._subspec) != 2:
96
+ raise ValueError("subspec must contain exactly two values")
89
97
 
90
98
  @property
91
99
  def output_folder(self) -> str:
@@ -181,7 +189,7 @@ class Properties:
181
189
  """
182
190
  str, optional: A list specifying the spectrum fit type
183
191
 
184
- Options supporded: "global","independent".
192
+ Options supporded: "global", "independent, "numint".
185
193
 
186
194
  """
187
195
  return self._spectrum_fit_type
@@ -189,10 +197,7 @@ class Properties:
189
197
  @spectrum_fit_type.setter
190
198
  def spectrum_fit_type(self, value: Any):
191
199
  """Sets the spectrum fit type"""
192
- allowed_values = {
193
- "global",
194
- "individual",
195
- }
200
+ allowed_values = {"global", "individual", "numint"}
196
201
  if not isinstance(value, str):
197
202
  raise TypeError(
198
203
  f"Expected 'spectrum_fit_type' to be of type 'str', got"
@@ -227,7 +232,9 @@ class Properties:
227
232
  "biexponential",
228
233
  "biexponential_with_offset",
229
234
  "exponential_with_offset",
230
- "streched_exponential",
235
+ "stretched_exponential",
236
+ "exponential_decay",
237
+ "exponential_decay_with_offset",
231
238
  }
232
239
  if not isinstance(value, list):
233
240
  raise TypeError(
screamlab/utils.py CHANGED
@@ -23,6 +23,7 @@ Classes:
23
23
  """
24
24
 
25
25
  import copy
26
+ from datetime import datetime
26
27
  import numpy as np
27
28
  import lmfit
28
29
  from pyDOE3 import lhs
@@ -33,7 +34,7 @@ class Fitter:
33
34
  """
34
35
  Base class for spectral fitting using `lmfit`.
35
36
 
36
- This class handles parameter initialization and spectral fitting for a ds.
37
+ This class handles parameter initialization and spectral fitting for a dataset.
37
38
 
38
39
  Attributes
39
40
  ----------
@@ -44,7 +45,7 @@ class Fitter:
44
45
 
45
46
  def __init__(self, dataset):
46
47
  """
47
- Initializes the Fitter with a ds.
48
+ Initializes the Fitter with a dataset.
48
49
 
49
50
  Args
50
51
  ----
@@ -66,7 +67,6 @@ class Fitter:
66
67
  x_axis, y_axis = self._generate_axis_list()
67
68
  params = self._generate_params_list()
68
69
  params = self._set_param_expr(params)
69
-
70
70
  return self._start_minimize(x_axis, y_axis, params)
71
71
 
72
72
  def _start_minimize(self, x_axis, y_axis, params):
@@ -194,8 +194,8 @@ class Fitter:
194
194
  return {
195
195
  "name": f"{peak.peak_label}_cen_{nr}",
196
196
  "value": peak.peak_center,
197
- "min": peak.peak_center - 20,
198
- "max": peak.peak_center + 20,
197
+ "min": peak.peak_center - 1,
198
+ "max": peak.peak_center + 1,
199
199
  }
200
200
 
201
201
  def _get_lw_dict(self, peak, nr, lw):
@@ -240,7 +240,9 @@ class Fitter:
240
240
 
241
241
  """
242
242
  residual = copy.deepcopy(y_axis)
243
- params_dict_list = functions.generate_spectra_param_dict(params)
243
+ params_dict_list = functions.generate_spectra_param_dict_global(
244
+ params
245
+ )
244
246
  for key, val_list in params_dict_list.items():
245
247
  for val in val_list:
246
248
  simspec = [0 for _ in range(len(x_axis[key]))]
@@ -281,6 +283,71 @@ class Prefitter(Fitter):
281
283
  return result
282
284
 
283
285
 
286
+ class NumericalIntegration(Fitter):
287
+ """
288
+ Subclass of Fitter that calculates spectral signal intensities via numerical integration.
289
+
290
+ This class is designed for applications where the area under a curve
291
+ in a given spectral window is of interest, such as quantifying peak
292
+ intensities in spectroscopy or other analytical measurements.
293
+ By integrating over a defined region, it provides a robust measure
294
+ of signal strength that accounts for variations in peak shape
295
+ and baseline fluctuations.
296
+ """
297
+
298
+ def fit(self):
299
+ """
300
+ Performs spectral numerical integration using numpy trapz or trapezoid function.
301
+
302
+ Returns
303
+ -------
304
+ dict
305
+ The result of the integration process.
306
+
307
+ """
308
+ integrals = {}
309
+ for spectrum in self.dataset.spectra:
310
+ for peak in self.dataset.peak_list:
311
+ if peak not in integrals:
312
+ integrals[peak] = []
313
+ self._check_integration_range_in_spectra(spectrum, peak)
314
+ subspec_x_axis, subspec_y_axis = functions.generate_subspec(
315
+ spectrum, peak.integration_range
316
+ )
317
+ if hasattr(np, "trapezoid"):
318
+ integrals[peak].append(
319
+ np.trapezoid(
320
+ subspec_y_axis[::-1], subspec_x_axis[::-1]
321
+ )
322
+ )
323
+ else:
324
+ integrals[peak].append(
325
+ np.trapz(subspec_y_axis[::-1], subspec_x_axis[::-1])
326
+ )
327
+ return integrals
328
+
329
+ def _check_integration_range_in_spectra(self, spectrum, peak):
330
+ self._check_if_integration_range_are_set(peak)
331
+ for integration_boundary in peak.integration_range:
332
+ if not (
333
+ min(spectrum.x_axis)
334
+ <= integration_boundary
335
+ <= max(spectrum.x_axis)
336
+ ):
337
+ raise ValueError(
338
+ f"Integration boundary {integration_boundary} is outside the spectrum "
339
+ f"range ({min(spectrum.x_axis)} – {max(spectrum.x_axis)})."
340
+ )
341
+
342
+ def _check_if_integration_range_are_set(self, peak):
343
+ if peak.integration_range is None:
344
+ raise ValueError(
345
+ f"Peak '{peak.peak_label}' ({peak.peak_center:.3f} ppm): "
346
+ f"integration_range is not set. "
347
+ f"Call dataset.add_peak({peak.peak_center}, integration_range=(from_ppm, to_ppm))."
348
+ )
349
+
350
+
284
351
  class GlobalFitter(Fitter):
285
352
  """
286
353
  Global fit over all spectra at different polarization times.
@@ -329,6 +396,77 @@ class IndependentFitter(Fitter):
329
396
  must be ensured that all spectra can be fitted by conditions given in point two.
330
397
  """
331
398
 
399
+ def _generate_params_list(self):
400
+ """
401
+ Generates initial fitting parameters based on peak information in the ds.
402
+
403
+ Returns
404
+ -------
405
+ lmfit.Parameters
406
+ The initialized parameters for fitting.
407
+
408
+ """
409
+ params_list = []
410
+ spectra = self._get_spectra_list()
411
+ lw_types = {
412
+ "voigt": ["sigma", "gamma"],
413
+ "gauss": ["sigma"],
414
+ "lorentz": ["gamma"],
415
+ }
416
+ for spectrum_nr, _ in enumerate(spectra):
417
+ params = lmfit.Parameters()
418
+ for peak in self.dataset.peak_list:
419
+ params.add(**self._get_amplitude_dict(peak, spectrum_nr))
420
+ params.add(**self._get_center_dict(peak, spectrum_nr))
421
+
422
+ for lw_type in lw_types.get(peak.fitting_type, []):
423
+ params.add(
424
+ **self._get_lw_dict(peak, spectrum_nr, lw_type)
425
+ )
426
+ params_list.append(params)
427
+ return params_list
428
+
429
+ def _start_minimize(self, x_axis, y_axis, params):
430
+ all_results = []
431
+ for spectrum_nr, spectrum in enumerate(x_axis):
432
+ print(
433
+ f"\t{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: "
434
+ f"Start fitting spectrum number {spectrum_nr+1}/{len(x_axis)}"
435
+ )
436
+ result = lmfit.minimize(
437
+ self._spectral_fitting,
438
+ params[spectrum_nr],
439
+ args=(spectrum, y_axis[spectrum_nr]),
440
+ )
441
+ all_results.append(result)
442
+ return all_results
443
+
444
+ def _spectral_fitting(self, params, x_axis, y_axis):
445
+ """
446
+ Computes the residual between the fitted and experimental spectra.
447
+
448
+ Args
449
+ ----
450
+ params (lmfit.Parameters): The fitting parameters.
451
+ x_axis (list): List of x-axis values.
452
+ y_axis (list): List of y-axis values.
453
+
454
+ Returns
455
+ -------
456
+ np.ndarray: The residual between the fitted and experimental spectra.
457
+
458
+ """
459
+ residual = y_axis.copy()
460
+ params_dict_list = functions.generate_spectra_param_dict_global(
461
+ params
462
+ )
463
+ for _, val_list in params_dict_list.items():
464
+ for val in val_list:
465
+ simspec = [0 for _ in range(len(x_axis))]
466
+ simspec = functions.calc_peak(x_axis, simspec, val)
467
+ residual -= simspec
468
+ return residual
469
+
332
470
 
333
471
  class BuildupFitter:
334
472
  """
@@ -483,6 +621,27 @@ class BuildupFitter:
483
621
  """
484
622
  return [params[key].value for key in params]
485
623
 
624
+ def _get_intensity_offset_dict(self, peak):
625
+ """
626
+ Generate intensity offset parameter dictionary.
627
+
628
+ :param peak: Peak object containing buildup values.
629
+ :return: Dictionary with default intensity parameter values.
630
+ """
631
+ return (
632
+ {
633
+ "value": 10,
634
+ "min": max(peak.buildup_vals.intensity) * -3,
635
+ "max": max(peak.buildup_vals.intensity) * 3,
636
+ }
637
+ if peak.peak_sign == "+"
638
+ else {
639
+ "value": 10,
640
+ "max": min(peak.buildup_vals.intensity) * -3,
641
+ "min": min(peak.buildup_vals.intensity) * 3,
642
+ }
643
+ )
644
+
486
645
  def _get_intensity_dict(self, peak):
487
646
  """
488
647
  Generate intensity parameter dictionary.
@@ -559,6 +718,88 @@ class BiexpFitter(BuildupFitter):
559
718
  return functions.calc_biexponential(tdel, param)
560
719
 
561
720
 
721
+ class ExpDecayFitter(BuildupFitter):
722
+ """
723
+ Class for fitting exponential decay models to experimental data.
724
+
725
+ The exponential decay model fits decay curves using one exponential term
726
+ characterized by an amplitude (A) and a time constants (t).
727
+
728
+ The model function is defined as:
729
+ I(t_pol) = A * exp(-t_pol / t))
730
+
731
+ where:
732
+ - A : amplitudes of the exponential components
733
+ - t : time constants of the exponential components (t > 0)
734
+ - t_pol : polarization time (independent variable)
735
+ - I(t_pol) : peak intensity at polarization time t_pol
736
+ """
737
+
738
+ def _get_default_param_dict(self, peak):
739
+ """
740
+ Define default parameters for exponential decay fitting.
741
+
742
+ :param peak: Peak object containing peak_sign and buildup values.
743
+ :return: Dictionary of default parameters with keys: A, t.
744
+ """
745
+ return {
746
+ "Af": self._get_intensity_dict(peak),
747
+ "tf": self._get_time_dict(peak),
748
+ }
749
+
750
+ def _calc_intensity(self, tdel, param):
751
+ """
752
+ Calculate exponential decay intensity.
753
+
754
+ :param tdel: Time delays.
755
+ :param param: List of parameters.
756
+ :return: Calculated intensity values.
757
+ """
758
+ return functions.calc_expdecay(tdel, param)
759
+
760
+
761
+ class ExpDecayFitterWithOffset(BuildupFitter):
762
+ """
763
+ Class for fitting exponential decay models to experimental data.
764
+
765
+ The exponential decay model fits decay curves using one exponential term
766
+ characterized by an amplitude (A), an intensity offset (I0) and a time constants (t).
767
+
768
+ The model function is defined as:
769
+ I(t_pol) = I0 + A * exp(-t_pol / t))
770
+
771
+ where:
772
+ - A : amplitudes of the exponential components
773
+ - t : time constants of the exponential components (t > 0)
774
+ - t_pol : polarization time (independent variable)
775
+ - I0 : Intensity offset
776
+ - I(t_pol) : peak intensity at polarization time t_pol
777
+ """
778
+
779
+ def _get_default_param_dict(self, peak):
780
+ """
781
+ Define default parameters for exponential decay fitting with offset.
782
+
783
+ :param peak: Peak object containing peak_sign and buildup values.
784
+ :return: Dictionary of default parameters with keys: A, t, I0.
785
+ """
786
+ return {
787
+ "Af": self._get_intensity_dict(peak),
788
+ "tf": self._get_time_dict(peak),
789
+ "I0": self._get_intensity_offset_dict(peak),
790
+ }
791
+
792
+ def _calc_intensity(self, tdel, param):
793
+ """
794
+ Calculate exponential decay intensity.
795
+
796
+ :param tdel: Time delays.
797
+ :param param: List of parameters.
798
+ :return: Calculated intensity values.
799
+ """
800
+ return functions.calc_expdecaywithoffset(tdel, param)
801
+
802
+
562
803
  class BiexpFitterWithOffset(BuildupFitter):
563
804
  """
564
805
  Class for fitting biexponential models with offset to buildup data.
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: screamlab
3
- Version: 0.1.0
3
+ Version: 0.3.1
4
4
  Summary: Package for reproducible evaluation of SCREAM-DNP data.
5
5
  Home-page: https://github.com/FlorianTaube/screamlab
6
6
  Author: Florian Taube
7
7
  Author-email: florian.taube@uni-rostock.de
8
8
  License: BSD
9
- Project-URL: Documentation, https://github.com/FlorianTaube/screamlab/docs
9
+ Project-URL: Documentation, https://screamlab.readthedocs.io
10
10
  Project-URL: Source, https://github.com/FlorianTaube/screamlab/screamlab
11
11
  Keywords: Buildup Time Calculator,NMR,DNP,SCREAM_DNP,TopspinExport
12
12
  Classifier: Programming Language :: Python :: 3
@@ -0,0 +1,30 @@
1
+ screamlab/__init__.py,sha256=M2vfzk7vI3qvlxE2uIHyGYmPSrFYNUacFjkjiLX00wc,63
2
+ screamlab/dataset.py,sha256=d4Ztrr-gAYiNA8nGi5zhkQeRvdBdI6FblYBst3XLnzQ,26837
3
+ screamlab/functions.py,sha256=zujGG87iwcBfl8clg1JUG1SYYTIO4XutNmCVhlZME4M,14638
4
+ screamlab/io.py,sha256=deZEbf9gFn3OIr3lCS_ZbklGni-YG3_DBuNMEt710EQ,42968
5
+ screamlab/settings.py,sha256=4lUsrTj6Ne9RQPmjSy1EAM5M2I8EwaM4ZpVE8-GP-JM,9459
6
+ screamlab/utils.py,sha256=Ca82YmSmKsZf-EX9dra0WEcZrJWYcWdsnzs3xQDtHoQ,34268
7
+ screamlab/__pycache__/__init__.cpython-310.pyc,sha256=nGadfOt1WUjQxMQAWhkaJ8HQIBoFYgJOXOcou6xtrJ4,245
8
+ screamlab/__pycache__/__init__.cpython-312.pyc,sha256=Vo2caaR8VoJ8_NleXq-XOrPKFsFfwxsYJtyJjRxMaAQ,253
9
+ screamlab/__pycache__/__init__.cpython-313.pyc,sha256=yQf9pPv0AH2e55exkKjAhkP7dXZn17lnMgudh9XDnxo,249
10
+ screamlab/__pycache__/__init__.cpython-38.pyc,sha256=M5eZ95kmsA8r__ZH_prnNqi--MGl8WclL9g0yUXGTAo,176
11
+ screamlab/__pycache__/dataset.cpython-310.pyc,sha256=wIfwBQFdYvUbanp8okbVfyF4Txdx0DwPrID_AG054QM,24961
12
+ screamlab/__pycache__/dataset.cpython-312.pyc,sha256=6I6pajXpcAGzgMMWz8Uz8RBFvHhamr8ldh4LYvgmVHY,29658
13
+ screamlab/__pycache__/dataset.cpython-313.pyc,sha256=SZHG1m9zZ8iKTrETEkd1IyrZ0ts41wyONaug2zFYPNc,33499
14
+ screamlab/__pycache__/functions.cpython-310.pyc,sha256=QFIT-SC3IypiT3FjxR4rdFaX3mBCuNmI7gwHj3IPIWI,12089
15
+ screamlab/__pycache__/functions.cpython-312.pyc,sha256=3XGaxzxxkM11879B0tD2igT9kx-_s3lk1fhABYwIPec,13136
16
+ screamlab/__pycache__/functions.cpython-313.pyc,sha256=ozCyYcTb6HU6BBgz0Byag3-EYVdqTTNHmU1VqAFnVNU,12631
17
+ screamlab/__pycache__/io.cpython-310.pyc,sha256=qbi2IVwZfOTr8nZ1u4vxsgQtsqlxMAJxDUYUIZn3ZaM,33595
18
+ screamlab/__pycache__/io.cpython-312.pyc,sha256=MMoeXwNuzsekbKxuU151oMMqJ_Hn-gQ-GmwSHULdVOA,53564
19
+ screamlab/__pycache__/io.cpython-313.pyc,sha256=FqolkwTPOY7ViOsfEGFzf5pYfif4ikfFPDlXoG-tdlA,51707
20
+ screamlab/__pycache__/settings.cpython-310.pyc,sha256=JDbCK7P7CAU_xoh3uwcKJhyge-7TXD59RKRG6RcV6Hs,8642
21
+ screamlab/__pycache__/settings.cpython-312.pyc,sha256=C_E_orj-EgVwor9s8eqF0hBs-vejOFEglWI7DN1U6Yo,11907
22
+ screamlab/__pycache__/settings.cpython-313.pyc,sha256=m1P8CXfLTds2c40e-pmtBuWTfKI6X3YaroXsZL-mV7Q,12019
23
+ screamlab/__pycache__/utils.cpython-310.pyc,sha256=vG1o5HO3D_tTicOQJv1gYdkAg-9PhB2jnXxA5QVoSSU,32103
24
+ screamlab/__pycache__/utils.cpython-312.pyc,sha256=NkdFr8Yr-ywDfFqTJK3QUro_YMGyezhQ04YF5Va4yGo,30799
25
+ screamlab/__pycache__/utils.cpython-313.pyc,sha256=6nj3DrKpIb11HUDjo1ubnP4ymMBE8S2vuacY3zGjhNk,29120
26
+ screamlab-0.3.1.dist-info/licenses/LICENSE,sha256=Ic_N1IFIdReR7m-W6XtN_4k6B8IgJ33dQFLc6Xi5C2E,1291
27
+ screamlab-0.3.1.dist-info/METADATA,sha256=cPkvLs3GDzSemCu4hNU0Xnq4-C6RxaYBw2Et0VrLQYU,2942
28
+ screamlab-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
29
+ screamlab-0.3.1.dist-info/top_level.txt,sha256=XjErA4-PG_phESo1eWs-bMzdnBWu4gNxB-RX78zZqqw,10
30
+ screamlab-0.3.1.dist-info/RECORD,,
@@ -1,27 +0,0 @@
1
- screamlab/__init__.py,sha256=M2vfzk7vI3qvlxE2uIHyGYmPSrFYNUacFjkjiLX00wc,63
2
- screamlab/dataset.py,sha256=QZSGwm3au08ZEBLdH-pmkyXaeatwBVMZQKs-37j3IQ4,22537
3
- screamlab/functions.py,sha256=vq6YseAt6L0YlduI6LV3_WBcLhFaOqDRGDIIDaZ3kfc,11398
4
- screamlab/io.py,sha256=B5I9oxQ4uH2dExnoDlO7Glbk3KcrXSVJcWTEl05eLOk,38017
5
- screamlab/settings.py,sha256=XBlzWjsdcAO3Fq_d9UyxYViirT9qmpw5_UVrYd-lt0o,9130
6
- screamlab/utils.py,sha256=VbHaH_QWfcj2WM-TrraPCdjMr7qJ5ybkc2Vgguqhvxg,25503
7
- screamlab/__pycache__/__init__.cpython-310.pyc,sha256=nGadfOt1WUjQxMQAWhkaJ8HQIBoFYgJOXOcou6xtrJ4,245
8
- screamlab/__pycache__/__init__.cpython-312.pyc,sha256=Vo2caaR8VoJ8_NleXq-XOrPKFsFfwxsYJtyJjRxMaAQ,253
9
- screamlab/__pycache__/__init__.cpython-313.pyc,sha256=yQf9pPv0AH2e55exkKjAhkP7dXZn17lnMgudh9XDnxo,249
10
- screamlab/__pycache__/__init__.cpython-38.pyc,sha256=M5eZ95kmsA8r__ZH_prnNqi--MGl8WclL9g0yUXGTAo,176
11
- screamlab/__pycache__/dataset.cpython-310.pyc,sha256=_faFHwzFWVQ12RQn_JEmVacRbG3kfRjiq2oZMFC0lKU,21615
12
- screamlab/__pycache__/dataset.cpython-312.pyc,sha256=6I6pajXpcAGzgMMWz8Uz8RBFvHhamr8ldh4LYvgmVHY,29658
13
- screamlab/__pycache__/dataset.cpython-313.pyc,sha256=hUv5iLuEbc1ZvsghDsBs5fMJX8P2c9LVODugU9AUq6Q,28966
14
- screamlab/__pycache__/functions.cpython-310.pyc,sha256=NCAC7EjK1gJCi5sdEcferiMHbFVOhTL6jme0-0-5xKg,10221
15
- screamlab/__pycache__/functions.cpython-312.pyc,sha256=3XGaxzxxkM11879B0tD2igT9kx-_s3lk1fhABYwIPec,13136
16
- screamlab/__pycache__/io.cpython-310.pyc,sha256=5l2qLRHXu0_xQIeBtpRf4on_aX8z9M8Y-pvPWRNNxMM,30699
17
- screamlab/__pycache__/io.cpython-312.pyc,sha256=MMoeXwNuzsekbKxuU151oMMqJ_Hn-gQ-GmwSHULdVOA,53564
18
- screamlab/__pycache__/settings.cpython-310.pyc,sha256=NEb0GFRJNxnFdCyQSv5WPBp6yPT15dwC8_IHQVpB0Us,8263
19
- screamlab/__pycache__/settings.cpython-312.pyc,sha256=C_E_orj-EgVwor9s8eqF0hBs-vejOFEglWI7DN1U6Yo,11907
20
- screamlab/__pycache__/settings.cpython-313.pyc,sha256=bkB5KCTnxR8rKtrYezCt753f-cnjwhTfXZL2LsVTiaE,11800
21
- screamlab/__pycache__/utils.cpython-310.pyc,sha256=1ADymFGnozfp-gqDCH8PMxPKGDAutepRqsPheXKcuQ0,25452
22
- screamlab/__pycache__/utils.cpython-312.pyc,sha256=NkdFr8Yr-ywDfFqTJK3QUro_YMGyezhQ04YF5Va4yGo,30799
23
- screamlab-0.1.0.dist-info/licenses/LICENSE,sha256=Ic_N1IFIdReR7m-W6XtN_4k6B8IgJ33dQFLc6Xi5C2E,1291
24
- screamlab-0.1.0.dist-info/METADATA,sha256=rJ7ubHx5d35-l0izBb6ax6N4Sosrjb6kqlVZwaCLnEU,2956
25
- screamlab-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
- screamlab-0.1.0.dist-info/top_level.txt,sha256=XjErA4-PG_phESo1eWs-bMzdnBWu4gNxB-RX78zZqqw,10
27
- screamlab-0.1.0.dist-info/RECORD,,