rapidtide 3.0.11__py3-none-any.whl → 3.1.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 (144) hide show
  1. rapidtide/Colortables.py +492 -27
  2. rapidtide/OrthoImageItem.py +1049 -46
  3. rapidtide/RapidtideDataset.py +1533 -86
  4. rapidtide/_version.py +3 -3
  5. rapidtide/calccoherence.py +196 -29
  6. rapidtide/calcnullsimfunc.py +188 -40
  7. rapidtide/calcsimfunc.py +242 -42
  8. rapidtide/correlate.py +1203 -383
  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 +53 -3
  13. rapidtide/data/examples/src/testglmfilt +5 -5
  14. rapidtide/data/examples/src/testhappy +29 -7
  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/decorators.py +91 -0
  23. rapidtide/dlfilter.py +2226 -110
  24. rapidtide/dlfiltertorch.py +4842 -0
  25. rapidtide/externaltools.py +327 -12
  26. rapidtide/fMRIData_class.py +79 -40
  27. rapidtide/filter.py +1899 -810
  28. rapidtide/fit.py +2011 -581
  29. rapidtide/genericmultiproc.py +93 -18
  30. rapidtide/happy_supportfuncs.py +2047 -172
  31. rapidtide/helper_classes.py +584 -43
  32. rapidtide/io.py +2370 -372
  33. rapidtide/linfitfiltpass.py +346 -99
  34. rapidtide/makelaggedtcs.py +210 -24
  35. rapidtide/maskutil.py +448 -62
  36. rapidtide/miscmath.py +827 -121
  37. rapidtide/multiproc.py +210 -22
  38. rapidtide/patchmatch.py +242 -42
  39. rapidtide/peakeval.py +31 -31
  40. rapidtide/ppgproc.py +2203 -0
  41. rapidtide/qualitycheck.py +352 -39
  42. rapidtide/refinedelay.py +431 -57
  43. rapidtide/refineregressor.py +494 -189
  44. rapidtide/resample.py +671 -185
  45. rapidtide/scripts/applyppgproc.py +28 -0
  46. rapidtide/scripts/showxcorr_legacy.py +7 -7
  47. rapidtide/scripts/stupidramtricks.py +15 -17
  48. rapidtide/simFuncClasses.py +1052 -77
  49. rapidtide/simfuncfit.py +269 -69
  50. rapidtide/stats.py +540 -238
  51. rapidtide/tests/happycomp +9 -0
  52. rapidtide/tests/test_cleanregressor.py +1 -2
  53. rapidtide/tests/test_dlfiltertorch.py +627 -0
  54. rapidtide/tests/test_findmaxlag.py +24 -8
  55. rapidtide/tests/test_fullrunhappy_v1.py +0 -2
  56. rapidtide/tests/test_fullrunhappy_v2.py +0 -2
  57. rapidtide/tests/test_fullrunhappy_v3.py +11 -4
  58. rapidtide/tests/test_fullrunhappy_v4.py +10 -2
  59. rapidtide/tests/test_fullrunrapidtide_v7.py +1 -1
  60. rapidtide/tests/test_getparsers.py +11 -3
  61. rapidtide/tests/test_refinedelay.py +0 -1
  62. rapidtide/tests/test_simroundtrip.py +16 -8
  63. rapidtide/tests/test_stcorrelate.py +3 -1
  64. rapidtide/tests/utils.py +9 -8
  65. rapidtide/tidepoolTemplate.py +142 -38
  66. rapidtide/tidepoolTemplate_alt.py +165 -44
  67. rapidtide/tidepoolTemplate_big.py +189 -52
  68. rapidtide/util.py +1217 -118
  69. rapidtide/voxelData.py +684 -37
  70. rapidtide/wiener.py +136 -23
  71. rapidtide/wiener2.py +113 -7
  72. rapidtide/workflows/adjustoffset.py +105 -3
  73. rapidtide/workflows/aligntcs.py +85 -2
  74. rapidtide/workflows/applydlfilter.py +87 -10
  75. rapidtide/workflows/applyppgproc.py +540 -0
  76. rapidtide/workflows/atlasaverage.py +210 -47
  77. rapidtide/workflows/atlastool.py +100 -3
  78. rapidtide/workflows/calcSimFuncMap.py +288 -69
  79. rapidtide/workflows/calctexticc.py +201 -9
  80. rapidtide/workflows/ccorrica.py +101 -6
  81. rapidtide/workflows/cleanregressor.py +165 -31
  82. rapidtide/workflows/delayvar.py +171 -23
  83. rapidtide/workflows/diffrois.py +81 -3
  84. rapidtide/workflows/endtidalproc.py +144 -4
  85. rapidtide/workflows/fdica.py +195 -15
  86. rapidtide/workflows/filtnifti.py +70 -3
  87. rapidtide/workflows/filttc.py +74 -3
  88. rapidtide/workflows/fitSimFuncMap.py +202 -51
  89. rapidtide/workflows/fixtr.py +73 -3
  90. rapidtide/workflows/gmscalc.py +113 -3
  91. rapidtide/workflows/happy.py +801 -199
  92. rapidtide/workflows/happy2std.py +144 -12
  93. rapidtide/workflows/happy_parser.py +163 -23
  94. rapidtide/workflows/histnifti.py +118 -2
  95. rapidtide/workflows/histtc.py +84 -3
  96. rapidtide/workflows/linfitfilt.py +117 -4
  97. rapidtide/workflows/localflow.py +328 -28
  98. rapidtide/workflows/mergequality.py +79 -3
  99. rapidtide/workflows/niftidecomp.py +322 -18
  100. rapidtide/workflows/niftistats.py +174 -4
  101. rapidtide/workflows/pairproc.py +98 -4
  102. rapidtide/workflows/pairwisemergenifti.py +85 -2
  103. rapidtide/workflows/parser_funcs.py +1421 -40
  104. rapidtide/workflows/physiofreq.py +137 -11
  105. rapidtide/workflows/pixelcomp.py +207 -5
  106. rapidtide/workflows/plethquality.py +103 -21
  107. rapidtide/workflows/polyfitim.py +151 -11
  108. rapidtide/workflows/proj2flow.py +75 -2
  109. rapidtide/workflows/rankimage.py +111 -4
  110. rapidtide/workflows/rapidtide.py +368 -76
  111. rapidtide/workflows/rapidtide2std.py +98 -2
  112. rapidtide/workflows/rapidtide_parser.py +109 -9
  113. rapidtide/workflows/refineDelayMap.py +144 -33
  114. rapidtide/workflows/refineRegressor.py +675 -96
  115. rapidtide/workflows/regressfrommaps.py +161 -37
  116. rapidtide/workflows/resamplenifti.py +85 -3
  117. rapidtide/workflows/resampletc.py +91 -3
  118. rapidtide/workflows/retrolagtcs.py +99 -9
  119. rapidtide/workflows/retroregress.py +176 -26
  120. rapidtide/workflows/roisummarize.py +174 -5
  121. rapidtide/workflows/runqualitycheck.py +71 -3
  122. rapidtide/workflows/showarbcorr.py +149 -6
  123. rapidtide/workflows/showhist.py +86 -2
  124. rapidtide/workflows/showstxcorr.py +160 -3
  125. rapidtide/workflows/showtc.py +159 -3
  126. rapidtide/workflows/showxcorrx.py +190 -10
  127. rapidtide/workflows/showxy.py +185 -15
  128. rapidtide/workflows/simdata.py +264 -38
  129. rapidtide/workflows/spatialfit.py +77 -2
  130. rapidtide/workflows/spatialmi.py +250 -27
  131. rapidtide/workflows/spectrogram.py +305 -32
  132. rapidtide/workflows/synthASL.py +154 -3
  133. rapidtide/workflows/tcfrom2col.py +76 -2
  134. rapidtide/workflows/tcfrom3col.py +74 -2
  135. rapidtide/workflows/tidepool.py +2971 -130
  136. rapidtide/workflows/utils.py +19 -14
  137. rapidtide/workflows/utils_doc.py +293 -0
  138. rapidtide/workflows/variabilityizer.py +116 -3
  139. {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/METADATA +10 -8
  140. {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/RECORD +144 -128
  141. {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/entry_points.txt +1 -0
  142. {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/WHEEL +0 -0
  143. {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/licenses/LICENSE +0 -0
  144. {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/top_level.txt +0 -0
@@ -19,8 +19,11 @@
19
19
  import gc
20
20
  import logging
21
21
  import sys
22
+ from typing import Any
22
23
 
23
24
  import numpy as np
25
+ import statsmodels as sm
26
+ from numpy.typing import NDArray
24
27
  from scipy.stats import pearsonr
25
28
  from sklearn.decomposition import PCA, FastICA
26
29
 
@@ -35,17 +38,17 @@ LGR = logging.getLogger("GENERAL")
35
38
 
36
39
 
37
40
  def _procOneVoxelTimeShift(
38
- vox,
39
- voxelargs,
40
- **kwargs,
41
- ):
41
+ vox: int,
42
+ voxelargs: tuple,
43
+ **kwargs: Any,
44
+ ) -> tuple[int, NDArray, NDArray, NDArray, NDArray]:
42
45
  options = {
43
46
  "detrendorder": 1,
44
47
  "offsettime": 0.0,
45
48
  "debug": False,
46
49
  }
47
50
  options.update(kwargs)
48
- detrendorder = options["detrendorder"]
51
+ detrendorder = int(options["detrendorder"])
49
52
  offsettime = options["offsettime"]
50
53
  debug = options["debug"]
51
54
  if debug:
@@ -67,108 +70,244 @@ def _procOneVoxelTimeShift(
67
70
  return vox, shiftedtc, weights, paddedshiftedtc, paddedweights
68
71
 
69
72
 
70
- def _packvoxeldata(voxnum, voxelargs):
73
+ def _packvoxeldata(voxnum: int, voxelargs: tuple) -> list:
74
+ """
75
+ Pack voxel data into a list structure.
76
+
77
+ Parameters
78
+ ----------
79
+ voxnum : int
80
+ The voxel index to extract data from.
81
+ voxelargs : tuple
82
+ A tuple containing voxel data with the following structure:
83
+ - voxelargs[0]: 2D array of shape (n_voxels, n_features) containing voxel features
84
+ - voxelargs[1]: 1D array of shape (n_voxels,) containing voxel labels or values
85
+ - voxelargs[2]: Additional voxel parameter (type depends on context)
86
+ - voxelargs[3]: Additional voxel parameter (type depends on context)
87
+
88
+ Returns
89
+ -------
90
+ list
91
+ A list containing:
92
+ - [0]: 1D array of shape (n_features,) representing voxel features at voxnum
93
+ - [1]: scalar value representing voxel label or value at voxnum
94
+ - [2]: third element from voxelargs tuple
95
+ - [3]: fourth element from voxelargs tuple
96
+
97
+ Notes
98
+ -----
99
+ This function is typically used for extracting and packaging voxel data for further processing
100
+ in neuroimaging or 3D data analysis workflows.
101
+
102
+ Examples
103
+ --------
104
+ >>> voxel_features = np.array([[1, 2, 3], [4, 5, 6]])
105
+ >>> voxel_labels = np.array([10, 20])
106
+ >>> extra_param1 = "param1"
107
+ >>> extra_param2 = "param2"
108
+ >>> result = _packvoxeldata(0, (voxel_features, voxel_labels, extra_param1, extra_param2))
109
+ >>> print(result)
110
+ [[1, 2, 3], 10, 'param1', 'param2']
111
+ """
71
112
  return [(voxelargs[0])[voxnum, :], (voxelargs[1])[voxnum], voxelargs[2], voxelargs[3]]
72
113
 
73
114
 
74
- def _unpackvoxeldata(retvals, voxelproducts):
115
+ def _unpackvoxeldata(retvals: tuple, voxelproducts: list) -> None:
116
+ """
117
+ Unpack voxel data from retvals into voxelproducts arrays.
118
+
119
+ Parameters
120
+ ----------
121
+ retvals : tuple
122
+ Tuple containing voxel data to be unpacked. Expected to contain at least 5 elements
123
+ where retvals[0] is the index for assignment and retvals[1:5] are the data arrays.
124
+ voxelproducts : list
125
+ List of arrays where voxel data will be unpacked. Expected to contain exactly 4 arrays
126
+ that will be modified in-place.
127
+
128
+ Returns
129
+ -------
130
+ None
131
+ This function modifies the voxelproducts arrays in-place and does not return anything.
132
+
133
+ Notes
134
+ -----
135
+ This function performs in-place assignment of voxel data. The first element of retvals
136
+ is used as an index for row-wise assignment into each of the four arrays in voxelproducts.
137
+ All arrays in voxelproducts must have sufficient dimensions to accommodate the assignment.
138
+
139
+ Examples
140
+ --------
141
+ >>> import numpy as np
142
+ >>> voxel_data = [np.zeros((10, 5)), np.zeros((10, 5)), np.zeros((10, 5)), np.zeros((10, 5))]
143
+ >>> retvals = (2, np.array([1, 2, 3, 4, 5]), np.array([6, 7, 8, 9, 10]),
144
+ ... np.array([11, 12, 13, 14, 15]), np.array([16, 17, 18, 19, 20]))
145
+ >>> _unpackvoxeldata(retvals, voxel_data)
146
+ >>> print(voxel_data[0][2, :]) # Should print [1 2 3 4 5]
147
+ """
75
148
  (voxelproducts[0])[retvals[0], :] = retvals[1]
76
149
  (voxelproducts[1])[retvals[0], :] = retvals[2]
77
150
  (voxelproducts[2])[retvals[0], :] = retvals[3]
78
151
  (voxelproducts[3])[retvals[0], :] = retvals[4]
79
152
 
80
153
 
81
- def alignvoxels(
82
- fmridata,
83
- fmritr,
84
- shiftedtcs,
85
- weights,
86
- paddedshiftedtcs,
87
- paddedweights,
88
- lagtimes,
89
- lagmask,
90
- detrendorder=1,
91
- offsettime=0.0,
92
- nprocs=1,
93
- alwaysmultiproc=False,
94
- showprogressbar=True,
95
- chunksize=1000,
96
- padtrs=60,
97
- debug=False,
98
- rt_floatset=np.float64,
99
- rt_floattype="float64",
100
- ):
154
+ def findecho(
155
+ nlags: int,
156
+ shiftedtcs: NDArray,
157
+ sigmav: NDArray,
158
+ arcoefs: NDArray,
159
+ pacf: NDArray,
160
+ sigma: NDArray,
161
+ phi: NDArray,
162
+ ) -> None:
101
163
  """
102
- This routine applies a timeshift to every voxel in the image.
103
- Inputs are:
104
- fmridata - the fmri data, filtered to the passband
105
- fmritr - the timestep of the data
106
- shiftedtcs,
107
- weights,
108
- paddedshiftedtcs,
109
- paddedweights,
110
- lagtimes, lagmask - the results of the correlation fit.
111
- detrendorder - the order of the polynomial to use to detrend the data
112
- offsettime - the global timeshift to apply to all timecourses
113
- nprocs - the number of processes to use if multiprocessing is enabled
164
+ Compute autoregressive parameters and related statistics for each voxel using Levinson-Durbin recursion.
165
+
166
+ This function applies the Levinson-Durbin algorithm to estimate autoregressive coefficients
167
+ and associated statistics for time series data from multiple voxels. The algorithm computes
168
+ the variance, autoregressive coefficients, partial autocorrelations, and other related
169
+ parameters for each voxel's time series.
170
+
171
+ Parameters
172
+ ----------
173
+ nlags : int
174
+ Number of lags to compute for the autoregressive model.
175
+ shiftedtcs : NDArray
176
+ Input time series data with shape (n_voxels, n_timepoints), where each row represents
177
+ a voxel's time series.
178
+ sigmav : NDArray
179
+ Output array for variance estimates, shape (n_voxels,).
180
+ arcoefs : NDArray
181
+ Output array for autoregressive coefficients, shape (n_voxels, nlags).
182
+ pacf : NDArray
183
+ Output array for partial autocorrelations, shape (n_voxels, nlags).
184
+ sigma : NDArray
185
+ Output array for sigma values, shape (n_voxels, nlags).
186
+ phi : NDArray
187
+ Output array for phi values, shape (n_voxels, nlags).
188
+
189
+ Returns
190
+ -------
191
+ None
192
+ This function modifies the input arrays in-place and does not return any value.
193
+
194
+ Notes
195
+ -----
196
+ The function uses `statsmodels.tsa.stattools.levinson_durbin` to compute the autoregressive
197
+ parameters. This algorithm is efficient for computing autoregressive parameters and is
198
+ commonly used in time series analysis for estimating model parameters.
199
+
200
+ Examples
201
+ --------
202
+ >>> import numpy as np
203
+ >>> from statsmodels.tsa import stattools
204
+ >>> nlags = 5
205
+ >>> shiftedtcs = np.random.randn(100, 1000)
206
+ >>> sigmav = np.zeros(100)
207
+ >>> arcoefs = np.zeros((100, 5))
208
+ >>> pacf = np.zeros((100, 5))
209
+ >>> sigma = np.zeros((100, 5))
210
+ >>> phi = np.zeros((100, 5))
211
+ >>> findecho(nlags, shiftedtcs, sigmav, arcoefs, pacf, sigma, phi)
212
+ """
213
+ inputshape = np.shape(shiftedtcs)
214
+ for voxel in range(inputshape[0]):
215
+ sigmav[voxel], arcoefs[voxel, :], pacf[voxel, :], sigma[voxel, :], phi[voxel, :] = (
216
+ sm.tsa.stattools.levinson_durbin(shiftedtcs[voxel, :], nlags=nlags, isacov=False)
217
+ )
114
218
 
115
- Explicit outputs are:
116
- volumetotal - the number of voxels processed
117
219
 
118
- Implicit outputs:
119
- shiftedtcs - voxelwise fmri data timeshifted to zero lag
120
- weights - the weights of every timepoint in the final regressor
121
- paddedshiftedtcs - voxelwise fmri data timeshifted to zero lag, with a buffer of padtrs on each end
122
- paddedweights - the weights of every timepoint in the final regressor, with a buffer of padtrs on each end
220
+ def alignvoxels(
221
+ fmridata: NDArray,
222
+ fmritr: float,
223
+ shiftedtcs: NDArray,
224
+ weights: NDArray,
225
+ paddedshiftedtcs: NDArray,
226
+ paddedweights: NDArray,
227
+ lagtimes: NDArray,
228
+ lagmask: NDArray,
229
+ detrendorder: int = 1,
230
+ offsettime: float = 0.0,
231
+ nprocs: int = 1,
232
+ alwaysmultiproc: bool = False,
233
+ showprogressbar: bool = True,
234
+ chunksize: int = 1000,
235
+ padtrs: int = 60,
236
+ debug: bool = False,
237
+ rt_floattype: np.dtype = np.float64,
238
+ ) -> int:
239
+ """
240
+ Apply temporal alignment (timeshift) to all voxels in fMRI data based on correlation peaks.
123
241
 
242
+ This routine applies a time shift to every voxel in the fMRI data based on the lag times
243
+ determined from cross-correlation with a reference signal. The function modifies the input
244
+ arrays in-place to store the aligned timecourses and associated weights.
124
245
 
125
246
  Parameters
126
247
  ----------
127
- fmridata : 4D numpy float array
128
- fMRI data
248
+ fmridata : 4D NDArray
249
+ fMRI data, filtered to the passband, with shape (nx, ny, nz, nt)
129
250
  fmritr : float
130
- Data repetition rate, in seconds
131
- shiftedtcs : 4D numpy float array
132
- Destination array for time aligned voxel timecourses
133
- weights : unknown
134
- unknown
135
- passnum : int
136
- Number of the pass (for labelling output)
137
- lagstrengths : 3D numpy float array
138
- Maximum correlation coefficient in every voxel
139
- lagtimes : 3D numpy float array
140
- Time delay of maximum crosscorrelation in seconds
141
- lagsigma : 3D numpy float array
142
- Gaussian width of the crosscorrelation peak, in seconds.
143
- lagmask : 3D numpy float array
144
- Mask of voxels with successful correlation fits.
145
- R2 : 3D numpy float array
146
- Square of the maximum correlation coefficient in every voxel
147
- theprefilter : function
148
- The filter function to use
149
- optiondict : dict
150
- Dictionary of all internal rapidtide configuration variables.
251
+ Data repetition time (TR), in seconds
252
+ shiftedtcs : 4D NDArray
253
+ Destination array for time-aligned voxel timecourses, shape (nx, ny, nz, nt)
254
+ weights : 4D NDArray
255
+ Weights for each timepoint in the final regressor, shape (nx, ny, nz, nt)
256
+ paddedshiftedtcs : 4D NDArray
257
+ Time-aligned voxel timecourses with padding, shape (nx, ny, nz, nt + 2*padtrs)
258
+ paddedweights : 4D NDArray
259
+ Weights for each timepoint in the padded regressor, shape (nx, ny, nz, nt + 2*padtrs)
260
+ lagtimes : 3D NDArray
261
+ Time delay of maximum crosscorrelation in seconds, shape (nx, ny, nz)
262
+ lagmask : 3D NDArray
263
+ Mask of voxels with successful correlation fits, shape (nx, ny, nz)
264
+ detrendorder : int, optional
265
+ Order of polynomial used to detrend the data (default is 1)
266
+ offsettime : float, optional
267
+ Global time shift to apply to all timecourses in seconds (default is 0.0)
268
+ nprocs : int, optional
269
+ Number of processes to use for multiprocessing (default is 1)
270
+ alwaysmultiproc : bool, optional
271
+ If True, always use multiprocessing even for small datasets (default is False)
272
+ showprogressbar : bool, optional
273
+ If True, show a progress bar during processing (default is True)
274
+ chunksize : int, optional
275
+ Number of voxels to process per chunk in multiprocessing (default is 1000)
151
276
  padtrs : int, optional
152
- Number of timepoints to pad onto each end
153
- includemask : 3D array
154
- Mask of voxels to include in refinement. Default is None (all voxels).
155
- excludemask : 3D array
156
- Mask of voxels to exclude from refinement. Default is None (no voxels).
157
- debug : bool
158
- Enable additional debugging output. Default is False
159
- rt_floatset : function
160
- Function to coerce variable types
161
- rt_floattype : {'float32', 'float64'}
162
- Data type for internal variables
277
+ Number of timepoints to pad on each end of the timecourses (default is 60)
278
+ debug : bool, optional
279
+ If True, enable additional debugging output (default is False)
280
+ rt_floattype : np.dtype, optional
281
+ Function to coerce variable types (default is np.float64)
163
282
 
164
283
  Returns
165
284
  -------
166
285
  volumetotal : int
167
- Number of voxels processed
168
- outputdata : float array
169
- New regressor
170
- maskarray : 3D array
171
- Mask of voxels used for refinement
286
+ Total number of voxels processed
287
+
288
+ Notes
289
+ -----
290
+ This function modifies the input arrays `shiftedtcs`, `weights`, `paddedshiftedtcs`, and
291
+ `paddedweights` in-place. The `lagtimes` and `lagmask` arrays are used to determine the
292
+ appropriate time shifts for each voxel.
293
+
294
+ Examples
295
+ --------
296
+ >>> import numpy as np
297
+ >>> from rapidtide import alignvoxels
298
+ >>> fmridata = np.random.rand(64, 64, 32, 100)
299
+ >>> fmritr = 2.0
300
+ >>> shiftedtcs = np.zeros_like(fmridata)
301
+ >>> weights = np.ones_like(fmridata)
302
+ >>> paddedshiftedtcs = np.zeros((64, 64, 32, 100 + 2*60))
303
+ >>> paddedweights = np.ones((64, 64, 32, 100 + 2*60))
304
+ >>> lagtimes = np.random.rand(64, 64, 32)
305
+ >>> lagmask = np.ones((64, 64, 32))
306
+ >>> volumetotal = alignvoxels(
307
+ ... fmridata, fmritr, shiftedtcs, weights, paddedshiftedtcs, paddedweights,
308
+ ... lagtimes, lagmask, nprocs=4
309
+ ... )
310
+ >>> print(f"Processed {volumetotal} voxels")
172
311
  """
173
312
  inputshape = np.shape(fmridata)
174
313
  voxelargs = [fmridata, lagtimes, padtrs, fmritr]
@@ -220,81 +359,108 @@ def alignvoxels(
220
359
 
221
360
 
222
361
  def makerefinemask(
223
- lagstrengths,
224
- lagtimes,
225
- lagsigma,
226
- lagmask,
227
- offsettime=0.0,
228
- ampthresh=0.3,
229
- lagmaskside="both",
230
- lagminthresh=0.5,
231
- lagmaxthresh=5.0,
232
- sigmathresh=100,
233
- cleanrefined=False,
234
- bipolar=False,
235
- includemask=None,
236
- excludemask=None,
237
- fixdelay=False,
238
- debug=False,
239
- rt_floatset=np.float64,
240
- rt_floattype="float64",
241
- ):
362
+ lagstrengths: NDArray,
363
+ lagtimes: NDArray,
364
+ lagsigma: NDArray,
365
+ lagmask: NDArray,
366
+ offsettime: float = 0.0,
367
+ ampthresh: float = 0.3,
368
+ lagmaskside: str = "both",
369
+ lagminthresh: float = 0.5,
370
+ lagmaxthresh: float = 5.0,
371
+ sigmathresh: float = 100,
372
+ cleanrefined: bool = False,
373
+ bipolar: bool = False,
374
+ includemask: NDArray | None = None,
375
+ excludemask: NDArray | None = None,
376
+ fixdelay: bool = False,
377
+ debug: bool = False,
378
+ rt_floattype: np.dtype = np.float64,
379
+ ) -> tuple[int, NDArray | None, int, int, int, int, int]:
242
380
  """
243
- This routine determines which voxels should be used for regressor refinement.
381
+ Determine which voxels should be used for regressor refinement based on correlation strength,
382
+ time delay, and peak width criteria.
383
+
384
+ This routine evaluates a set of voxels defined by their correlation properties and applies
385
+ various thresholds to determine which ones are suitable for refinement. It supports optional
386
+ masking, bipolar correlation handling, and debugging output.
244
387
 
245
388
  Parameters
246
389
  ----------
247
- lagstrengths : 3D numpy float array
248
- Maximum correlation coefficient in every voxel
249
- lagtimes : 3D numpy float array
250
- Time delay of maximum crosscorrelation in seconds
251
- lagsigma : 3D numpy float array
252
- Gaussian width of the crosscorrelation peak, in seconds.
253
- lagmask : 3D numpy float array
254
- Mask of voxels with successful correlation fits.
255
- offsettime: float
256
- The offset time in seconds to apply to all regressors
257
- ampthresh: float
258
- The lower limit of correlation values to consider for refine mask inclusion
259
- lagmaskside: str
260
- Which side of the lag values to consider - upper, lower, or both
261
- lagminthresh: float
262
- The lower limit of absolute lag values to consider for refine mask inclusion
263
- lagmaxthresh: float
264
- The upper limit of absolute lag values to consider for refine mask inclusion
265
- sigmathresh: float
266
- The upper limit of lag peak width for refine mask inclusion
267
- cleanrefined: bool
268
- If True,
269
- bipolar : bool
270
- If True, consider positive and negative correlation peaks
271
- includemask : 3D array
272
- Mask of voxels to include in refinement. Default is None (all voxels).
273
- excludemask : 3D array
274
- Mask of voxels to exclude from refinement. Default is None (no voxels).
275
- debug : bool
276
- Enable additional debugging output. Default is False
277
- rt_floatset : function
278
- Function to coerce variable types
279
- rt_floattype : {'float32', 'float64'}
280
- Data type for internal variables
390
+ lagstrengths : ndarray
391
+ 3D numpy float array of maximum correlation coefficients in every voxel.
392
+ lagtimes : ndarray
393
+ 3D numpy float array of time delays (in seconds) of maximum crosscorrelation.
394
+ lagsigma : ndarray
395
+ 3D numpy float array of Gaussian widths (in seconds) of the crosscorrelation peaks.
396
+ lagmask : ndarray
397
+ 3D numpy float array masking voxels with successful correlation fits.
398
+ offsettime : float, optional
399
+ Offset time in seconds to apply to all regressors. Default is 0.0.
400
+ ampthresh : float, optional
401
+ Lower limit of correlation values to consider for refine mask inclusion.
402
+ If negative, treated as percentile. Default is 0.3.
403
+ lagmaskside : str, optional
404
+ Which side of the lag values to consider: 'upper', 'lower', or 'both'.
405
+ Default is 'both'.
406
+ lagminthresh : float, optional
407
+ Lower limit of absolute lag values to consider for inclusion. Default is 0.5.
408
+ lagmaxthresh : float, optional
409
+ Upper limit of absolute lag values to consider for inclusion. Default is 5.0.
410
+ sigmathresh : float, optional
411
+ Upper limit of lag peak width (in seconds) for inclusion. Default is 100.
412
+ cleanrefined : bool, optional
413
+ If True, uses the full location mask for refinement; otherwise, uses the refined mask.
414
+ Default is False.
415
+ bipolar : bool, optional
416
+ If True, considers both positive and negative correlation peaks. Default is False.
417
+ includemask : ndarray, optional
418
+ 3D array masking voxels to include in refinement. Default is None (all voxels).
419
+ excludemask : ndarray, optional
420
+ 3D array masking voxels to exclude from refinement. Default is None (no voxels).
421
+ fixdelay : bool, optional
422
+ If True, uses the raw `lagmask` without applying delay thresholds. Default is False.
423
+ debug : bool, optional
424
+ Enable additional debugging output. Default is False.
425
+ rt_floattype : np.dtype, optional
426
+ Data type for internal arrays. Default is `np.float64`.
281
427
 
282
428
  Returns
283
429
  -------
284
430
  volumetotal : int
285
- Number of voxels processed
286
- maskarray : 3D array
287
- Mask of voxels used for refinement
288
- locationfails: int
289
- Number of locations eliminated due to the include and exclude masks
290
- ampfails: int
291
- Number of locations eliminated because the correlation value was too low
292
- lagfails: int
293
- Number of locations eliminated because the lag values were out of range
294
- sigmafails: int
295
- Number of locations eliminated because the correlation peak was too wide
431
+ Number of voxels processed for refinement.
432
+ maskarray : ndarray or None
433
+ 3D mask of voxels used for refinement. Returns None if no voxels remain after filtering.
434
+ locationfails : int
435
+ Number of voxels eliminated due to include/exclude mask constraints.
436
+ ampfails : int
437
+ Number of voxels eliminated due to low correlation amplitude.
438
+ lagfails : int
439
+ Number of voxels eliminated due to lag value out of range.
440
+ sigmafails : int
441
+ Number of voxels eliminated due to wide correlation peak.
442
+ numinmask : int
443
+ Total number of voxels in the original `lagmask`.
444
+
445
+ Notes
446
+ -----
447
+ - The function applies multiple filtering steps: amplitude, lag time, and sigma (peak width).
448
+ - If `ampthresh` is negative, it is interpreted as a percentile threshold.
449
+ - The `lagmaskside` parameter controls which direction of the lag values to consider:
450
+ 'upper' for positive lags, 'lower' for negative lags, 'both' for both.
451
+ - If no voxels remain after filtering, an error is printed and the function returns early.
452
+
453
+ Examples
454
+ --------
455
+ >>> import numpy as np
456
+ >>> lagstrengths = np.random.rand(10, 10, 10)
457
+ >>> lagtimes = np.random.rand(10, 10, 10) * 10
458
+ >>> lagsigma = np.random.rand(10, 10, 10) * 50
459
+ >>> lagmask = np.ones((10, 10, 10))
460
+ >>> volumetotal, maskarray, locfails, ampfails, lagfails, sigfails, numinmask = makerefinemask(
461
+ ... lagstrengths, lagtimes, lagsigma, lagmask, ampthresh=0.4, lagminthresh=1.0
462
+ ... )
296
463
  """
297
-
298
464
  if ampthresh < 0.0:
299
465
  if bipolar:
300
466
  theampthresh = tide_stats.getfracval(np.fabs(lagstrengths), -ampthresh, nozero=True)
@@ -401,16 +567,66 @@ def makerefinemask(
401
567
 
402
568
 
403
569
  def prenorm(
404
- shiftedtcs,
405
- refinemask,
406
- lagtimes,
407
- lagmaxthresh,
408
- lagstrengths,
409
- R2vals,
410
- refineprenorm,
411
- refineweighting,
412
- debug=False,
413
- ):
570
+ shiftedtcs: NDArray,
571
+ refinemask: NDArray,
572
+ lagtimes: NDArray,
573
+ lagmaxthresh: float,
574
+ lagstrengths: NDArray,
575
+ R2vals: NDArray,
576
+ refineprenorm: str,
577
+ refineweighting: str,
578
+ debug: bool = False,
579
+ ) -> None:
580
+ """
581
+ Apply pre-normalization and weighting to shifted time correlation data.
582
+
583
+ This function performs normalization and weighting of time correlation data
584
+ based on specified criteria. It modifies the input `shiftedtcs` array in-place.
585
+
586
+ Parameters
587
+ ----------
588
+ shiftedtcs : NDArray
589
+ Array of shifted time correlation data, shape (n_samples, n_timepoints).
590
+ refinemask : NDArray
591
+ Boolean mask for refining data, shape (n_samples,).
592
+ lagtimes : NDArray
593
+ Array of lag times, shape (n_samples,).
594
+ lagmaxthresh : float
595
+ Threshold for lag time normalization.
596
+ lagstrengths : NDArray
597
+ Array of lag strengths, shape (n_samples,).
598
+ R2vals : NDArray
599
+ Array of R-squared values, shape (n_samples,).
600
+ refineprenorm : str
601
+ Normalization method to use: 'mean', 'var', 'std', or 'invlag'.
602
+ If any other value is provided, unit normalization is applied.
603
+ refineweighting : str
604
+ Weighting method to use: 'R', 'R2', or other (default weighting based on lagstrengths).
605
+ debug : bool, optional
606
+ If True, print debug information about input shapes and intermediate values.
607
+
608
+ Returns
609
+ -------
610
+ None
611
+ The function modifies `shiftedtcs` in-place.
612
+
613
+ Notes
614
+ -----
615
+ The function applies normalization using a divisor computed according to the
616
+ `refineprenorm` parameter and then applies weights based on `refineweighting`.
617
+ The `shiftedtcs` array is updated in-place.
618
+
619
+ Examples
620
+ --------
621
+ >>> import numpy as np
622
+ >>> shiftedtcs = np.random.rand(10, 5)
623
+ >>> refinemask = np.ones(10, dtype=bool)
624
+ >>> lagtimes = np.arange(10)
625
+ >>> lagmaxthresh = 2.0
626
+ >>> lagstrengths = np.random.rand(10)
627
+ >>> R2vals = np.random.rand(10)
628
+ >>> prenorm(shiftedtcs, refinemask, lagtimes, lagmaxthresh, lagstrengths, R2vals, "mean", "R", debug=True)
629
+ """
414
630
  if debug:
415
631
  print(f"{shiftedtcs.shape=}"),
416
632
  print(f"{refinemask.shape=}"),
@@ -450,30 +666,119 @@ def prenorm(
450
666
 
451
667
 
452
668
  def dorefine(
453
- shiftedtcs,
454
- refinemask,
455
- weights,
456
- theprefilter,
457
- fmritr,
458
- passnum,
459
- lagstrengths,
460
- lagtimes,
461
- refinetype,
462
- fmrifreq,
463
- outputname,
464
- detrendorder=1,
465
- pcacomponents=0.8,
466
- dodispersioncalc=False,
467
- dispersioncalc_lower=0.0,
468
- dispersioncalc_upper=0.0,
469
- dispersioncalc_step=0.0,
470
- windowfunc="hamming",
471
- cleanrefined=False,
472
- bipolar=False,
473
- debug=False,
474
- rt_floatset=np.float64,
475
- rt_floattype="float64",
476
- ):
669
+ shiftedtcs: NDArray,
670
+ refinemask: NDArray,
671
+ weights: NDArray,
672
+ theprefilter: Any,
673
+ fmritr: float,
674
+ passnum: int,
675
+ lagstrengths: NDArray,
676
+ lagtimes: NDArray,
677
+ refinetype: str,
678
+ fmrifreq: float,
679
+ outputname: str,
680
+ detrendorder: int = 1,
681
+ pcacomponents: float | str = 0.8,
682
+ dodispersioncalc: bool = False,
683
+ dispersioncalc_lower: float = 0.0,
684
+ dispersioncalc_upper: float = 0.0,
685
+ dispersioncalc_step: float = 0.0,
686
+ windowfunc: str = "hamming",
687
+ cleanrefined: bool = False,
688
+ bipolar: bool = False,
689
+ debug: bool = False,
690
+ rt_floattype: np.dtype = np.float64,
691
+ ) -> tuple[int, NDArray]:
692
+ """
693
+ Refine timecourses using specified method (ICA, PCA, weighted average, or unweighted average).
694
+
695
+ This function applies a refinement process to a set of timecourses based on a mask and
696
+ weights. It supports multiple refinement techniques including ICA, PCA, and averaging,
697
+ and can optionally perform dispersion calculation and cleaning of refined data.
698
+
699
+ Parameters
700
+ ----------
701
+ shiftedtcs : ndarray
702
+ Array of shape (n_voxels, n_timepoints) containing the shifted timecourses.
703
+ refinemask : ndarray
704
+ Boolean mask indicating which voxels to include in refinement.
705
+ weights : ndarray
706
+ Array of shape (n_voxels, n_timepoints) containing weights for each voxel.
707
+ theprefilter : Any
708
+ Pre-filter object with an `apply` method to filter the data.
709
+ fmritr : float
710
+ fMRI repetition time in seconds.
711
+ passnum : int
712
+ Pass number for output file naming.
713
+ lagstrengths : ndarray
714
+ Array of lag strengths for each voxel.
715
+ lagtimes : ndarray
716
+ Array of lag times for each voxel.
717
+ refinetype : str
718
+ Type of refinement to perform: 'ica', 'pca', 'weighted_average', or 'unweighted_average'.
719
+ fmrifreq : float
720
+ fMRI frequency in Hz.
721
+ outputname : str
722
+ Base name for output files.
723
+ detrendorder : int, optional
724
+ Order of detrending for correlation normalization (default is 1).
725
+ pcacomponents : float or str, optional
726
+ Number of PCA components to use. If < 1, treated as fraction of variance; if 'mle', uses MLE.
727
+ Default is 0.8.
728
+ dodispersioncalc : bool, optional
729
+ If True, compute dispersion calculation across lag ranges (default is False).
730
+ dispersioncalc_lower : float, optional
731
+ Lower bound for dispersion calculation lag range (default is 0.0).
732
+ dispersioncalc_upper : float, optional
733
+ Upper bound for dispersion calculation lag range (default is 0.0).
734
+ dispersioncalc_step : float, optional
735
+ Step size for dispersion calculation lag range (default is 0.0).
736
+ windowfunc : str, optional
737
+ Window function for correlation normalization (default is "hamming").
738
+ cleanrefined : bool, optional
739
+ If True, remove linearly fitted discard data from refined output (default is False).
740
+ bipolar : bool, optional
741
+ If True, flip sign of negative lag strengths (default is False).
742
+ debug : bool, optional
743
+ If True, print debug information (default is False).
744
+ rt_floattype : np.dtype, optional
745
+ Data type for floating-point numbers (default is np.float64).
746
+
747
+ Returns
748
+ -------
749
+ tuple[int, ndarray]
750
+ A tuple containing:
751
+ - `volumetotal`: int, total number of voxels included in refinement.
752
+ - `outputdata`: ndarray, refined timecourse of shape (n_timepoints,).
753
+
754
+ Notes
755
+ -----
756
+ - The function supports multiple refinement methods: ICA, PCA, weighted average, and
757
+ unweighted average.
758
+ - If `cleanrefined` is True, a linear regression is performed to remove discard data
759
+ from the refined output.
760
+ - If `dodispersioncalc` is True, dispersion calculation is performed across lag ranges
761
+ and outputs are saved to files with the prefix `outputname`.
762
+
763
+ Examples
764
+ --------
765
+ >>> import numpy as np
766
+ >>> shiftedtcs = np.random.rand(100, 200)
767
+ >>> refinemask = np.ones(100)
768
+ >>> weights = np.ones((100, 200))
769
+ >>> theprefilter = SomeFilter()
770
+ >>> fmritr = 2.0
771
+ >>> passnum = 1
772
+ >>> lagstrengths = np.random.rand(100)
773
+ >>> lagtimes = np.random.rand(100)
774
+ >>> refinetype = "pca"
775
+ >>> fmrifreq = 0.1
776
+ >>> outputname = "test_output"
777
+ >>> volumetotal, outputdata = dorefine(
778
+ ... shiftedtcs, refinemask, weights, theprefilter, fmritr, passnum,
779
+ ... lagstrengths, lagtimes, refinetype, fmrifreq, outputname
780
+ ... )
781
+ """
477
782
  # now generate the refined timecourse(s)
478
783
  inputshape = np.shape(shiftedtcs)
479
784
  validlist = np.where(refinemask > 0)[0]
@@ -569,7 +874,7 @@ def dorefine(
569
874
  theprefilter.apply(fmrifreq, icadata),
570
875
  detrendorder=detrendorder,
571
876
  )
572
- thepxcorr = pearsonr(filteredavg, filteredica)[0]
877
+ thepxcorr = pearsonr(filteredavg, filteredica).statistic
573
878
  LGR.info(f"ica/avg correlation = {thepxcorr}")
574
879
  if thepxcorr > 0.0:
575
880
  outputdata = 1.0 * icadata
@@ -604,7 +909,7 @@ def dorefine(
604
909
  theprefilter.apply(fmrifreq, pcadata),
605
910
  detrendorder=detrendorder,
606
911
  )
607
- thepxcorr = pearsonr(filteredavg, filteredpca)[0]
912
+ thepxcorr = pearsonr(filteredavg, filteredpca).statistic
608
913
  LGR.info(f"pca/avg correlation = {thepxcorr}")
609
914
  if thepxcorr > 0.0:
610
915
  outputdata = 1.0 * pcadata
@@ -620,8 +925,8 @@ def dorefine(
620
925
  if cleanrefined:
621
926
  thefit, R2 = tide_fit.mlregress(averagediscard, averagedata)
622
927
 
623
- fitcoff = rt_floatset(thefit[0, 1])
624
- datatoremove = rt_floatset(fitcoff * averagediscard)
928
+ fitcoff = thefit[0, 1]
929
+ datatoremove = (fitcoff * averagediscard).astype(rt_floattype)
625
930
  outputdata -= datatoremove
626
931
 
627
932
  # garbage collect