rapidtide 3.0.10__py3-none-any.whl → 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.
Files changed (141) hide show
  1. rapidtide/Colortables.py +492 -27
  2. rapidtide/OrthoImageItem.py +1053 -47
  3. rapidtide/RapidtideDataset.py +1533 -86
  4. rapidtide/_version.py +3 -3
  5. rapidtide/calccoherence.py +196 -29
  6. rapidtide/calcnullsimfunc.py +191 -40
  7. rapidtide/calcsimfunc.py +245 -42
  8. rapidtide/correlate.py +1210 -393
  9. rapidtide/data/examples/src/testLD +56 -0
  10. rapidtide/data/examples/src/testalign +1 -1
  11. rapidtide/data/examples/src/testdelayvar +0 -1
  12. rapidtide/data/examples/src/testfmri +19 -1
  13. rapidtide/data/examples/src/testglmfilt +5 -5
  14. rapidtide/data/examples/src/testhappy +30 -1
  15. rapidtide/data/examples/src/testppgproc +17 -0
  16. rapidtide/data/examples/src/testrolloff +11 -0
  17. rapidtide/data/models/model_cnn_pytorch/best_model.pth +0 -0
  18. rapidtide/data/models/model_cnn_pytorch/loss.png +0 -0
  19. rapidtide/data/models/model_cnn_pytorch/loss.txt +1 -0
  20. rapidtide/data/models/model_cnn_pytorch/model.pth +0 -0
  21. rapidtide/data/models/model_cnn_pytorch/model_meta.json +68 -0
  22. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1_space-MNI152NLin2009cAsym_2mm.nii.gz +0 -0
  23. rapidtide/data/reference/JHU-ArterialTerritoriesNoVent-LVL1_space-MNI152NLin2009cAsym_2mm_mask.nii.gz +0 -0
  24. rapidtide/decorators.py +91 -0
  25. rapidtide/dlfilter.py +2225 -108
  26. rapidtide/dlfiltertorch.py +4843 -0
  27. rapidtide/externaltools.py +327 -12
  28. rapidtide/fMRIData_class.py +79 -40
  29. rapidtide/filter.py +1899 -810
  30. rapidtide/fit.py +2004 -574
  31. rapidtide/genericmultiproc.py +93 -18
  32. rapidtide/happy_supportfuncs.py +2044 -171
  33. rapidtide/helper_classes.py +584 -43
  34. rapidtide/io.py +2363 -370
  35. rapidtide/linfitfiltpass.py +341 -75
  36. rapidtide/makelaggedtcs.py +211 -20
  37. rapidtide/maskutil.py +423 -53
  38. rapidtide/miscmath.py +827 -121
  39. rapidtide/multiproc.py +210 -22
  40. rapidtide/patchmatch.py +234 -33
  41. rapidtide/peakeval.py +32 -30
  42. rapidtide/ppgproc.py +2203 -0
  43. rapidtide/qualitycheck.py +352 -39
  44. rapidtide/refinedelay.py +422 -57
  45. rapidtide/refineregressor.py +498 -184
  46. rapidtide/resample.py +671 -185
  47. rapidtide/scripts/applyppgproc.py +28 -0
  48. rapidtide/simFuncClasses.py +1052 -77
  49. rapidtide/simfuncfit.py +260 -46
  50. rapidtide/stats.py +540 -238
  51. rapidtide/tests/happycomp +9 -0
  52. rapidtide/tests/test_dlfiltertorch.py +627 -0
  53. rapidtide/tests/test_findmaxlag.py +24 -8
  54. rapidtide/tests/test_fullrunhappy_v1.py +0 -2
  55. rapidtide/tests/test_fullrunhappy_v2.py +0 -2
  56. rapidtide/tests/test_fullrunhappy_v3.py +1 -0
  57. rapidtide/tests/test_fullrunhappy_v4.py +2 -2
  58. rapidtide/tests/test_fullrunrapidtide_v7.py +1 -1
  59. rapidtide/tests/test_simroundtrip.py +8 -8
  60. rapidtide/tests/utils.py +9 -8
  61. rapidtide/tidepoolTemplate.py +142 -38
  62. rapidtide/tidepoolTemplate_alt.py +165 -44
  63. rapidtide/tidepoolTemplate_big.py +189 -52
  64. rapidtide/util.py +1217 -118
  65. rapidtide/voxelData.py +684 -37
  66. rapidtide/wiener.py +19 -12
  67. rapidtide/wiener2.py +113 -7
  68. rapidtide/wiener_doc.py +255 -0
  69. rapidtide/workflows/adjustoffset.py +105 -3
  70. rapidtide/workflows/aligntcs.py +85 -2
  71. rapidtide/workflows/applydlfilter.py +87 -10
  72. rapidtide/workflows/applyppgproc.py +522 -0
  73. rapidtide/workflows/atlasaverage.py +210 -47
  74. rapidtide/workflows/atlastool.py +100 -3
  75. rapidtide/workflows/calcSimFuncMap.py +294 -64
  76. rapidtide/workflows/calctexticc.py +201 -9
  77. rapidtide/workflows/ccorrica.py +97 -4
  78. rapidtide/workflows/cleanregressor.py +168 -29
  79. rapidtide/workflows/delayvar.py +163 -10
  80. rapidtide/workflows/diffrois.py +81 -3
  81. rapidtide/workflows/endtidalproc.py +144 -4
  82. rapidtide/workflows/fdica.py +195 -15
  83. rapidtide/workflows/filtnifti.py +70 -3
  84. rapidtide/workflows/filttc.py +74 -3
  85. rapidtide/workflows/fitSimFuncMap.py +206 -48
  86. rapidtide/workflows/fixtr.py +73 -3
  87. rapidtide/workflows/gmscalc.py +113 -3
  88. rapidtide/workflows/happy.py +813 -201
  89. rapidtide/workflows/happy2std.py +144 -12
  90. rapidtide/workflows/happy_parser.py +149 -8
  91. rapidtide/workflows/histnifti.py +118 -2
  92. rapidtide/workflows/histtc.py +84 -3
  93. rapidtide/workflows/linfitfilt.py +117 -4
  94. rapidtide/workflows/localflow.py +328 -28
  95. rapidtide/workflows/mergequality.py +79 -3
  96. rapidtide/workflows/niftidecomp.py +322 -18
  97. rapidtide/workflows/niftistats.py +174 -4
  98. rapidtide/workflows/pairproc.py +88 -2
  99. rapidtide/workflows/pairwisemergenifti.py +85 -2
  100. rapidtide/workflows/parser_funcs.py +1421 -40
  101. rapidtide/workflows/physiofreq.py +137 -11
  102. rapidtide/workflows/pixelcomp.py +208 -5
  103. rapidtide/workflows/plethquality.py +103 -21
  104. rapidtide/workflows/polyfitim.py +151 -11
  105. rapidtide/workflows/proj2flow.py +75 -2
  106. rapidtide/workflows/rankimage.py +111 -4
  107. rapidtide/workflows/rapidtide.py +272 -15
  108. rapidtide/workflows/rapidtide2std.py +98 -2
  109. rapidtide/workflows/rapidtide_parser.py +109 -9
  110. rapidtide/workflows/refineDelayMap.py +143 -33
  111. rapidtide/workflows/refineRegressor.py +682 -93
  112. rapidtide/workflows/regressfrommaps.py +152 -31
  113. rapidtide/workflows/resamplenifti.py +85 -3
  114. rapidtide/workflows/resampletc.py +91 -3
  115. rapidtide/workflows/retrolagtcs.py +98 -6
  116. rapidtide/workflows/retroregress.py +165 -9
  117. rapidtide/workflows/roisummarize.py +173 -5
  118. rapidtide/workflows/runqualitycheck.py +71 -3
  119. rapidtide/workflows/showarbcorr.py +147 -4
  120. rapidtide/workflows/showhist.py +86 -2
  121. rapidtide/workflows/showstxcorr.py +160 -3
  122. rapidtide/workflows/showtc.py +159 -3
  123. rapidtide/workflows/showxcorrx.py +184 -4
  124. rapidtide/workflows/showxy.py +185 -15
  125. rapidtide/workflows/simdata.py +262 -36
  126. rapidtide/workflows/spatialfit.py +77 -2
  127. rapidtide/workflows/spatialmi.py +251 -27
  128. rapidtide/workflows/spectrogram.py +305 -32
  129. rapidtide/workflows/synthASL.py +154 -3
  130. rapidtide/workflows/tcfrom2col.py +76 -2
  131. rapidtide/workflows/tcfrom3col.py +74 -2
  132. rapidtide/workflows/tidepool.py +2972 -133
  133. rapidtide/workflows/utils.py +19 -14
  134. rapidtide/workflows/utils_doc.py +293 -0
  135. rapidtide/workflows/variabilityizer.py +116 -3
  136. {rapidtide-3.0.10.dist-info → rapidtide-3.1.dist-info}/METADATA +10 -9
  137. {rapidtide-3.0.10.dist-info → rapidtide-3.1.dist-info}/RECORD +141 -122
  138. {rapidtide-3.0.10.dist-info → rapidtide-3.1.dist-info}/entry_points.txt +1 -0
  139. {rapidtide-3.0.10.dist-info → rapidtide-3.1.dist-info}/WHEEL +0 -0
  140. {rapidtide-3.0.10.dist-info → rapidtide-3.1.dist-info}/licenses/LICENSE +0 -0
  141. {rapidtide-3.0.10.dist-info → rapidtide-3.1.dist-info}/top_level.txt +0 -0
rapidtide/dlfilter.py CHANGED
@@ -120,32 +120,186 @@ class DeepLearningFilter:
120
120
 
121
121
  def __init__(
122
122
  self,
123
- window_size=128,
124
- num_layers=5,
125
- dropout_rate=0.3,
126
- num_pretrain_epochs=0,
127
- num_epochs=1,
128
- activation="relu",
129
- modelroot=".",
130
- dofft=False,
131
- excludethresh=4.0,
132
- usebadpts=False,
133
- thesuffix="25.0Hz",
134
- modelpath=".",
135
- thedatadir="/Users/frederic/Documents/MR_data/physioconn/timecourses",
136
- inputfrag="abc",
137
- targetfrag="xyz",
138
- corrthresh=0.5,
139
- excludebysubject=True,
140
- startskip=200,
141
- endskip=200,
142
- step=1,
143
- namesuffix=None,
144
- readlim=None,
145
- readskip=None,
146
- countlim=None,
123
+ window_size: int = 128,
124
+ num_layers: int = 5,
125
+ dropout_rate: float = 0.3,
126
+ num_pretrain_epochs: int = 0,
127
+ num_epochs: int = 1,
128
+ activation: str = "relu",
129
+ modelroot: str = ".",
130
+ dofft: bool = False,
131
+ excludethresh: float = 4.0,
132
+ usebadpts: bool = False,
133
+ thesuffix: str = "25.0Hz",
134
+ modelpath: str = ".",
135
+ thedatadir: str = "/Users/frederic/Documents/MR_data/physioconn/timecourses",
136
+ inputfrag: str = "abc",
137
+ targetfrag: str = "xyz",
138
+ corrthresh: float = 0.5,
139
+ excludebysubject: bool = True,
140
+ startskip: int = 200,
141
+ endskip: int = 200,
142
+ step: int = 1,
143
+ namesuffix: str | None = None,
144
+ readlim: int | None = None,
145
+ readskip: int | None = None,
146
+ countlim: int | None = None,
147
147
  **kwargs,
148
- ):
148
+ ) -> None:
149
+ """
150
+ Initialize the DeepLearningFilter with specified parameters.
151
+
152
+ This constructor sets up the configuration for a deep learning model used
153
+ for filtering physiological timecourses. It initializes various hyperparameters,
154
+ paths, and flags that control the behavior of the model and data processing.
155
+
156
+ Parameters
157
+ ----------
158
+ window_size : int, optional
159
+ Size of the sliding window used for processing time series data. Default is 128.
160
+ num_layers : int, optional
161
+ Number of layers in the neural network model. Default is 5.
162
+ dropout_rate : float, optional
163
+ Dropout rate for regularization during training. Default is 0.3.
164
+ num_pretrain_epochs : int, optional
165
+ Number of pre-training epochs. Default is 0.
166
+ num_epochs : int, optional
167
+ Number of training epochs. Default is 1.
168
+ activation : str, optional
169
+ Activation function to use in the model. Default is "relu".
170
+ modelroot : str, optional
171
+ Root directory for model storage. Default is ".".
172
+ dofft : bool, optional
173
+ Whether to apply FFT transformation to input data. Default is False.
174
+ excludethresh : float, optional
175
+ Threshold for excluding data points based on correlation. Default is 4.0.
176
+ usebadpts : bool, optional
177
+ Whether to include bad points in the input. Default is False.
178
+ thesuffix : str, optional
179
+ Suffix to append to filenames. Default is "25.0Hz".
180
+ modelpath : str, optional
181
+ Path to save or load the model. Default is ".".
182
+ thedatadir : str, optional
183
+ Directory containing the physiological data files. Default is
184
+ "/Users/frederic/Documents/MR_data/physioconn/timecourses".
185
+ inputfrag : str, optional
186
+ Fragment identifier for input data. Default is "abc".
187
+ targetfrag : str, optional
188
+ Fragment identifier for target data. Default is "xyz".
189
+ corrthresh : float, optional
190
+ Correlation threshold for filtering. Default is 0.5.
191
+ excludebysubject : bool, optional
192
+ Whether to exclude data by subject. Default is True.
193
+ startskip : int, optional
194
+ Number of samples to skip at the beginning of each timecourse. Default is 200.
195
+ endskip : int, optional
196
+ Number of samples to skip at the end of each timecourse. Default is 200.
197
+ step : int, optional
198
+ Step size for sliding window. Default is 1.
199
+ namesuffix : str, optional
200
+ Suffix to append to model name. Default is None.
201
+ readlim : int, optional
202
+ Limit on number of samples to read. Default is None.
203
+ readskip : int, optional
204
+ Number of samples to skip when reading data. Default is None.
205
+ countlim : int, optional
206
+ Limit on number of timecourses to process. Default is None.
207
+ **kwargs
208
+ Additional keyword arguments passed to the parent class.
209
+
210
+ Notes
211
+ -----
212
+ The `inputsize` is dynamically set based on the `usebadpts` flag:
213
+ - If `usebadpts` is True, input size is 2.
214
+ - Otherwise, input size is 1.
215
+
216
+ Examples
217
+ --------
218
+ >>> filter = DeepLearningFilter(
219
+ ... window_size=256,
220
+ ... num_layers=6,
221
+ ... dropout_rate=0.2,
222
+ ... modelroot="/models",
223
+ ... dofft=True
224
+ ... )
225
+ """
226
+ """
227
+ Initialize the DeepLearningFilter with specified parameters.
228
+
229
+ This constructor sets up the configuration for a deep learning model used
230
+ for filtering physiological timecourses. It initializes various hyperparameters,
231
+ paths, and flags that control the behavior of the model and data processing.
232
+
233
+ Parameters
234
+ ----------
235
+ window_size : int, optional
236
+ Size of the sliding window used for processing time series data. Default is 128.
237
+ num_layers : int, optional
238
+ Number of layers in the neural network model. Default is 5.
239
+ dropout_rate : float, optional
240
+ Dropout rate for regularization during training. Default is 0.3.
241
+ num_pretrain_epochs : int, optional
242
+ Number of pre-training epochs. Default is 0.
243
+ num_epochs : int, optional
244
+ Number of training epochs. Default is 1.
245
+ activation : str, optional
246
+ Activation function to use in the model. Default is "relu".
247
+ modelroot : str, optional
248
+ Root directory for model storage. Default is ".".
249
+ dofft : bool, optional
250
+ Whether to apply FFT transformation to input data. Default is False.
251
+ excludethresh : float, optional
252
+ Threshold for excluding data points based on correlation. Default is 4.0.
253
+ usebadpts : bool, optional
254
+ Whether to include bad points in the input. Default is False.
255
+ thesuffix : str, optional
256
+ Suffix to append to filenames. Default is "25.0Hz".
257
+ modelpath : str, optional
258
+ Path to save or load the model. Default is ".".
259
+ thedatadir : str, optional
260
+ Directory containing the physiological data files. Default is
261
+ "/Users/frederic/Documents/MR_data/physioconn/timecourses".
262
+ inputfrag : str, optional
263
+ Fragment identifier for input data. Default is "abc".
264
+ targetfrag : str, optional
265
+ Fragment identifier for target data. Default is "xyz".
266
+ corrthresh : float, optional
267
+ Correlation threshold for filtering. Default is 0.5.
268
+ excludebysubject : bool, optional
269
+ Whether to exclude data by subject. Default is True.
270
+ startskip : int, optional
271
+ Number of samples to skip at the beginning of each timecourse. Default is 200.
272
+ endskip : int, optional
273
+ Number of samples to skip at the end of each timecourse. Default is 200.
274
+ step : int, optional
275
+ Step size for sliding window. Default is 1.
276
+ namesuffix : str, optional
277
+ Suffix to append to model name. Default is None.
278
+ readlim : int, optional
279
+ Limit on number of samples to read. Default is None.
280
+ readskip : int, optional
281
+ Number of samples to skip when reading data. Default is None.
282
+ countlim : int, optional
283
+ Limit on number of timecourses to process. Default is None.
284
+ **kwargs
285
+ Additional keyword arguments passed to the parent class.
286
+
287
+ Notes
288
+ -----
289
+ The `inputsize` is dynamically set based on the `usebadpts` flag:
290
+ - If `usebadpts` is True, input size is 2.
291
+ - Otherwise, input size is 1.
292
+
293
+ Examples
294
+ --------
295
+ >>> filter = DeepLearningFilter(
296
+ ... window_size=256,
297
+ ... num_layers=6,
298
+ ... dropout_rate=0.2,
299
+ ... modelroot="/models",
300
+ ... dofft=True
301
+ ... )
302
+ """
149
303
  self.window_size = window_size
150
304
  self.dropout_rate = dropout_rate
151
305
  self.num_pretrain_epochs = num_pretrain_epochs
@@ -195,7 +349,91 @@ class DeepLearningFilter:
195
349
  self.infodict["step"] = self.step
196
350
  self.infodict["train_arch"] = sys.platform
197
351
 
198
- def loaddata(self):
352
+ def loaddata(self) -> None:
353
+ """
354
+ Load and preprocess data for training and validation.
355
+
356
+ This method initializes the data loading process by calling the `prep` function
357
+ with a set of parameters derived from the instance attributes. It handles both
358
+ FFT and non-FFT modes of data preprocessing. The loaded data is stored in
359
+ instance variables for use in subsequent training steps.
360
+
361
+ Parameters
362
+ ----------
363
+ self : object
364
+ The instance of the class containing the following attributes:
365
+ - initialized : bool
366
+ Indicates whether the model has been initialized.
367
+ - dofft : bool
368
+ Whether to apply FFT transformation to the data.
369
+ - window_size : int
370
+ Size of the sliding window used for data segmentation.
371
+ - thesuffix : str
372
+ Suffix to append to filenames when reading data.
373
+ - thedatadir : str
374
+ Directory path where the data files are located.
375
+ - inputfrag : str
376
+ Fragment identifier for input data.
377
+ - targetfrag : str
378
+ Fragment identifier for target data.
379
+ - startskip : int
380
+ Number of samples to skip at the beginning of each file.
381
+ - endskip : int
382
+ Number of samples to skip at the end of each file.
383
+ - corrthresh : float
384
+ Correlation threshold for filtering data.
385
+ - step : int
386
+ Step size for sliding window.
387
+ - usebadpts : bool
388
+ Whether to include bad points in the data.
389
+ - excludethresh : float
390
+ Threshold for excluding data points.
391
+ - excludebysubject : bool
392
+ Whether to exclude data by subject.
393
+ - readlim : int
394
+ Limit on the number of samples to read.
395
+ - readskip : int
396
+ Number of samples to skip while reading.
397
+ - countlim : int
398
+ Limit on the number of data points to process.
399
+
400
+ Returns
401
+ -------
402
+ None
403
+ This method does not return any value. It modifies the instance attributes
404
+ in place.
405
+
406
+ Raises
407
+ ------
408
+ Exception
409
+ If the model is not initialized prior to calling this method.
410
+
411
+ Notes
412
+ -----
413
+ The method assigns the following attributes to the instance after loading:
414
+ - train_x : array-like
415
+ Training input data.
416
+ - train_y : array-like
417
+ Training target data.
418
+ - val_x : array-like
419
+ Validation input data.
420
+ - val_y : array-like
421
+ Validation target data.
422
+ - Ns : int
423
+ Number of samples.
424
+ - tclen : int
425
+ Length of time series.
426
+ - thebatchsize : int
427
+ Batch size for training.
428
+
429
+ Examples
430
+ --------
431
+ >>> model = MyModel()
432
+ >>> model.initialized = True
433
+ >>> model.loaddata()
434
+ >>> print(model.train_x.shape)
435
+ (1000, 10)
436
+ """
199
437
  if not self.initialized:
200
438
  raise Exception("model must be initialized prior to loading data")
201
439
 
@@ -257,10 +495,87 @@ class DeepLearningFilter:
257
495
  )
258
496
 
259
497
  @tf.function
260
- def predict_model(self, X):
498
+ def predict_model(self, X: np.ndarray) -> np.ndarray:
499
+ """
500
+ Make predictions using the trained model.
501
+
502
+ Parameters
503
+ ----------
504
+ X : np.ndarray
505
+ Input features for prediction. Shape should be (n_samples, n_features)
506
+ where n_samples is the number of samples and n_features is the number
507
+ of features expected by the model.
508
+
509
+ Returns
510
+ -------
511
+ np.ndarray
512
+ Model predictions. Shape will depend on the specific model type but
513
+ typically follows (n_samples,) for regression or (n_samples, n_classes)
514
+ for classification.
515
+
516
+ Notes
517
+ -----
518
+ This method sets the model to inference mode by calling with training=False.
519
+ The predictions are made without computing gradients, making it efficient
520
+ for inference tasks.
521
+
522
+ Examples
523
+ --------
524
+ >>> # Assuming model is already trained
525
+ >>> X_test = np.array([[1.0, 2.0], [3.0, 4.0]])
526
+ >>> predictions = model.predict_model(X_test)
527
+ >>> print(predictions)
528
+ """
261
529
  return self.model(X, training=False)
262
530
 
263
- def evaluate(self):
531
+ def evaluate(self) -> tuple[list, list, float, float]:
532
+ """
533
+ Evaluate the model performance on validation data and compute loss metrics.
534
+
535
+ This method performs model evaluation by computing prediction errors and
536
+ saving training/validation loss curves. It calculates both prediction error
537
+ (difference between predicted and actual values) and raw error (difference
538
+ between input and actual values). The method also generates and saves a
539
+ plot of the training and validation loss over epochs.
540
+
541
+ Parameters
542
+ ----------
543
+ self : object
544
+ The instance of the class containing the model and data attributes.
545
+
546
+ Returns
547
+ -------
548
+ tuple[list, list, float, float]
549
+ A tuple containing:
550
+ - training_loss : list
551
+ List of training loss values per epoch
552
+ - validation_loss : list
553
+ List of validation loss values per epoch
554
+ - prediction_error : float
555
+ Mean squared error between predicted and actual values
556
+ - raw_error : float
557
+ Mean squared error between input features and actual values
558
+
559
+ Notes
560
+ -----
561
+ This method modifies the instance attributes:
562
+ - self.lossfilename: Path to the saved loss plot
563
+ - self.pred_error: Computed prediction error
564
+ - self.raw_error: Computed raw error
565
+ - self.loss: Training loss history
566
+ - self.val_loss: Validation loss history
567
+
568
+ The method saves:
569
+ - Loss plot as PNG file
570
+ - Loss metrics as text file
571
+
572
+ Examples
573
+ --------
574
+ >>> model = MyModel()
575
+ >>> train_loss, val_loss, pred_error, raw_error = model.evaluate()
576
+ >>> print(f"Prediction Error: {pred_error}")
577
+ Prediction Error: 0.1234
578
+ """
264
579
  self.lossfilename = os.path.join(self.modelname, "loss.png")
265
580
  LGR.info(f"lossfilename: {self.lossfilename}")
266
581
 
@@ -301,7 +616,44 @@ class DeepLearningFilter:
301
616
 
302
617
  return self.loss, self.val_loss, self.pred_error, self.raw_error
303
618
 
304
- def initmetadata(self):
619
+ def initmetadata(self) -> None:
620
+ """
621
+ Initialize and store metadata information for the model.
622
+
623
+ This function creates a dictionary containing various model configuration parameters
624
+ and writes them to a JSON file for future reference and reproducibility.
625
+
626
+ Parameters
627
+ ----------
628
+ self : object
629
+ The instance of the class containing the metadata attributes.
630
+
631
+ Returns
632
+ -------
633
+ None
634
+ This function does not return any value but writes metadata to a JSON file.
635
+
636
+ Notes
637
+ -----
638
+ The metadata includes:
639
+ - Window size for processing
640
+ - Bad point handling flag
641
+ - FFT usage flag
642
+ - Exclusion threshold
643
+ - Number of epochs and layers
644
+ - Dropout rate
645
+ - Operating system platform
646
+ - Model name
647
+
648
+ The metadata is saved to ``{modelname}/model_meta.json`` where ``modelname``
649
+ is the model's name attribute.
650
+
651
+ Examples
652
+ --------
653
+ >>> model = MyModel()
654
+ >>> model.initmetadata()
655
+ >>> # Metadata stored in modelname/model_meta.json
656
+ """
305
657
  self.infodict = {}
306
658
  self.infodict["window_size"] = self.window_size
307
659
  self.infodict["usebadpts"] = self.usebadpts
@@ -314,14 +666,87 @@ class DeepLearningFilter:
314
666
  self.infodict["modelname"] = self.modelname
315
667
  tide_io.writedicttojson(self.infodict, os.path.join(self.modelname, "model_meta.json"))
316
668
 
317
- def updatemetadata(self):
669
+ def updatemetadata(self) -> None:
670
+ """
671
+ Update metadata dictionary with model metrics and save to JSON file.
672
+
673
+ This method updates the internal information dictionary with various model
674
+ performance metrics and writes the complete metadata to a JSON file for
675
+ model persistence and tracking.
676
+
677
+ Parameters
678
+ ----------
679
+ self : object
680
+ The instance of the class containing the metadata and model information.
681
+ Expected to have the following attributes:
682
+ - infodict : dict
683
+ Dictionary containing model metadata.
684
+ - loss : float
685
+ Training loss value.
686
+ - val_loss : float
687
+ Validation loss value.
688
+ - raw_error : float
689
+ Raw error metric.
690
+ - pred_error : float
691
+ Prediction error metric.
692
+ - modelname : str
693
+ Name/path of the model for file output.
694
+
695
+ Returns
696
+ -------
697
+ None
698
+ This method does not return any value but modifies the `infodict` in-place
699
+ and writes to a JSON file.
700
+
701
+ Notes
702
+ -----
703
+ The method writes metadata to ``{modelname}/model_meta.json`` where
704
+ ``modelname`` is the model name attribute of the instance.
705
+
706
+ Examples
707
+ --------
708
+ >>> model = MyModel()
709
+ >>> model.updatemetadata()
710
+ >>> # Creates model_meta.json with loss, val_loss, raw_error, and pred_error
711
+ """
318
712
  self.infodict["loss"] = self.loss
319
713
  self.infodict["val_loss"] = self.val_loss
320
714
  self.infodict["raw_error"] = self.raw_error
321
715
  self.infodict["prediction_error"] = self.pred_error
322
716
  tide_io.writedicttojson(self.infodict, os.path.join(self.modelname, "model_meta.json"))
323
717
 
324
- def savemodel(self, altname=None):
718
+ def savemodel(self, altname: str | None = None) -> None:
719
+ """
720
+ Save the model to disk with the specified name.
721
+
722
+ This method saves the current model to a Keras file format (.keras) in a
723
+ directory named according to the model name or an alternative name provided.
724
+
725
+ Parameters
726
+ ----------
727
+ altname : str, optional
728
+ Alternative name to use for saving the model. If None, uses the
729
+ model's default name stored in `self.modelname`. Default is None.
730
+
731
+ Returns
732
+ -------
733
+ None
734
+ This method does not return any value.
735
+
736
+ Notes
737
+ -----
738
+ The model is saved in the Keras format (.keras) and stored in a directory
739
+ with the same name as the model. The method logs the saving operation
740
+ using the logger instance `LGR`.
741
+
742
+ Examples
743
+ --------
744
+ >>> # Save model with default name
745
+ >>> savemodel()
746
+ >>>
747
+ >>> # Save model with alternative name
748
+ >>> savemodel(altname="my_custom_model")
749
+ """
325
750
  if altname is None:
326
751
  modelsavename = self.modelname
327
752
  else:
@@ -329,7 +754,51 @@ class DeepLearningFilter:
329
754
  LGR.info(f"saving {modelsavename}")
330
755
  self.model.save(os.path.join(modelsavename, "model.keras"))
331
756
 
332
- def loadmodel(self, modelname, verbose=False):
757
+ def loadmodel(self, modelname: str, verbose: bool = False) -> None:
758
+ """
759
+ Load a trained model from disk and initialize model parameters.
760
+
761
+ Load a Keras model from the specified model directory, along with associated
762
+ metadata and configuration information. The function attempts to load the model
763
+ in Keras format first, falling back to HDF5 format if the Keras format is not found.
764
+
765
+ Parameters
766
+ ----------
767
+ modelname : str
768
+ Name of the model to load, corresponding to a subdirectory in ``self.modelpath``.
769
+ verbose : bool, optional
770
+ If True, print model summary and metadata information. Default is False.
771
+
772
+ Returns
773
+ -------
774
+ None
775
+ This method modifies the instance attributes in-place and does not return anything.
776
+
777
+ Notes
778
+ -----
779
+ The function attempts to load the model in the following order:
780
+ 1. Keras format (``model.keras``)
781
+ 2. HDF5 format (``model.h5``)
782
+
783
+ If neither format is found, the function exits with an error message.
784
+
785
+ The loaded model metadata is stored in ``self.infodict``, and model configuration
786
+ is stored in ``self.config``. Additional attributes like ``window_size`` and ``usebadpts``
787
+ are extracted from the metadata and stored as instance attributes.
788
+
789
+ Examples
790
+ --------
791
+ >>> loader = ModelLoader()
792
+ >>> loader.loadmodel("my_model", verbose=True)
793
+ loading my_model
794
+ Model: "sequential"
795
+ _________________________________________________________________
796
+ Layer (type) Output Shape Param #
797
+ =================================================================
798
+ ...
799
+ >>> print(loader.window_size)
800
+ 100
801
+ """
333
802
  # read in the data
334
803
  LGR.info(f"loading {modelname}")
335
804
  try:
@@ -361,7 +830,41 @@ class DeepLearningFilter:
361
830
  self.trained = True
362
831
  LGR.info(f"{modelname} loaded")
363
832
 
364
- def initialize(self):
833
+ def initialize(self) -> None:
834
+ """
835
+ Initialize the model by setting up network architecture and metadata.
836
+
837
+ This method performs a series of initialization steps including retrieving
838
+ the model name, creating the network architecture, displaying model summary,
839
+ saving the model configuration, initializing metadata, and setting appropriate
840
+ flags to indicate initialization status.
841
+
842
+ Parameters
843
+ ----------
844
+ self : object
845
+ The instance of the model class being initialized.
846
+
847
+ Returns
848
+ -------
849
+ None
850
+ This method does not return any value.
851
+
852
+ Notes
853
+ -----
854
+ This method should be called before any training or prediction operations.
855
+ The initialization process sets `self.initialized` to True and `self.trained`
856
+ to False, indicating that the model is ready for training but has not been
857
+ trained yet.
858
+
859
+ Examples
860
+ --------
861
+ >>> model = MyModel()
862
+ >>> model.initialize()
863
+ >>> print(model.initialized)
864
+ True
865
+ >>> print(model.trained)
866
+ False
867
+ """
365
868
  self.getname()
366
869
  self.makenet()
367
870
  self.model.summary()
@@ -370,7 +873,47 @@ class DeepLearningFilter:
370
873
  self.initialized = True
371
874
  self.trained = False
372
875
 
373
- def train(self):
876
+ def train(self) -> None:
877
+ """
878
+ Train the model using the provided training and validation datasets.
879
+
880
+ This method performs model training with optional pretraining and logging. It supports
881
+ TensorBoard logging, model checkpointing, early stopping, and NaN termination. The trained
882
+ model is saved at the end of training.
883
+
884
+ Parameters
885
+ ----------
886
+ self : object
887
+ The instance of the class containing the model and training configuration.
888
+ Expected attributes include:
889
+ - `model`: The Keras model to be trained.
890
+ - `train_x`, `train_y`: Training data inputs and labels.
891
+ - `val_x`, `val_y`: Validation data inputs and labels.
892
+ - `modelname`: Name of the model for saving purposes.
893
+ - `usetensorboard`: Boolean flag to enable TensorBoard logging.
894
+ - `num_pretrain_epochs`: Number of epochs for pretraining phase.
895
+ - `num_epochs`: Total number of training epochs.
896
+ - `savemodel()`: Method to save the trained model.
897
+
898
+ Returns
899
+ -------
900
+ None
901
+ This function does not return any value.
902
+
903
+ Notes
904
+ -----
905
+ - If `self.usetensorboard` is True, TensorBoard logging is enabled.
906
+ - If `self.num_pretrain_epochs` is greater than 0, a pretraining phase is performed
907
+ before the main training loop.
908
+ - The model is saved after training using the `savemodel()` method.
909
+ - Training uses `ModelCheckpoint`, `EarlyStopping`, and `TerminateOnNaN` callbacks
910
+ to manage training process and prevent overfitting or NaN issues.
911
+
912
+ Examples
913
+ --------
914
+ >>> trainer = ModelTrainer(model, train_x, train_y, val_x, val_y)
915
+ >>> trainer.train()
916
+ """
374
917
  self.intermediatemodelpath = os.path.join(
375
918
  self.modelname, "model_e{epoch:02d}_v{val_loss:.4f}.keras"
376
919
  )
@@ -421,7 +964,43 @@ class DeepLearningFilter:
421
964
  self.savemodel()
422
965
  self.trained = True
423
966
 
424
- def apply(self, inputdata, badpts=None):
967
+ def apply(self, inputdata: np.ndarray, badpts: np.ndarray | None = None) -> np.ndarray:
968
+ """
969
+ Apply a sliding-window prediction model to the input data, optionally incorporating bad points.
970
+
971
+ This function performs a sliding-window prediction using a pre-trained model. It scales the input
972
+ data using the median absolute deviation (MAD), applies the model to overlapping windows of data,
973
+ and aggregates predictions with a weighted scheme. Optionally, bad points can be included in
974
+ the prediction process to influence the model's behavior.
975
+
976
+ Parameters
977
+ ----------
978
+ inputdata : np.ndarray
979
+ Input data array of shape (N,) to be processed.
980
+ badpts : np.ndarray | None, optional
981
+ Array of same shape as `inputdata` indicating bad or invalid points. If None, no bad points
982
+ are considered. Default is None.
983
+
984
+ Returns
985
+ -------
986
+ np.ndarray
987
+ Predicted data array of the same shape as `inputdata`, with predictions aggregated and
988
+ weighted across overlapping windows.
989
+
990
+ Notes
991
+ -----
992
+ - The function uses a sliding window of size `self.window_size` to process input data.
993
+ - Predictions are aggregated by summing over overlapping windows.
994
+ - A triangular weight scheme is applied to the aggregated predictions to reduce edge effects.
995
+ - If `self.usebadpts` is True, `badpts` are included as an additional feature in the model input.
996
+
997
+ Examples
998
+ --------
999
+ >>> model = MyModel(window_size=10, usebadpts=True)
1000
+ >>> input_data = np.random.randn(100)
1001
+ >>> bad_points = np.zeros_like(input_data)
1002
+ >>> result = model.apply(input_data, bad_points)
1003
+ """
425
1004
  initscale = mad(inputdata)
426
1005
  scaleddata = inputdata / initscale
427
1006
  predicteddata = scaleddata * 0.0
@@ -460,14 +1039,104 @@ class MultiscaleCNNDLFilter(DeepLearningFilter):
460
1039
  # it takes a time series as an input, performs 1-D convolution, and returns it as an output ready for concatenation
461
1040
  def __init__(
462
1041
  self,
463
- num_filters=10,
464
- kernel_sizes=[4, 8, 12],
465
- input_lens=[64, 128, 192],
466
- input_width=1,
467
- dilation_rate=1,
1042
+ num_filters: int = 10,
1043
+ kernel_sizes: list[int] = [4, 8, 12],
1044
+ input_lens: list[int] = [64, 128, 192],
1045
+ input_width: int = 1,
1046
+ dilation_rate: int = 1,
468
1047
  *args,
469
1048
  **kwargs,
470
- ):
1049
+ ) -> None:
1050
+ """
1051
+ Initialize the MultiscaleCNNDLFilter.
1052
+
1053
+ This constructor initializes a multiscale CNN filter with specified parameters
1054
+ for processing sequential data with multiple kernel sizes and dilation rates.
1055
+
1056
+ Parameters
1057
+ ----------
1058
+ num_filters : int, optional
1059
+ Number of filters to use in the convolutional layers. Default is 10.
1060
+ kernel_sizes : list of int, optional
1061
+ List of kernel sizes to use for different convolutional layers.
1062
+ Default is [4, 8, 12].
1063
+ input_lens : list of int, optional
1064
+ List of input sequence lengths to process. Default is [64, 128, 192].
1065
+ input_width : int, optional
1066
+ Width of the input data (number of input channels). Default is 1.
1067
+ dilation_rate : int, optional
1068
+ Dilation rate for the convolutional layers. Default is 1.
1069
+ *args
1070
+ Variable length argument list passed to parent class.
1071
+ **kwargs
1072
+ Arbitrary keyword arguments passed to parent class.
1073
+
1074
+ Returns
1075
+ -------
1076
+ None
1077
+ This method initializes the object and does not return any value.
1078
+
1079
+ Notes
1080
+ -----
1081
+ The initialized object will store network configuration information in
1082
+ `infodict` including network type, number of filters, kernel sizes, input lengths,
1083
+ and input width. The parent class initialization is called using `super()`.
1084
+
1085
+ Examples
1086
+ --------
1087
+ >>> filter = MultiscaleCNNDLFilter(
1088
+ ... num_filters=20,
1089
+ ... kernel_sizes=[3, 6, 9],
1090
+ ... input_lens=[32, 64, 128],
1091
+ ... input_width=2,
1092
+ ... dilation_rate=2
1093
+ ... )
1094
+ """
1095
+ """
1096
+ Initialize the MultiscaleCNNDLFilter.
1097
+
1098
+ This constructor initializes a multiscale CNN filter with specified parameters
1099
+ for processing sequential data with multiple kernel sizes and dilation rates.
1100
+
1101
+ Parameters
1102
+ ----------
1103
+ num_filters : int, optional
1104
+ Number of filters to use in the convolutional layers, default is 10
1105
+ kernel_sizes : list of int, optional
1106
+ List of kernel sizes to use for different convolutional layers,
1107
+ default is [4, 8, 12]
1108
+ input_lens : list of int, optional
1109
+ List of input sequence lengths to process, default is [64, 128, 192]
1110
+ input_width : int, optional
1111
+ Width of the input data (number of input channels), default is 1
1112
+ dilation_rate : int, optional
1113
+ Dilation rate for the convolutional layers, default is 1
1114
+ *args
1115
+ Variable length argument list passed to parent class
1116
+ **kwargs
1117
+ Arbitrary keyword arguments passed to parent class
1118
+
1119
+ Returns
1120
+ -------
1121
+ None
1122
+ This method initializes the object and does not return any value
1123
+
1124
+ Notes
1125
+ -----
1126
+ The initialized object will store network configuration information in
1127
+ `infodict` including network type, number of filters, kernel sizes, input lengths,
1128
+ and input width. The parent class initialization is called using super().
1129
+
1130
+ Examples
1131
+ --------
1132
+ >>> filter = MultiscaleCNNDLFilter(
1133
+ ... num_filters=20,
1134
+ ... kernel_sizes=[3, 6, 9],
1135
+ ... input_lens=[32, 64, 128],
1136
+ ... input_width=2,
1137
+ ... dilation_rate=2
1138
+ ... )
1139
+ """
471
1140
  self.num_filters = num_filters
472
1141
  self.kernel_sizes = kernel_sizes
473
1142
  self.input_lens = input_lens
@@ -481,10 +1150,74 @@ class MultiscaleCNNDLFilter(DeepLearningFilter):
481
1150
  super(MultiscaleCNNDLFilter, self).__init__(*args, **kwargs)
482
1151
 
483
1152
  def getname(self):
1153
+ """
1154
+ Generate and return model name based on configuration parameters.
1155
+
1156
+ This method constructs a descriptive model name by joining various configuration
1157
+ parameters with specific prefixes and zero-padded numbers. The generated name
1158
+ is used to create a unique model identifier and corresponding directory path.
1159
+
1160
+ Parameters
1161
+ ----------
1162
+ self : object
1163
+ The instance of the class containing the following attributes:
1164
+
1165
+ - window_size : int
1166
+ Size of the input window
1167
+ - num_layers : int
1168
+ Number of layers in the model
1169
+ - num_filters : int
1170
+ Number of filters in the model
1171
+ - kernel_size : int
1172
+ Size of the convolutional kernel
1173
+ - num_epochs : int
1174
+ Number of training epochs
1175
+ - excludethresh : float
1176
+ Threshold for excluding data points
1177
+ - corrthresh : float
1178
+ Correlation threshold for filtering
1179
+ - step : int
1180
+ Step size for processing
1181
+ - dilation_rate : int
1182
+ Dilation rate for convolutional layers
1183
+ - activation : str
1184
+ Activation function name
1185
+ - usebadpts : bool
1186
+ Whether to use bad points in training
1187
+ - excludebysubject : bool
1188
+ Whether to exclude data by subject
1189
+ - namesuffix : str, optional
1190
+ Additional suffix to append to the model name
1191
+ - modelroot : str
1192
+ Root directory for model storage
1193
+
1194
+ Returns
1195
+ -------
1196
+ None
1197
+ This method modifies the instance attributes `modelname` and `modelpath`
1198
+ but does not return any value.
1199
+
1200
+ Notes
1201
+ -----
1202
+ The generated model name follows this format:
1203
+ "model_multiscalecnn_tf2_wXxx_lYy_fnZz_flZz_eXxx_tY_ctZ_sZ_dZ_activation[_usebadpts][_excludebysubject][_suffix]"
1204
+
1205
+ Where Xxx, Yy, Zz, etc. represent zero-padded numbers based on the parameter values.
1206
+
1207
+ Examples
1208
+ --------
1209
+ >>> model = MyModel()
1210
+ >>> model.window_size = 100
1211
+ >>> model.num_layers = 5
1212
+ >>> model.getname()
1213
+ >>> print(model.modelname)
1214
+ 'model_multiscalecnn_tf2_w100_l05_fn05_fl05_e001_t0.5_ct0.8_s1_d1_relu'
1215
+ """
484
1216
  self.modelname = "_".join(
485
1217
  [
486
1218
  "model",
487
1219
  "multiscalecnn",
1220
+ "tf2",
488
1221
  "w" + str(self.window_size).zfill(3),
489
1222
  "l" + str(self.num_layers).zfill(2),
490
1223
  "fn" + str(self.num_filters).zfill(2),
@@ -511,6 +1244,41 @@ class MultiscaleCNNDLFilter(DeepLearningFilter):
511
1244
  pass
512
1245
 
513
1246
  def makesubnet(self, inputlen, kernelsize):
1247
+ """
1248
+ Create a 1D convolutional neural network submodel for time series processing.
1249
+
1250
+ This function constructs a neural network submodel that processes time series data
1251
+ through 1D convolutional layers followed by global max pooling and dense layers
1252
+ with dropout regularization. The model is designed for feature extraction from
1253
+ sequential data.
1254
+
1255
+ Parameters
1256
+ ----------
1257
+ inputlen : int
1258
+ Length of the input time series sequence.
1259
+ kernelsize : int
1260
+ Size of the convolutional kernel for 1D convolution operation.
1261
+
1262
+ Returns
1263
+ -------
1264
+ Model
1265
+ Keras Model object representing the constructed submodel with the following structure:
1266
+ Input -> Conv1D -> GlobalMaxPool1D -> Dense -> Dropout -> Dense -> Output
1267
+
1268
+ Notes
1269
+ -----
1270
+ The model architecture includes:
1271
+ - 1D convolution with tanh activation
1272
+ - Global max pooling for sequence reduction
1273
+ - Two dense layers with tanh activation
1274
+ - Dropout regularization (0.3) after first dense layer
1275
+ - Uses 'same' padding for convolutional layer
1276
+
1277
+ Examples
1278
+ --------
1279
+ >>> model = makesubnet(inputlen=100, kernelsize=3)
1280
+ >>> model.summary()
1281
+ """
514
1282
  # the input is a time series of length input_len and width input_width
515
1283
  input_seq = Input(shape=(inputlen, self.input_width))
516
1284
 
@@ -527,6 +1295,48 @@ class MultiscaleCNNDLFilter(DeepLearningFilter):
527
1295
  return basemodel
528
1296
 
529
1297
  def makenet(self):
1298
+ """
1299
+ Create a multi-scale neural network for time series analysis.
1300
+
1301
+ This function constructs a neural network model that processes time series data at
1302
+ multiple resolutions (original, medium, and small scale). The model uses separate
1303
+ sub-networks for each resolution level and concatenates their outputs to make
1304
+ predictions. The architecture leverages different kernel sizes for different
1305
+ down-sampled versions to capture features at multiple temporal scales.
1306
+
1307
+ Parameters
1308
+ ----------
1309
+ self : object
1310
+ The instance containing the following attributes:
1311
+ - inputs_lens : list of int
1312
+ Lengths of input sequences for small, medium, and original scales.
1313
+ - input_width : int
1314
+ Width of input features.
1315
+ - kernel_sizes : list of int
1316
+ Kernel sizes for convolutional layers corresponding to each scale.
1317
+ - makesubnet : callable
1318
+ Function to create sub-network for a given sequence length and kernel size.
1319
+
1320
+ Returns
1321
+ -------
1322
+ None
1323
+ This method modifies the instance in-place by setting the `model` attribute
1324
+ to the constructed Keras model.
1325
+
1326
+ Notes
1327
+ -----
1328
+ The model architecture:
1329
+ 1. Takes three inputs at different resolutions.
1330
+ 2. Processes each input through separate sub-networks with scale-specific kernels.
1331
+ 3. Concatenates the embeddings from all branches.
1332
+ 4. Applies a final dense layer with sigmoid activation for binary classification.
1333
+
1334
+ Examples
1335
+ --------
1336
+ >>> # Assuming self is an instance with proper attributes set
1337
+ >>> self.makenet()
1338
+ >>> print(self.model.summary())
1339
+ """
530
1340
  # the inputs to the branches are the original time series, and its down-sampled versions
531
1341
  input_smallseq = Input(shape=(self.inputs_lens[0], self.input_width))
532
1342
  input_medseq = Input(shape=(self.inputs_lens[1], self.input_width))
@@ -548,7 +1358,48 @@ class MultiscaleCNNDLFilter(DeepLearningFilter):
548
1358
 
549
1359
 
550
1360
  class CNNDLFilter(DeepLearningFilter):
551
- def __init__(self, num_filters=10, kernel_size=5, dilation_rate=1, *args, **kwargs):
1361
+ def __init__(
1362
+ self,
1363
+ num_filters: int = 10,
1364
+ kernel_size: int = 5,
1365
+ dilation_rate: int = 1,
1366
+ *args,
1367
+ **kwargs,
1368
+ ) -> None:
1369
+ """
1370
+ Initialize the CNNDLFilter layer.
1371
+
1372
+ Parameters
1373
+ ----------
1374
+ num_filters : int, optional
1375
+ Number of convolutional filters to use, by default 10.
1376
+ kernel_size : int, optional
1377
+ Size of the convolutional kernel, by default 5.
1378
+ dilation_rate : int, optional
1379
+ Dilation rate for the convolutional layer, by default 1.
1380
+ *args
1381
+ Variable length argument list passed to parent class.
1382
+ **kwargs
1383
+ Arbitrary keyword arguments passed to parent class.
1384
+
1385
+ Returns
1386
+ -------
1387
+ None
1388
+ This method initializes the layer and does not return any value.
1389
+
1390
+ Notes
1391
+ -----
1392
+ This constructor sets up a convolutional layer with specified parameters
1393
+ and registers the network type as "cnn" in the infodict. The dilation rate
1394
+ controls the spacing between kernel points, allowing for wider receptive
1395
+ fields without increasing the number of parameters.
1396
+
1397
+ Examples
1398
+ --------
1399
+ >>> layer = CNNDLFilter(num_filters=32, kernel_size=3, dilation_rate=2)
1400
+ >>> print(layer.num_filters)
1401
+ 32
1402
+ """
552
1403
  self.num_filters = num_filters
553
1404
  self.kernel_size = kernel_size
554
1405
  self.dilation_rate = dilation_rate
@@ -558,10 +1409,79 @@ class CNNDLFilter(DeepLearningFilter):
558
1409
  super(CNNDLFilter, self).__init__(*args, **kwargs)
559
1410
 
560
1411
  def getname(self):
1412
+ """
1413
+ Generate and return the model name based on configuration parameters.
1414
+
1415
+ This method constructs a descriptive model name by joining various configuration
1416
+ parameters with specific prefixes and zero-padded numbers. The resulting name
1417
+ is used to create a unique directory path for model storage.
1418
+
1419
+ Parameters
1420
+ ----------
1421
+ self : object
1422
+ The instance of the class containing model configuration parameters.
1423
+ Expected attributes include:
1424
+ - window_size : int
1425
+ - num_layers : int
1426
+ - num_filters : int
1427
+ - kernel_size : int
1428
+ - num_epochs : int
1429
+ - excludethresh : float
1430
+ - corrthresh : float
1431
+ - step : int
1432
+ - dilation_rate : int
1433
+ - activation : str
1434
+ - modelroot : str
1435
+ - usebadpts : bool
1436
+ - excludebysubject : bool
1437
+ - namesuffix : str, optional
1438
+
1439
+ Returns
1440
+ -------
1441
+ None
1442
+ This method does not return a value but sets the following attributes:
1443
+ - `self.modelname`: str, the constructed model name
1444
+ - `self.modelpath`: str, the full path to the model directory
1445
+
1446
+ Notes
1447
+ -----
1448
+ The generated model name follows this format:
1449
+ "model_cnn_tf2_wXXX_lYY_fnZZ_flZZ_eXXX_tY_ctZ_sZ_dZ_activation[_usebadpts][_excludebysubject][_suffix]"
1450
+
1451
+ Where:
1452
+ - XXX: window_size (3-digit zero-padded)
1453
+ - YY: num_layers (2-digit zero-padded)
1454
+ - ZZ: num_filters (2-digit zero-padded)
1455
+ - ZZ: kernel_size (2-digit zero-padded)
1456
+ - XXX: num_epochs (3-digit zero-padded)
1457
+ - Y: excludethresh (single digit)
1458
+ - Z: corrthresh (single digit)
1459
+ - Z: step (single digit)
1460
+ - Z: dilation_rate (single digit)
1461
+
1462
+ Examples
1463
+ --------
1464
+ >>> model = MyModel()
1465
+ >>> model.window_size = 100
1466
+ >>> model.num_layers = 5
1467
+ >>> model.num_filters = 32
1468
+ >>> model.kernel_size = 3
1469
+ >>> model.num_epochs = 1000
1470
+ >>> model.excludethresh = 0.5
1471
+ >>> model.corrthresh = 0.8
1472
+ >>> model.step = 1
1473
+ >>> model.dilation_rate = 2
1474
+ >>> model.activation = "relu"
1475
+ >>> model.modelroot = "./models"
1476
+ >>> model.getname()
1477
+ >>> print(model.modelname)
1478
+ 'model_cnn_tf2_w100_l05_fn32_fl03_e1000_t05_ct08_s1_d2_relu'
1479
+ """
561
1480
  self.modelname = "_".join(
562
1481
  [
563
1482
  "model",
564
1483
  "cnn",
1484
+ "tf2",
565
1485
  "w" + str(self.window_size).zfill(3),
566
1486
  "l" + str(self.num_layers).zfill(2),
567
1487
  "fn" + str(self.num_filters).zfill(2),
@@ -588,6 +1508,63 @@ class CNNDLFilter(DeepLearningFilter):
588
1508
  pass
589
1509
 
590
1510
  def makenet(self):
1511
+ """
1512
+ Create and configure a 1D convolutional neural network model.
1513
+
1514
+ This method builds a sequential CNN architecture with multiple convolutional layers,
1515
+ batch normalization, dropout regularization, and ReLU activation functions. The network
1516
+ is designed for sequence-to-sequence mapping with skip connections.
1517
+
1518
+ Parameters
1519
+ ----------
1520
+ self : object
1521
+ The instance of the class containing the model configuration parameters.
1522
+ Expected attributes include:
1523
+ - num_filters : int
1524
+ Number of convolutional filters in each layer.
1525
+ - kernel_size : int
1526
+ Size of the convolutional kernel.
1527
+ - inputsize : int
1528
+ Size of the input sequence.
1529
+ - num_layers : int
1530
+ Total number of layers in the network.
1531
+ - dilation_rate : int
1532
+ Dilation rate for dilated convolutions.
1533
+ - dropout_rate : float
1534
+ Dropout rate for regularization.
1535
+ - activation : str or callable
1536
+ Activation function to use.
1537
+
1538
+ Returns
1539
+ -------
1540
+ None
1541
+ This method modifies the instance's model attribute in-place and does not return anything.
1542
+
1543
+ Notes
1544
+ -----
1545
+ The network architecture follows this pattern:
1546
+ - Input layer with Conv1D, BatchNormalization, Dropout, and Activation
1547
+ - Intermediate layers with Conv1D, BatchNormalization, Dropout, and Activation
1548
+ - Output layer with Conv1D matching the input size
1549
+ - Model compiled with RMSprop optimizer and MSE loss
1550
+
1551
+ Examples
1552
+ --------
1553
+ >>> class MyModel:
1554
+ ... def __init__(self):
1555
+ ... self.num_filters = 64
1556
+ ... self.kernel_size = 3
1557
+ ... self.inputsize = 100
1558
+ ... self.num_layers = 5
1559
+ ... self.dilation_rate = 2
1560
+ ... self.dropout_rate = 0.2
1561
+ ... self.activation = 'relu'
1562
+ ... self.model = None
1563
+ ...
1564
+ >>> model = MyModel()
1565
+ >>> model.makenet()
1566
+ >>> print(model.model.summary())
1567
+ """
591
1568
  self.model = Sequential()
592
1569
 
593
1570
  # make the input layer
@@ -625,17 +1602,108 @@ class CNNDLFilter(DeepLearningFilter):
625
1602
 
626
1603
 
627
1604
  class DenseAutoencoderDLFilter(DeepLearningFilter):
628
- def __init__(self, encoding_dim=10, *args, **kwargs):
1605
+ def __init__(self, encoding_dim: int = 10, *args, **kwargs) -> None:
1606
+ """
1607
+ Initialize the DenseAutoencoderDLFilter.
1608
+
1609
+ Parameters
1610
+ ----------
1611
+ encoding_dim : int, default=10
1612
+ The dimensionality of the encoding layer in the autoencoder.
1613
+ *args
1614
+ Variable length argument list passed to the parent class constructor.
1615
+ **kwargs
1616
+ Arbitrary keyword arguments passed to the parent class constructor.
1617
+
1618
+ Returns
1619
+ -------
1620
+ None
1621
+ This method initializes the instance and does not return any value.
1622
+
1623
+ Notes
1624
+ -----
1625
+ This constructor sets up the autoencoder architecture by:
1626
+ 1. Storing the encoding dimension as an instance attribute
1627
+ 2. Updating the infodict with network type and encoding dimension information
1628
+ 3. Calling the parent class constructor with passed arguments
1629
+
1630
+ Examples
1631
+ --------
1632
+ >>> filter = DenseAutoencoderDLFilter(encoding_dim=20)
1633
+ >>> print(filter.encoding_dim)
1634
+ 20
1635
+ """
629
1636
  self.encoding_dim = encoding_dim
630
1637
  self.infodict["nettype"] = "autoencoder"
631
1638
  self.infodict["encoding_dim"] = self.encoding_dim
632
1639
  super(DenseAutoencoderDLFilter, self).__init__(*args, **kwargs)
633
1640
 
634
1641
  def getname(self):
1642
+ """
1643
+ Generate and return model name based on configuration parameters.
1644
+
1645
+ This method constructs a descriptive model name by joining various configuration
1646
+ parameters with specific prefixes and formatting conventions. The generated name
1647
+ is used to create a unique identifier for the model and its corresponding directory
1648
+ path.
1649
+
1650
+ Parameters
1651
+ ----------
1652
+ self : object
1653
+ The instance of the class containing the model configuration attributes.
1654
+ Expected attributes include:
1655
+ - `window_size`: int, size of the window
1656
+ - `encoding_dim`: int, dimension of the encoding layer
1657
+ - `num_epochs`: int, number of training epochs
1658
+ - `excludethresh`: float, threshold for exclusion
1659
+ - `corrthresh`: float, correlation threshold
1660
+ - `step`: int, step size
1661
+ - `activation`: str, activation function name
1662
+ - `modelroot`: str, root directory for models
1663
+ - `usebadpts`: bool, flag to include bad points
1664
+ - `excludebysubject`: bool, flag to exclude by subject
1665
+ - `namesuffix`: str, optional suffix to append to the model name
1666
+
1667
+ Returns
1668
+ -------
1669
+ None
1670
+ This method does not return a value but sets the following attributes:
1671
+ - `self.modelname`: str, the generated model name
1672
+ - `self.modelpath`: str, the full path to the model directory
1673
+
1674
+ Notes
1675
+ -----
1676
+ The model name is constructed using the following components:
1677
+ - "model_denseautoencoder_tf2" as base identifier
1678
+ - Window size with 3-digit zero-padded formatting (wXXX)
1679
+ - Encoding dimension with 3-digit zero-padded formatting (enXXX)
1680
+ - Number of epochs with 3-digit zero-padded formatting (eXXX)
1681
+ - Exclusion threshold (tX.XX)
1682
+ - Correlation threshold (ctX.XX)
1683
+ - Step size (sX)
1684
+ - Activation function name
1685
+ - Optional suffixes based on configuration flags
1686
+
1687
+ Examples
1688
+ --------
1689
+ >>> model = MyModel()
1690
+ >>> model.window_size = 100
1691
+ >>> model.encoding_dim = 50
1692
+ >>> model.num_epochs = 1000
1693
+ >>> model.excludethresh = 0.5
1694
+ >>> model.corrthresh = 0.8
1695
+ >>> model.step = 10
1696
+ >>> model.activation = 'relu'
1697
+ >>> model.modelroot = '/models'
1698
+ >>> model.getname()
1699
+ >>> print(model.modelname)
1700
+ 'model_denseautoencoder_tf2_w100_en050_e1000_t0.5_ct00.8_s10_relu'
1701
+ """
635
1702
  self.modelname = "_".join(
636
1703
  [
637
1704
  "model",
638
1705
  "denseautoencoder",
1706
+ "tf2",
639
1707
  "w" + str(self.window_size).zfill(3),
640
1708
  "en" + str(self.encoding_dim).zfill(3),
641
1709
  "e" + str(self.num_epochs).zfill(3),
@@ -659,6 +1727,56 @@ class DenseAutoencoderDLFilter(DeepLearningFilter):
659
1727
  pass
660
1728
 
661
1729
  def makenet(self):
1730
+ """
1731
+ Create and compile a neural network model for autoencoding.
1732
+
1733
+ This function constructs a symmetric autoencoder architecture with configurable
1734
+ number of layers, encoding dimension, and activation function. The network
1735
+ consists of an input layer, multiple encoding layers, an encoding layer,
1736
+ decoding layers, and an output layer. Batch normalization, dropout, and
1737
+ activation functions are applied at each layer as specified by the instance
1738
+ attributes.
1739
+
1740
+ Parameters
1741
+ ----------
1742
+ self : object
1743
+ The instance of the class containing the following attributes:
1744
+ - num_layers : int
1745
+ Number of layers in the network.
1746
+ - encoding_dim : int
1747
+ Dimension of the encoding layer.
1748
+ - inputsize : int
1749
+ Size of the input data.
1750
+ - dropout_rate : float
1751
+ Dropout rate applied to all layers.
1752
+ - activation : str or callable
1753
+ Activation function used in all layers.
1754
+ - model : keras.Sequential
1755
+ The constructed Keras model (assigned within the function).
1756
+
1757
+ Returns
1758
+ -------
1759
+ None
1760
+ This function does not return a value but assigns the constructed model
1761
+ to the instance attribute `self.model`.
1762
+
1763
+ Notes
1764
+ -----
1765
+ - The network architecture is symmetric, with the number of units in each
1766
+ layer following a pattern that doubles or halves based on the layer index.
1767
+ - The model is compiled with the RMSprop optimizer and mean squared error loss.
1768
+
1769
+ Examples
1770
+ --------
1771
+ >>> autoencoder = AutoEncoder()
1772
+ >>> autoencoder.num_layers = 4
1773
+ >>> autoencoder.encoding_dim = 32
1774
+ >>> autoencoder.inputsize = 784
1775
+ >>> autoencoder.dropout_rate = 0.2
1776
+ >>> autoencoder.activation = 'relu'
1777
+ >>> autoencoder.makenet()
1778
+ >>> autoencoder.model.summary()
1779
+ """
662
1780
  self.model = Sequential()
663
1781
 
664
1782
  # make the input layer
@@ -705,8 +1823,51 @@ class DenseAutoencoderDLFilter(DeepLearningFilter):
705
1823
 
706
1824
  class ConvAutoencoderDLFilter(DeepLearningFilter):
707
1825
  def __init__(
708
- self, encoding_dim=10, num_filters=5, kernel_size=5, dilation_rate=1, *args, **kwargs
709
- ):
1826
+ self,
1827
+ encoding_dim: int = 10,
1828
+ num_filters: int = 5,
1829
+ kernel_size: int = 5,
1830
+ dilation_rate: int = 1,
1831
+ *args,
1832
+ **kwargs,
1833
+ ) -> None:
1834
+ """
1835
+ Initialize ConvAutoencoderDLFilter.
1836
+
1837
+ Parameters
1838
+ ----------
1839
+ encoding_dim : int, optional
1840
+ Dimension of the encoding layer, by default 10.
1841
+ num_filters : int, optional
1842
+ Number of filters in the convolutional layers, by default 5.
1843
+ kernel_size : int, optional
1844
+ Size of the convolutional kernel, by default 5.
1845
+ dilation_rate : int, optional
1846
+ Dilation rate for the convolutional layers, by default 1.
1847
+ *args
1848
+ Variable length argument list.
1849
+ **kwargs
1850
+ Arbitrary keyword arguments.
1851
+
1852
+ Returns
1853
+ -------
1854
+ None
1855
+ This method does not return any value.
1856
+
1857
+ Notes
1858
+ -----
1859
+ This constructor initializes the ConvAutoencoderDLFilter with specified
1860
+ convolutional parameters and sets up the infodict with network metadata.
1861
+
1862
+ Examples
1863
+ --------
1864
+ >>> model = ConvAutoencoderDLFilter(
1865
+ ... encoding_dim=15,
1866
+ ... num_filters=8,
1867
+ ... kernel_size=3,
1868
+ ... dilation_rate=2
1869
+ ... )
1870
+ """
710
1871
  self.encoding_dim = encoding_dim
711
1872
  self.num_filters = num_filters
712
1873
  self.kernel_size = kernel_size
@@ -718,10 +1879,72 @@ class ConvAutoencoderDLFilter(DeepLearningFilter):
718
1879
  super(ConvAutoencoderDLFilter, self).__init__(*args, **kwargs)
719
1880
 
720
1881
  def getname(self):
1882
+ """
1883
+ Generate and configure the model name and path based on current configuration parameters.
1884
+
1885
+ This method constructs a descriptive model name string using various configuration
1886
+ parameters and creates the corresponding directory path for model storage. The generated
1887
+ name includes information about window size, encoding dimensions, filter settings,
1888
+ training parameters, and optional flags.
1889
+
1890
+ Parameters
1891
+ ----------
1892
+ self : object
1893
+ The instance containing configuration parameters for model naming.
1894
+ Expected attributes include:
1895
+ - window_size : int
1896
+ - encoding_dim : int
1897
+ - num_filters : int
1898
+ - kernel_size : int
1899
+ - num_epochs : int
1900
+ - excludethresh : float
1901
+ - corrthresh : float
1902
+ - step : int
1903
+ - activation : str
1904
+ - usebadpts : bool
1905
+ - excludebysubject : bool
1906
+ - namesuffix : str or None
1907
+ - modelroot : str
1908
+
1909
+ Returns
1910
+ -------
1911
+ None
1912
+ This method modifies the instance attributes in-place and does not return a value.
1913
+ Modifies the following instance attributes:
1914
+ - modelname : str
1915
+ - modelpath : str
1916
+
1917
+ Notes
1918
+ -----
1919
+ The generated model name follows a specific naming convention:
1920
+ "model_convautoencoder_tf2_wXXX_enYYY_fnZZ_flZZ_eXXX_tY_ctZ_sZ_activation"
1921
+ where XXX, YYY, ZZ, and Z represent zero-padded numerical values.
1922
+
1923
+ Examples
1924
+ --------
1925
+ >>> model = MyModel()
1926
+ >>> model.window_size = 100
1927
+ >>> model.encoding_dim = 50
1928
+ >>> model.num_filters = 32
1929
+ >>> model.kernel_size = 5
1930
+ >>> model.num_epochs = 1000
1931
+ >>> model.excludethresh = 0.5
1932
+ >>> model.corrthresh = 0.8
1933
+ >>> model.step = 10
1934
+ >>> model.activation = 'relu'
1935
+ >>> model.usebadpts = True
1936
+ >>> model.excludebysubject = False
1937
+ >>> model.namesuffix = 'test'
1938
+ >>> model.modelroot = '/path/to/models'
1939
+ >>> model.getname()
1940
+ >>> print(model.modelname)
1941
+ 'model_convautoencoder_tf2_w100_en050_fn32_fl05_e1000_t0.5_ct0.8_s10_relu_usebadpts_test'
1942
+ """
721
1943
  self.modelname = "_".join(
722
1944
  [
723
1945
  "model",
724
1946
  "convautoencoder",
1947
+ "tf2",
725
1948
  "w" + str(self.window_size).zfill(3),
726
1949
  "en" + str(self.encoding_dim).zfill(3),
727
1950
  "fn" + str(self.num_filters).zfill(2),
@@ -747,6 +1970,60 @@ class ConvAutoencoderDLFilter(DeepLearningFilter):
747
1970
  pass
748
1971
 
749
1972
  def makenet(self):
1973
+ """
1974
+ Build and compile a 1D convolutional autoencoder model.
1975
+
1976
+ This function constructs a symmetric encoder-decoder architecture using 1D convolutions,
1977
+ batch normalization, dropout, and pooling layers. The model is designed for sequence
1978
+ processing tasks such as time-series or signal denoising.
1979
+
1980
+ Parameters
1981
+ ----------
1982
+ self : object
1983
+ Instance of the class containing the following attributes:
1984
+ - window_size : int
1985
+ The length of the input sequence.
1986
+ - inputsize : int
1987
+ The number of input features at each time step.
1988
+ - num_filters : int
1989
+ Initial number of filters in the first convolutional layer.
1990
+ - kernel_size : int
1991
+ Size of the convolutional kernel.
1992
+ - dropout_rate : float
1993
+ Dropout rate applied after batch normalization.
1994
+ - activation : str or callable
1995
+ Activation function used in layers.
1996
+ - encoding_dim : int
1997
+ Dimensionality of the encoded representation.
1998
+
1999
+ Returns
2000
+ -------
2001
+ None
2002
+ This method does not return a value but sets the `self.model` attribute to the
2003
+ compiled Keras model.
2004
+
2005
+ Notes
2006
+ -----
2007
+ The model architecture includes:
2008
+ - An initial convolutional block followed by max pooling.
2009
+ - Three encoding layers with increasing filter sizes and halving the sequence length.
2010
+ - A bottleneck layer that compresses the representation.
2011
+ - A symmetric decoding path that mirrors the encoding path.
2012
+ - Final upsampling to reconstruct the original sequence dimensions.
2013
+
2014
+ Examples
2015
+ --------
2016
+ >>> model = MyClass()
2017
+ >>> model.window_size = 100
2018
+ >>> model.inputsize = 10
2019
+ >>> model.num_filters = 32
2020
+ >>> model.kernel_size = 3
2021
+ >>> model.dropout_rate = 0.2
2022
+ >>> model.activation = 'relu'
2023
+ >>> model.encoding_dim = 16
2024
+ >>> model.makenet()
2025
+ >>> model.model.summary()
2026
+ """
750
2027
  input_layer = Input(shape=(self.window_size, self.inputsize))
751
2028
  x = input_layer
752
2029
 
@@ -803,8 +2080,51 @@ class ConvAutoencoderDLFilter(DeepLearningFilter):
803
2080
 
804
2081
  class CRNNDLFilter(DeepLearningFilter):
805
2082
  def __init__(
806
- self, encoding_dim=10, num_filters=10, kernel_size=5, dilation_rate=1, *args, **kwargs
807
- ):
2083
+ self,
2084
+ encoding_dim: int = 10,
2085
+ num_filters: int = 10,
2086
+ kernel_size: int = 5,
2087
+ dilation_rate: int = 1,
2088
+ *args,
2089
+ **kwargs,
2090
+ ) -> None:
2091
+ """
2092
+ Initialize CRNNDLFilter layer.
2093
+
2094
+ Parameters
2095
+ ----------
2096
+ encoding_dim : int, default=10
2097
+ Dimension of the encoding layer.
2098
+ num_filters : int, default=10
2099
+ Number of filters in the convolutional layer.
2100
+ kernel_size : int, default=5
2101
+ Size of the convolutional kernel.
2102
+ dilation_rate : int, default=1
2103
+ Dilation rate for the convolutional layer.
2104
+ *args
2105
+ Variable length argument list.
2106
+ **kwargs
2107
+ Arbitrary keyword arguments.
2108
+
2109
+ Returns
2110
+ -------
2111
+ None
2112
+ This method does not return any value.
2113
+
2114
+ Notes
2115
+ -----
2116
+ This constructor initializes the CRNNDLFilter layer with specified parameters
2117
+ and sets up the network type information in the infodict.
2118
+
2119
+ Examples
2120
+ --------
2121
+ >>> filter_layer = CRNNDLFilter(
2122
+ ... encoding_dim=15,
2123
+ ... num_filters=20,
2124
+ ... kernel_size=3,
2125
+ ... dilation_rate=2
2126
+ ... )
2127
+ """
808
2128
  self.num_filters = num_filters
809
2129
  self.kernel_size = kernel_size
810
2130
  self.dilation_rate = dilation_rate
@@ -816,10 +2136,73 @@ class CRNNDLFilter(DeepLearningFilter):
816
2136
  super(CRNNDLFilter, self).__init__(*args, **kwargs)
817
2137
 
818
2138
  def getname(self):
2139
+ """
2140
+ Generate and configure the model name and path based on current parameters.
2141
+
2142
+ This method constructs a descriptive model name string using various instance
2143
+ attributes and creates the corresponding directory path for model storage.
2144
+
2145
+ Parameters
2146
+ ----------
2147
+ self : object
2148
+ The instance containing model configuration parameters
2149
+
2150
+ Attributes Used
2151
+ ---------------
2152
+ window_size : int
2153
+ Size of the sliding window
2154
+ encoding_dim : int
2155
+ Dimension of the encoding layer
2156
+ num_filters : int
2157
+ Number of filters in the convolutional layers
2158
+ kernel_size : int
2159
+ Size of the convolutional kernel
2160
+ num_epochs : int
2161
+ Number of training epochs
2162
+ excludethresh : float
2163
+ Threshold for excluding data points
2164
+ corrthresh : float
2165
+ Correlation threshold for filtering
2166
+ step : int
2167
+ Step size for sliding window
2168
+ activation : str
2169
+ Activation function used
2170
+ usebadpts : bool
2171
+ Whether to use bad points in training
2172
+ excludebysubject : bool
2173
+ Whether to exclude data by subject
2174
+ namesuffix : str, optional
2175
+ Additional suffix to append to model name
2176
+ modelroot : str
2177
+ Root directory for model storage
2178
+
2179
+ Returns
2180
+ -------
2181
+ None
2182
+ This method modifies instance attributes in-place:
2183
+ - self.modelname: constructed model name string
2184
+ - self.modelpath: full path to model directory
2185
+
2186
+ Notes
2187
+ -----
2188
+ The generated model name follows a consistent format:
2189
+ "model_crnn_tf2_wXxx_enXxx_fnXX_flXX_eXXX_tX_ctX_sX_activation"
2190
+ where Xxx represents zero-padded numbers and XX represents zero-padded two-digit numbers.
2191
+
2192
+ Examples
2193
+ --------
2194
+ >>> model = MyModel()
2195
+ >>> model.window_size = 100
2196
+ >>> model.encoding_dim = 50
2197
+ >>> model.getname()
2198
+ >>> print(model.modelname)
2199
+ 'model_crnn_tf2_w100_en050_fn10_fl10_e001_t0.5_ct0.8_s1_relu'
2200
+ """
819
2201
  self.modelname = "_".join(
820
2202
  [
821
2203
  "model",
822
2204
  "crnn",
2205
+ "tf2",
823
2206
  "w" + str(self.window_size).zfill(3),
824
2207
  "en" + str(self.encoding_dim).zfill(3),
825
2208
  "fn" + str(self.num_filters).zfill(2),
@@ -845,6 +2228,65 @@ class CRNNDLFilter(DeepLearningFilter):
845
2228
  pass
846
2229
 
847
2230
  def makenet(self):
2231
+ """
2232
+ Create and compile a 1D convolutional neural network for temporal feature extraction and reconstruction.
2233
+
2234
+ This function builds a neural network architecture consisting of:
2235
+ - A convolutional front-end for feature extraction
2236
+ - A bidirectional LSTM layer for temporal modeling
2237
+ - A dense output layer mapping to the input size
2238
+
2239
+ The model is compiled with Adam optimizer and mean squared error loss.
2240
+
2241
+ Parameters
2242
+ ----------
2243
+ self : object
2244
+ The class instance containing the following attributes:
2245
+ - window_size : int
2246
+ The size of the input time window.
2247
+ - inputsize : int
2248
+ The number of input channels/features.
2249
+ - num_filters : int
2250
+ Number of filters in the convolutional layers.
2251
+ - kernel_size : int
2252
+ Size of the convolutional kernel.
2253
+ - dropout_rate : float
2254
+ Dropout rate for regularization.
2255
+ - activation : str or callable
2256
+ Activation function for convolutional layers.
2257
+ - encoding_dim : int
2258
+ Number of units in the LSTM layer.
2259
+
2260
+ Returns
2261
+ -------
2262
+ None
2263
+ This method modifies the instance's `model` attribute in-place.
2264
+
2265
+ Notes
2266
+ -----
2267
+ The network architecture follows this pipeline:
2268
+ Input -> Conv1D -> BatchNorm -> Dropout -> Activation ->
2269
+ Conv1D -> BatchNorm -> Dropout -> Activation ->
2270
+ Bidirectional LSTM -> Dense -> Output
2271
+
2272
+ The model is compiled with:
2273
+ - Optimizer: Adam
2274
+ - Loss: Mean Squared Error (MSE)
2275
+
2276
+ Examples
2277
+ --------
2278
+ >>> # Assuming a class with the required attributes
2279
+ >>> model = MyModel()
2280
+ >>> model.window_size = 100
2281
+ >>> model.inputsize = 10
2282
+ >>> model.num_filters = 32
2283
+ >>> model.kernel_size = 3
2284
+ >>> model.dropout_rate = 0.2
2285
+ >>> model.activation = 'relu'
2286
+ >>> model.encoding_dim = 64
2287
+ >>> model.makenet()
2288
+ >>> model.model.summary()
2289
+ """
848
2290
  input_layer = Input(shape=(self.window_size, self.inputsize))
849
2291
  x = input_layer
850
2292
 
@@ -875,17 +2317,110 @@ class CRNNDLFilter(DeepLearningFilter):
875
2317
 
876
2318
 
877
2319
  class LSTMDLFilter(DeepLearningFilter):
878
- def __init__(self, num_units=16, *args, **kwargs):
2320
+ def __init__(self, num_units: int = 16, *args, **kwargs) -> None:
2321
+ """
2322
+ Initialize the LSTMDLFilter layer.
2323
+
2324
+ Parameters
2325
+ ----------
2326
+ num_units : int, optional
2327
+ Number of units in the LSTM layer, by default 16
2328
+ *args : tuple
2329
+ Additional positional arguments passed to the parent class
2330
+ **kwargs : dict
2331
+ Additional keyword arguments passed to the parent class
2332
+
2333
+ Returns
2334
+ -------
2335
+ None
2336
+ This method initializes the layer in-place and does not return any value
2337
+
2338
+ Notes
2339
+ -----
2340
+ This method sets up the LSTM layer with the specified number of units and
2341
+ configures the infodict with the network type and unit count. The parent
2342
+ class initialization is called with any additional arguments provided.
2343
+
2344
+ Examples
2345
+ --------
2346
+ >>> layer = LSTMDLFilter(num_units=32)
2347
+ >>> print(layer.num_units)
2348
+ 32
2349
+ """
879
2350
  self.num_units = num_units
880
2351
  self.infodict["nettype"] = "lstm"
881
2352
  self.infodict["num_units"] = self.num_units
882
2353
  super(LSTMDLFilter, self).__init__(*args, **kwargs)
883
2354
 
884
2355
  def getname(self):
2356
+ """
2357
+ Generate and return the model name and path based on current configuration parameters.
2358
+
2359
+ This method constructs a standardized model name string using various configuration
2360
+ parameters and creates the corresponding directory path. The generated name includes
2361
+ information about the model architecture, training parameters, and preprocessing settings.
2362
+
2363
+ Parameters
2364
+ ----------
2365
+ self : object
2366
+ The instance containing the following attributes:
2367
+ - window_size : int
2368
+ Size of the sliding window for time series data
2369
+ - num_layers : int
2370
+ Number of LSTM layers in the model
2371
+ - num_units : int
2372
+ Number of units in each LSTM layer
2373
+ - dropout_rate : float
2374
+ Dropout rate for regularization
2375
+ - num_epochs : int
2376
+ Number of training epochs
2377
+ - excludethresh : float
2378
+ Threshold for exclusion criteria
2379
+ - corrthresh : float
2380
+ Correlation threshold for filtering
2381
+ - step : int
2382
+ Step size for data processing
2383
+ - excludebysubject : bool
2384
+ Whether to exclude data by subject
2385
+ - modelroot : str
2386
+ Root directory for model storage
2387
+
2388
+ Returns
2389
+ -------
2390
+ None
2391
+ This method modifies the instance attributes `modelname` and `modelpath` in place.
2392
+ It does not return any value.
2393
+
2394
+ Notes
2395
+ -----
2396
+ The generated model name follows a specific naming convention:
2397
+ "model_lstm_tf2_wXxx_lYY_nuZZZ_dDD_rdDD_eEEE_tT_ctTT_sS"
2398
+ where Xxx, YY, ZZZ, DD, EEEE, T, TT, S represent zero-padded numerical values.
2399
+
2400
+ If `excludebysubject` is True, "_excludebysubject" is appended to the model name.
2401
+
2402
+ Examples
2403
+ --------
2404
+ >>> model = MyModel()
2405
+ >>> model.window_size = 100
2406
+ >>> model.num_layers = 2
2407
+ >>> model.num_units = 128
2408
+ >>> model.dropout_rate = 0.2
2409
+ >>> model.num_epochs = 100
2410
+ >>> model.excludethresh = 0.5
2411
+ >>> model.corrthresh = 0.8
2412
+ >>> model.step = 1
2413
+ >>> model.excludebysubject = True
2414
+ >>> model.modelroot = "/path/to/models"
2415
+ >>> model.getname()
2416
+ >>> print(model.modelname)
2417
+ 'model_lstm_tf2_w100_l02_nu128_d02_rd02_e100_t05_ct08_s1_excludebysubject'
2418
+ """
885
2419
  self.modelname = "_".join(
886
2420
  [
887
2421
  "model",
888
2422
  "lstm",
2423
+ "tf2",
889
2424
  "w" + str(self.window_size).zfill(3),
890
2425
  "l" + str(self.num_layers).zfill(2),
891
2426
  "nu" + str(self.num_units),
@@ -907,6 +2442,47 @@ class LSTMDLFilter(DeepLearningFilter):
907
2442
  pass
908
2443
 
909
2444
  def makenet(self):
2445
+ """
2446
+ Create and configure a bidirectional LSTM neural network model.
2447
+
2448
+ This function builds a sequential neural network architecture using bidirectional LSTM layers
2449
+ followed by time-distributed dense layers. The model is compiled with Adam optimizer and MSE loss.
2450
+
2451
+ Parameters
2452
+ ----------
2453
+ self : object
2454
+ The instance containing the following attributes:
2455
+ - num_layers : int
2456
+ Number of LSTM layers in the model
2457
+ - num_units : int
2458
+ Number of units in each LSTM layer
2459
+ - dropout_rate : float
2460
+ Dropout rate for both dropout and recurrent dropout
2461
+ - window_size : int
2462
+ Size of the input window for time series data
2463
+
2464
+ Returns
2465
+ -------
2466
+ None
2467
+ This method modifies the instance in-place by setting the `model` attribute.
2468
+
2469
+ Notes
2470
+ -----
2471
+ The model architecture consists of:
2472
+ 1. Bidirectional LSTM layers with specified number of units and dropout rates
2473
+ 2. TimeDistributed Dense layers to map outputs back to window size
2474
+ 3. Compilation with Adam optimizer and MSE loss function
2475
+
2476
+ Examples
2477
+ --------
2478
+ >>> model_instance = MyModel()
2479
+ >>> model_instance.num_layers = 2
2480
+ >>> model_instance.num_units = 50
2481
+ >>> model_instance.dropout_rate = 0.2
2482
+ >>> model_instance.window_size = 10
2483
+ >>> model_instance.makenet()
2484
+ >>> print(model_instance.model.summary())
2485
+ """
910
2486
  self.model = Sequential()
911
2487
 
912
2488
  # each layer consists of an LSTM followed by a dense time distributed layer to get it back to the window size
@@ -928,7 +2504,53 @@ class LSTMDLFilter(DeepLearningFilter):
928
2504
 
929
2505
 
930
2506
  class HybridDLFilter(DeepLearningFilter):
931
- def __init__(self, invert=False, num_filters=10, kernel_size=5, num_units=16, *args, **kwargs):
2507
+ def __init__(
2508
+ self,
2509
+ invert: bool = False,
2510
+ num_filters: int = 10,
2511
+ kernel_size: int = 5,
2512
+ num_units: int = 16,
2513
+ *args,
2514
+ **kwargs,
2515
+ ) -> None:
2516
+ """
2517
+ Initialize the HybridDLFilter layer.
2518
+
2519
+ Parameters
2520
+ ----------
2521
+ invert : bool, optional
2522
+ If True, inverts the filter operation, by default False
2523
+ num_filters : int, optional
2524
+ Number of filters to use in the convolutional layer, by default 10
2525
+ kernel_size : int, optional
2526
+ Size of the convolutional kernel, by default 5
2527
+ num_units : int, optional
2528
+ Number of units in the dense layer, by default 16
2529
+ *args
2530
+ Variable length argument list
2531
+ **kwargs
2532
+ Arbitrary keyword arguments
2533
+
2534
+ Returns
2535
+ -------
2536
+ None
2537
+ This method does not return a value
2538
+
2539
+ Notes
2540
+ -----
2541
+ This method initializes the hybrid deep learning filter by setting up
2542
+ the convolutional and dense layer parameters. The infodict is populated
2543
+ with configuration information for tracking and debugging purposes.
2544
+
2545
+ Examples
2546
+ --------
2547
+ >>> layer = HybridDLFilter(
2548
+ ... invert=True,
2549
+ ... num_filters=20,
2550
+ ... kernel_size=3,
2551
+ ... num_units=32
2552
+ ... )
2553
+ """
932
2554
  self.invert = invert
933
2555
  self.num_filters = num_filters
934
2556
  self.kernel_size = kernel_size
@@ -941,10 +2563,84 @@ class HybridDLFilter(DeepLearningFilter):
941
2563
  super(HybridDLFilter, self).__init__(*args, **kwargs)
942
2564
 
943
2565
  def getname(self):
2566
+ """
2567
+ Generate and return the model name and path based on current configuration parameters.
2568
+
2569
+ This method constructs a descriptive model name string by joining various configuration
2570
+ parameters with specific prefixes and formatting conventions. The resulting model name
2571
+ is used to create a unique directory path for model storage.
2572
+
2573
+ Parameters
2574
+ ----------
2575
+ self : object
2576
+ The instance containing model configuration parameters. Expected attributes include:
2577
+ - `window_size` : int
2578
+ - `num_layers` : int
2579
+ - `num_filters` : int
2580
+ - `kernel_size` : int
2581
+ - `num_units` : int
2582
+ - `dropout_rate` : float
2583
+ - `num_epochs` : int
2584
+ - `excludethresh` : float
2585
+ - `corrthresh` : float
2586
+ - `step` : int
2587
+ - `activation` : str
2588
+ - `invert` : bool
2589
+ - `excludebysubject` : bool
2590
+ - `modelroot` : str
2591
+
2592
+ Returns
2593
+ -------
2594
+ None
2595
+ This method does not return a value but modifies instance attributes:
2596
+ - `self.modelname`: The constructed model name string
2597
+ - `self.modelpath`: The full path to the model directory
2598
+
2599
+ Notes
2600
+ -----
2601
+ The model name is constructed using the following components:
2602
+ - "model_hybrid_tf2_" prefix
2603
+ - Window size with 3-digit zero-padded formatting
2604
+ - Number of layers with 2-digit zero-padded formatting
2605
+ - Number of filters with 2-digit zero-padded formatting
2606
+ - Kernel size with 2-digit zero-padded formatting
2607
+ - Number of units
2608
+ - Dropout rate (appears twice with different prefixes)
2609
+ - Number of epochs with 3-digit zero-padded formatting
2610
+ - Exclusion threshold
2611
+ - Correlation threshold
2612
+ - Step size
2613
+ - Activation function name
2614
+
2615
+ Additional suffixes are appended based on boolean flags:
2616
+ - "_invert" if `self.invert` is True
2617
+ - "_excludebysubject" if `self.excludebysubject` is True
2618
+
2619
+ Examples
2620
+ --------
2621
+ >>> model = MyModel()
2622
+ >>> model.window_size = 100
2623
+ >>> model.num_layers = 3
2624
+ >>> model.num_filters = 16
2625
+ >>> model.kernel_size = 5
2626
+ >>> model.num_units = 64
2627
+ >>> model.dropout_rate = 0.2
2628
+ >>> model.num_epochs = 100
2629
+ >>> model.excludethresh = 0.5
2630
+ >>> model.corrthresh = 0.8
2631
+ >>> model.step = 1
2632
+ >>> model.activation = "relu"
2633
+ >>> model.invert = True
2634
+ >>> model.excludebysubject = False
2635
+ >>> model.getname()
2636
+ >>> print(model.modelname)
2637
+ 'model_hybrid_tf2_w100_l03_fn16_fl05_nu64_d0.2_rd0.2_e100_t0.5_ct0.8_s01_relu_invert'
2638
+ """
944
2639
  self.modelname = "_".join(
945
2640
  [
946
2641
  "model",
947
2642
  "hybrid",
2643
+ "tf2",
948
2644
  "w" + str(self.window_size).zfill(3),
949
2645
  "l" + str(self.num_layers).zfill(2),
950
2646
  "fn" + str(self.num_filters).zfill(2),
@@ -971,6 +2667,71 @@ class HybridDLFilter(DeepLearningFilter):
971
2667
  pass
972
2668
 
973
2669
  def makenet(self):
2670
+ """
2671
+ Build and compile a neural network model with configurable CNN and LSTM layers.
2672
+
2673
+ This function constructs a neural network model using Keras, with the architecture
2674
+ determined by the `invert` flag. If `invert` is True, the model starts with a
2675
+ Conv1D layer followed by LSTM layers; otherwise, it starts with LSTM layers
2676
+ followed by Conv1D layers. The model is compiled with the RMSprop optimizer
2677
+ and mean squared error loss.
2678
+
2679
+ Parameters
2680
+ ----------
2681
+ self : object
2682
+ The instance of the class containing the model configuration attributes.
2683
+
2684
+ Attributes Used
2685
+ ---------------
2686
+ self.invert : bool
2687
+ If True, the model begins with a Conv1D layer and ends with an LSTM layer.
2688
+ If False, the model begins with an LSTM layer and ends with a Conv1D layer.
2689
+ self.num_filters : int
2690
+ Number of filters in each Conv1D layer.
2691
+ self.kernel_size : int
2692
+ Size of the kernel in Conv1D layers.
2693
+ self.padding : str, default='same'
2694
+ Padding mode for Conv1D layers.
2695
+ self.window_size : int
2696
+ Length of the input sequence.
2697
+ self.inputsize : int
2698
+ Number of features in the input data.
2699
+ self.num_layers : int
2700
+ Total number of layers in the model.
2701
+ self.num_units : int
2702
+ Number of units in the LSTM layers.
2703
+ self.dropout_rate : float
2704
+ Dropout rate for regularization.
2705
+ self.activation : str or callable
2706
+ Activation function for Conv1D layers.
2707
+
2708
+ Returns
2709
+ -------
2710
+ None
2711
+ This method modifies the instance's `self.model` attribute in place.
2712
+
2713
+ Notes
2714
+ -----
2715
+ - The model uses `Sequential` from Keras.
2716
+ - Batch normalization and dropout are applied after each Conv1D layer (except the last).
2717
+ - The final layer is a Dense layer wrapped in `TimeDistributed` for sequence-to-sequence output.
2718
+ - The model is compiled using `RMSprop` optimizer and `mse` loss.
2719
+
2720
+ Examples
2721
+ --------
2722
+ >>> model_builder = MyModelClass()
2723
+ >>> model_builder.invert = True
2724
+ >>> model_builder.num_filters = 32
2725
+ >>> model_builder.kernel_size = 3
2726
+ >>> model_builder.window_size = 100
2727
+ >>> model_builder.inputsize = 1
2728
+ >>> model_builder.num_layers = 5
2729
+ >>> model_builder.num_units = 64
2730
+ >>> model_builder.dropout_rate = 0.2
2731
+ >>> model_builder.activation = 'relu'
2732
+ >>> model_builder.makenet()
2733
+ >>> model_builder.model.summary()
2734
+ """
974
2735
  self.model = Sequential()
975
2736
 
976
2737
  if self.invert:
@@ -1052,14 +2813,67 @@ class HybridDLFilter(DeepLearningFilter):
1052
2813
 
1053
2814
 
1054
2815
  def filtscale(
1055
- data,
1056
- scalefac=1.0,
1057
- reverse=False,
1058
- hybrid=False,
1059
- lognormalize=True,
1060
- epsilon=1e-10,
1061
- numorders=6,
1062
- ):
2816
+ data: np.ndarray,
2817
+ scalefac: float = 1.0,
2818
+ reverse: bool = False,
2819
+ hybrid: bool = False,
2820
+ lognormalize: bool = True,
2821
+ epsilon: float = 1e-10,
2822
+ numorders: int = 6,
2823
+ ) -> tuple[np.ndarray, float] | np.ndarray:
2824
+ """
2825
+ Apply or reverse a frequency-domain scaling and normalization to input data.
2826
+
2827
+ This function performs either forward or inverse transformation of the input
2828
+ data in the frequency domain, applying scaling, normalization, and optionally
2829
+ hybrid encoding. It supports both logarithmic and standard normalization
2830
+ modes.
2831
+
2832
+ Parameters
2833
+ ----------
2834
+ data : np.ndarray
2835
+ Input signal or transformed data (depending on `reverse` flag).
2836
+ scalefac : float, optional
2837
+ Scaling factor used for normalization. Default is 1.0.
2838
+ reverse : bool, optional
2839
+ If True, performs inverse transformation from frequency domain back
2840
+ to time domain. Default is False.
2841
+ hybrid : bool, optional
2842
+ If True, returns a hybrid representation combining original data
2843
+ and magnitude spectrum. Default is False.
2844
+ lognormalize : bool, optional
2845
+ If True, applies logarithmic normalization to the magnitude spectrum.
2846
+ Default is True.
2847
+ epsilon : float, optional
2848
+ Small constant added to avoid log(0). Default is 1e-10.
2849
+ numorders : int, optional
2850
+ Number of orders used for scaling in log normalization. Default is 6.
2851
+
2852
+ Returns
2853
+ -------
2854
+ tuple[np.ndarray, float] or np.ndarray
2855
+ - If `reverse=False`: A tuple of (transformed data, scale factor).
2856
+ The transformed data is a stacked array of magnitude and phase components
2857
+ (or original data in hybrid mode).
2858
+ - If `reverse=True`: Reconstructed time-domain signal.
2859
+
2860
+ Notes
2861
+ -----
2862
+ - Forward mode applies FFT, normalizes the magnitude, and stacks magnitude
2863
+ and phase.
2864
+ - In hybrid mode, the output includes the original time-domain signal
2865
+ instead of the phase component.
2866
+ - In reverse mode, the phase and magnitude components are used to reconstruct
2867
+ the original signal using inverse FFT.
2868
+
2869
+ Examples
2870
+ --------
2871
+ >>> import numpy as np
2872
+ >>> from scipy import fftpack
2873
+ >>> x = np.random.randn(1024)
2874
+ >>> scaled_data, scale = filtscale(x)
2875
+ >>> reconstructed = filtscale(scaled_data, scale, reverse=True)
2876
+ """
1063
2877
  if not reverse:
1064
2878
  specvals = fftpack.fft(data)
1065
2879
  if lognormalize:
@@ -1089,16 +2903,128 @@ def filtscale(
1089
2903
  return fftpack.ifft(specvals).real
1090
2904
 
1091
2905
 
1092
- def tobadpts(name):
2906
+ def tobadpts(name: str) -> str:
2907
+ """
2908
+ Convert a filename to its corresponding bad points filename.
2909
+
2910
+ Replaces the '.txt' extension with '_badpts.txt' to create a standardized
2911
+ bad points filename pattern.
2912
+
2913
+ Parameters
2914
+ ----------
2915
+ name : str
2916
+ Input filename, typically ending with '.txt' extension.
2917
+
2918
+ Returns
2919
+ -------
2920
+ str
2921
+ Filename with '.txt' replaced by '_badpts.txt' extension.
2922
+
2923
+ Notes
2924
+ -----
2925
+ This function assumes the input filename ends with '.txt' extension.
2926
+ If the input does not contain '.txt', the function will append '_badpts.txt'
2927
+ to the end of the string.
2928
+
2929
+ Examples
2930
+ --------
2931
+ >>> tobadpts("data.txt")
2932
+ 'data_badpts.txt'
2933
+
2934
+ >>> tobadpts("results.txt")
2935
+ 'results_badpts.txt'
2936
+
2937
+ >>> tobadpts("config")
2938
+ 'config_badpts.txt'
2939
+ """
1093
2940
  return name.replace(".txt", "_badpts.txt")
1094
2941
 
1095
2942
 
1096
- def targettoinput(name, targetfrag="xyz", inputfrag="abc"):
2943
+ def targettoinput(name: str, targetfrag: str = "xyz", inputfrag: str = "abc") -> str:
2944
+ """
2945
+ Replace occurrences of a target fragment with an input fragment in a string.
2946
+
2947
+ Parameters
2948
+ ----------
2949
+ name : str
2950
+ The input string to process.
2951
+ targetfrag : str, default='xyz'
2952
+ The fragment to search for and replace. Defaults to 'xyz'.
2953
+ inputfrag : str, default='abc'
2954
+ The fragment to replace targetfrag with. Defaults to 'abc'.
2955
+
2956
+ Returns
2957
+ -------
2958
+ str
2959
+ The modified string with targetfrag replaced by inputfrag.
2960
+
2961
+ Notes
2962
+ -----
2963
+ This function uses Python's built-in string replace method, which replaces
2964
+ all occurrences of targetfrag with inputfrag in the input string.
2965
+
2966
+ Examples
2967
+ --------
2968
+ >>> targettoinput("hello xyz world")
2969
+ 'hello abc world'
2970
+
2971
+ >>> targettoinput("xyzxyzxyz", "xyz", "123")
2972
+ '123123123'
2973
+
2974
+ >>> targettoinput("abcdef", "xyz", "123")
2975
+ 'abcdef'
2976
+ """
1097
2977
  LGR.debug(f"replacing {targetfrag} with {inputfrag}")
1098
2978
  return name.replace(targetfrag, inputfrag)
1099
2979
 
1100
2980
 
1101
- def getmatchedtcs(searchstring, usebadpts=False, targetfrag="xyz", inputfrag="abc", debug=False):
2981
+ def getmatchedtcs(
2982
+ searchstring: str,
2983
+ usebadpts: bool = False,
2984
+ targetfrag: str = "xyz",
2985
+ inputfrag: str = "abc",
2986
+ debug: bool = False,
2987
+ ) -> tuple[list[str], int]:
2988
+ """
2989
+ Find and validate timecourse files matching a search pattern, and determine the length of the timecourses.
2990
+
2991
+ This function searches for files matching the given `searchstring`, checks for the existence of
2992
+ corresponding info files to ensure completeness, and reads the first matched file to determine
2993
+ the length of the timecourses. It is intended for use with BIDS-compatible timecourse files.
2994
+
2995
+ Parameters
2996
+ ----------
2997
+ searchstring : str
2998
+ A glob pattern to match target files. Typically includes a path and file name pattern.
2999
+ usebadpts : bool, optional
3000
+ Flag indicating whether to use bad points in processing. Default is False.
3001
+ targetfrag : str, optional
3002
+ Fragment identifier for target files. Default is "xyz".
3003
+ inputfrag : str, optional
3004
+ Fragment identifier for input files. Default is "abc".
3005
+ debug : bool, optional
3006
+ If True, print debug information including matched files and processing steps.
3007
+ Default is False.
3008
+
3009
+ Returns
3010
+ -------
3011
+ tuple[list[str], int]
3012
+ A tuple containing:
3013
+ - List of matched and validated file paths.
3014
+ - Length of the timecourses (number of timepoints) in the first matched file.
3015
+
3016
+ Notes
3017
+ -----
3018
+ - The function expects files to have a corresponding `_info` file for validation.
3019
+ - Timecourse data is read from the first matched file using `tide_io.readbidstsv`.
3020
+ - The function currently only reads the first matched file to determine `tclen`, assuming all
3021
+ matched files have the same timecourse length.
3022
+
3023
+ Examples
3024
+ --------
3025
+ >>> matched_files, length = getmatchedtcs("sub-*/func/*cardiacfromfmri_25.0Hz*")
3026
+ >>> print(f"Found {len(matched_files)} files with {length} timepoints each.")
3027
+ """
1102
3028
  # list all of the target files
1103
3029
  fromfile = sorted(glob.glob(searchstring))
1104
3030
  if debug:
@@ -1136,18 +3062,144 @@ def getmatchedtcs(searchstring, usebadpts=False, targetfrag="xyz", inputfrag="ab
1136
3062
 
1137
3063
 
1138
3064
  def readindata(
1139
- matchedfilelist,
1140
- tclen,
1141
- targetfrag="xyz",
1142
- inputfrag="abc",
1143
- usebadpts=False,
1144
- startskip=0,
1145
- endskip=0,
1146
- corrthresh=0.5,
1147
- readlim=None,
1148
- readskip=None,
1149
- debug=False,
3065
+ matchedfilelist: list[str],
3066
+ tclen: int,
3067
+ targetfrag: str = "xyz",
3068
+ inputfrag: str = "abc",
3069
+ usebadpts: bool = False,
3070
+ startskip: int = 0,
3071
+ endskip: int = 0,
3072
+ corrthresh: float = 0.5,
3073
+ readlim: int | None = None,
3074
+ readskip: int | None = None,
3075
+ debug: bool = False,
3076
+ ) -> (
3077
+ tuple[np.ndarray, np.ndarray, list[str]] | tuple[np.ndarray, np.ndarray, list[str], np.ndarray]
1150
3078
  ):
3079
+ """
3080
+ Read and process time-series data from a list of matched files.
3081
+
3082
+ This function reads cardiac and plethysmographic data from a set of files, applies
3083
+ filtering based on data quality metrics (e.g., correlation thresholds, NaN values,
3084
+ data length, and standard deviation), and returns processed arrays for training.
3085
+
3086
+ Parameters
3087
+ ----------
3088
+ matchedfilelist : list of str
3089
+ List of file paths to be processed. Each file should contain time-series data
3090
+ in a format compatible with `tide_io.readbidstsv`.
3091
+ tclen : int
3092
+ The length of the time series to be read from each file.
3093
+ targetfrag : str, optional
3094
+ Fragment identifier used for mapping filenames (default is "xyz").
3095
+ inputfrag : str, optional
3096
+ Fragment identifier used for mapping filenames (default is "abc").
3097
+ usebadpts : bool, optional
3098
+ If True, include bad point data in the output (default is False).
3099
+ startskip : int, optional
3100
+ Number of samples to skip at the beginning of each time series (default is 0).
3101
+ endskip : int, optional
3102
+ Number of samples to skip at the end of each time series (default is 0).
3103
+ corrthresh : float, optional
3104
+ Threshold for correlation between raw and plethysmographic signals.
3105
+ Files with correlations below this value are excluded (default is 0.5).
3106
+ readlim : int, optional
3107
+ Maximum number of files to read. If None, all files are read (default is None).
3108
+ readskip : int, optional
3109
+ Number of files to skip at the beginning of the list. If None, no files are skipped (default is None).
3110
+ debug : bool, optional
3111
+ If True, print debug information during processing (default is False).
3112
+
3113
+ Returns
3114
+ -------
3115
+ tuple of (np.ndarray, np.ndarray, list[str]) or (np.ndarray, np.ndarray, list[str], np.ndarray)
3116
+ - `x1[startskip:-endskip, :count]`: Array of x-axis time series data.
3117
+ - `y1[startskip:-endskip, :count]`: Array of y-axis time series data.
3118
+ - `names[:count]`: List of file names that passed quality checks.
3119
+ - `bad1[startskip:-endskip, :count]`: Optional array of bad point data if `usebadpts` is True.
3120
+
3121
+ Notes
3122
+ -----
3123
+ - Files are filtered based on:
3124
+ - Correlation threshold (`corrthresh`)
3125
+ - Presence of NaN values
3126
+ - Data length (must be at least `tclen`)
3127
+ - Standard deviation of data (must be between 0.5 and 20.0)
3128
+ - Excluded files are logged with reasons.
3129
+ - If `usebadpts` is True, bad point data is included in the returned tuple.
3130
+
3131
+ Examples
3132
+ --------
3133
+ >>> x, y, names = readindata(
3134
+ ... matchedfilelist=["file1.tsv", "file2.tsv"],
3135
+ ... tclen=1000,
3136
+ ... corrthresh=0.6,
3137
+ ... readlim=10
3138
+ ... )
3139
+ >>> print(f"Loaded {len(names)} files")
3140
+ """
3141
+ """
3142
+ Read and process time-series data from a list of matched files.
3143
+
3144
+ This function reads cardiac and plethysmographic data from a set of files, applies
3145
+ filtering based on data quality metrics (e.g., correlation thresholds, NaN values,
3146
+ data length, and standard deviation), and returns processed arrays for training.
3147
+
3148
+ Parameters
3149
+ ----------
3150
+ matchedfilelist : list of str
3151
+ List of file paths to be processed. Each file should contain time-series data
3152
+ in a format compatible with `tide_io.readbidstsv`.
3153
+ tclen : int
3154
+ The length of the time series to be read from each file.
3155
+ targetfrag : str, optional
3156
+ Fragment identifier used for mapping filenames (default is "xyz").
3157
+ inputfrag : str, optional
3158
+ Fragment identifier used for mapping filenames (default is "abc").
3159
+ usebadpts : bool, optional
3160
+ If True, include bad point data in the output (default is False).
3161
+ startskip : int, optional
3162
+ Number of samples to skip at the beginning of each time series (default is 0).
3163
+ endskip : int, optional
3164
+ Number of samples to skip at the end of each time series (default is 0).
3165
+ corrthresh : float, optional
3166
+ Threshold for correlation between raw and plethysmographic signals.
3167
+ Files with correlations below this value are excluded (default is 0.5).
3168
+ readlim : int, optional
3169
+ Maximum number of files to read. If None, all files are read (default is None).
3170
+ readskip : int, optional
3171
+ Number of files to skip at the beginning of the list. If None, no files are skipped (default is None).
3172
+ debug : bool, optional
3173
+ If True, print debug information during processing (default is False).
3174
+
3175
+ Returns
3176
+ -------
3177
+ tuple of (np.ndarray, np.ndarray, list[str]) or (np.ndarray, np.ndarray, list[str], np.ndarray)
3178
+ - `x1[startskip:-endskip, :count]`: Array of x-axis time series data.
3179
+ - `y1[startskip:-endskip, :count]`: Array of y-axis time series data.
3180
+ - `names[:count]`: List of file names that passed quality checks.
3181
+ - `bad1[startskip:-endskip, :count]`: Optional array of bad point data if `usebadpts` is True.
3182
+
3183
+ Notes
3184
+ -----
3185
+ - Files are filtered based on:
3186
+ - Correlation threshold (`corrthresh`)
3187
+ - Presence of NaN values
3188
+ - Data length (must be at least `tclen`)
3189
+ - Standard deviation of data (must be between 0.5 and 20.0)
3190
+ - Excluded files are logged with reasons.
3191
+ - If `usebadpts` is True, bad point data is included in the returned tuple.
3192
+
3193
+ Examples
3194
+ --------
3195
+ >>> x, y, names = readindata(
3196
+ ... matchedfilelist=["file1.tsv", "file2.tsv"],
3197
+ ... tclen=1000,
3198
+ ... corrthresh=0.6,
3199
+ ... readlim=10
3200
+ ... )
3201
+ >>> print(f"Loaded {len(names)} files")
3202
+ """
1151
3203
  LGR.info(
1152
3204
  "readindata called with usebadpts, startskip, endskip, readlim, readskip, targetfrag, inputfrag = "
1153
3205
  f"{usebadpts} {startskip} {endskip} {readlim} {readskip} {targetfrag} {inputfrag}"
@@ -1296,52 +3348,117 @@ def readindata(
1296
3348
 
1297
3349
 
1298
3350
  def prep(
1299
- window_size,
1300
- step=1,
1301
- excludethresh=4.0,
1302
- usebadpts=False,
1303
- startskip=200,
1304
- endskip=200,
1305
- excludebysubject=True,
1306
- thesuffix="sliceres",
1307
- thedatadir="/data/frederic/physioconn/output_2025",
1308
- inputfrag="abc",
1309
- targetfrag="xyz",
1310
- corrthresh=0.5,
1311
- dofft=False,
1312
- readlim=None,
1313
- readskip=None,
1314
- countlim=None,
1315
- debug=False,
3351
+ window_size: int,
3352
+ step: int = 1,
3353
+ excludethresh: float = 4.0,
3354
+ usebadpts: bool = False,
3355
+ startskip: int = 200,
3356
+ endskip: int = 200,
3357
+ excludebysubject: bool = True,
3358
+ thesuffix: str = "sliceres",
3359
+ thedatadir: str = "/data/frederic/physioconn/output_2025",
3360
+ inputfrag: str = "abc",
3361
+ targetfrag: str = "xyz",
3362
+ corrthresh: float = 0.5,
3363
+ dofft: bool = False,
3364
+ readlim: int | None = None,
3365
+ readskip: int | None = None,
3366
+ countlim: int | None = None,
3367
+ debug: bool = False,
3368
+ ) -> (
3369
+ tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, int, int, int]
3370
+ | tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, int, int, int, np.ndarray, np.ndarray]
1316
3371
  ):
1317
3372
  """
1318
- prep - reads in training and validation data for 1D filter
3373
+ Prepare time-series data for training and validation by reading, normalizing,
3374
+ windowing, and splitting into batches.
3375
+
3376
+ This function reads time-series data from JSON files, normalizes the data,
3377
+ applies windowing to create input-output pairs, and splits the data into
3378
+ training and validation sets based on subject-wise or window-wise exclusion
3379
+ criteria.
1319
3380
 
1320
3381
  Parameters
1321
3382
  ----------
1322
- window_size
1323
- step
1324
- excludethresh
1325
- excludebysubject
1326
- usebadpts
1327
- startskip
1328
- endskip
1329
- thesuffix
1330
- thedatadir
1331
- inputfrag
1332
- targetfrag
1333
- corrthresh
1334
- dofft
1335
- readlim
1336
- readskip
1337
- countlim
3383
+ window_size : int
3384
+ Size of the sliding window used to create input-output pairs.
3385
+ step : int, optional
3386
+ Step size for sliding window (default is 1).
3387
+ excludethresh : float, optional
3388
+ Threshold for excluding windows or subjects based on maximum absolute
3389
+ value of input data (default is 4.0).
3390
+ usebadpts : bool, optional
3391
+ Whether to include bad points in the data (default is False).
3392
+ startskip : int, optional
3393
+ Number of time points to skip at the beginning of each time series
3394
+ (default is 200).
3395
+ endskip : int, optional
3396
+ Number of time points to skip at the end of each time series
3397
+ (default is 200).
3398
+ excludebysubject : bool, optional
3399
+ If True, exclude entire subjects based on maximum absolute value;
3400
+ otherwise, exclude individual windows (default is True).
3401
+ thesuffix : str, optional
3402
+ Suffix used to identify files (default is "sliceres").
3403
+ thedatadir : str, optional
3404
+ Directory where the data files are located (default is
3405
+ "/data/frederic/physioconn/output_2025").
3406
+ inputfrag : str, optional
3407
+ Fragment identifier for input data (default is "abc").
3408
+ targetfrag : str, optional
3409
+ Fragment identifier for target data (default is "xyz").
3410
+ corrthresh : float, optional
3411
+ Correlation threshold for matching time series (default is 0.5).
3412
+ dofft : bool, optional
3413
+ Whether to perform FFT on the data (default is False).
3414
+ readlim : int or None, optional
3415
+ Limit on number of time points to read (default is None).
3416
+ readskip : int or None, optional
3417
+ Number of time points to skip when reading data (default is None).
3418
+ countlim : int or None, optional
3419
+ Limit on number of subjects to process (default is None).
3420
+ debug : bool, optional
3421
+ Whether to enable debug logging (default is False).
1338
3422
 
1339
3423
  Returns
1340
3424
  -------
1341
- train_x, train_y, val_x, val_y, N_subjs, tclen - startskip, batchsize
1342
-
3425
+ tuple of (np.ndarray, np.ndarray, np.ndarray, np.ndarray, int, int, int)
3426
+ If `dofft` is False:
3427
+ - train_x : ndarray of shape (n_train, window_size, 1)
3428
+ - train_y : ndarray of shape (n_train, window_size, 1)
3429
+ - val_x : ndarray of shape (n_val, window_size, 1)
3430
+ - val_y : ndarray of shape (n_val, window_size, 1)
3431
+ - N_subjs : int
3432
+ - tclen : int
3433
+ - batchsize : int
3434
+
3435
+ tuple of (np.ndarray, np.ndarray, np.ndarray, np.ndarray, int, int, int,
3436
+ np.ndarray, np.ndarray)
3437
+ If `dofft` is True:
3438
+ - train_x : ndarray of shape (n_train, window_size, 2)
3439
+ - train_y : ndarray of shape (n_train, window_size, 2)
3440
+ - val_x : ndarray of shape (n_val, window_size, 2)
3441
+ - val_y : ndarray of shape (n_val, window_size, 2)
3442
+ - N_subjs : int
3443
+ - tclen : int
3444
+ - batchsize : int
3445
+ - Xscale_fourier : ndarray of shape (N_subjs, windowspersubject)
3446
+ - Yscale_fourier : ndarray of shape (N_subjs, windowspersubject)
3447
+
3448
+ Notes
3449
+ -----
3450
+ - Data normalization is performed using median absolute deviation (MAD).
3451
+ - Windows are created based on sliding window approach.
3452
+ - Training and validation sets are split based on subject-wise partitioning.
3453
+ - If `usebadpts` is True, bad points are included in the returned data.
3454
+ - If `dofft` is True, data is transformed using a filtering scale function.
3455
+
3456
+ Examples
3457
+ --------
3458
+ >>> train_x, train_y, val_x, val_y, N_subjs, tclen, batchsize = prep(
3459
+ ... window_size=100, step=10, excludethresh=3.0, dofft=False
3460
+ ... )
1343
3461
  """
1344
-
1345
3462
  searchstring = os.path.join(thedatadir, "*", "*_desc-stdrescardfromfmri_timeseries.json")
1346
3463
 
1347
3464
  # find matched files