rapidtide 3.0.11__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 (139) 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 +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 +25 -3
  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 +2225 -108
  24. rapidtide/dlfiltertorch.py +4843 -0
  25. rapidtide/externaltools.py +327 -12
  26. rapidtide/fMRIData_class.py +79 -40
  27. rapidtide/filter.py +1899 -810
  28. rapidtide/fit.py +2004 -574
  29. rapidtide/genericmultiproc.py +93 -18
  30. rapidtide/happy_supportfuncs.py +2044 -171
  31. rapidtide/helper_classes.py +584 -43
  32. rapidtide/io.py +2363 -370
  33. rapidtide/linfitfiltpass.py +341 -75
  34. rapidtide/makelaggedtcs.py +211 -20
  35. rapidtide/maskutil.py +423 -53
  36. rapidtide/miscmath.py +827 -121
  37. rapidtide/multiproc.py +210 -22
  38. rapidtide/patchmatch.py +234 -33
  39. rapidtide/peakeval.py +32 -30
  40. rapidtide/ppgproc.py +2203 -0
  41. rapidtide/qualitycheck.py +352 -39
  42. rapidtide/refinedelay.py +422 -57
  43. rapidtide/refineregressor.py +498 -184
  44. rapidtide/resample.py +671 -185
  45. rapidtide/scripts/applyppgproc.py +28 -0
  46. rapidtide/simFuncClasses.py +1052 -77
  47. rapidtide/simfuncfit.py +260 -46
  48. rapidtide/stats.py +540 -238
  49. rapidtide/tests/happycomp +9 -0
  50. rapidtide/tests/test_dlfiltertorch.py +627 -0
  51. rapidtide/tests/test_findmaxlag.py +24 -8
  52. rapidtide/tests/test_fullrunhappy_v1.py +0 -2
  53. rapidtide/tests/test_fullrunhappy_v2.py +0 -2
  54. rapidtide/tests/test_fullrunhappy_v3.py +1 -0
  55. rapidtide/tests/test_fullrunhappy_v4.py +2 -2
  56. rapidtide/tests/test_fullrunrapidtide_v7.py +1 -1
  57. rapidtide/tests/test_simroundtrip.py +8 -8
  58. rapidtide/tests/utils.py +9 -8
  59. rapidtide/tidepoolTemplate.py +142 -38
  60. rapidtide/tidepoolTemplate_alt.py +165 -44
  61. rapidtide/tidepoolTemplate_big.py +189 -52
  62. rapidtide/util.py +1217 -118
  63. rapidtide/voxelData.py +684 -37
  64. rapidtide/wiener.py +19 -12
  65. rapidtide/wiener2.py +113 -7
  66. rapidtide/wiener_doc.py +255 -0
  67. rapidtide/workflows/adjustoffset.py +105 -3
  68. rapidtide/workflows/aligntcs.py +85 -2
  69. rapidtide/workflows/applydlfilter.py +87 -10
  70. rapidtide/workflows/applyppgproc.py +522 -0
  71. rapidtide/workflows/atlasaverage.py +210 -47
  72. rapidtide/workflows/atlastool.py +100 -3
  73. rapidtide/workflows/calcSimFuncMap.py +294 -64
  74. rapidtide/workflows/calctexticc.py +201 -9
  75. rapidtide/workflows/ccorrica.py +97 -4
  76. rapidtide/workflows/cleanregressor.py +168 -29
  77. rapidtide/workflows/delayvar.py +163 -10
  78. rapidtide/workflows/diffrois.py +81 -3
  79. rapidtide/workflows/endtidalproc.py +144 -4
  80. rapidtide/workflows/fdica.py +195 -15
  81. rapidtide/workflows/filtnifti.py +70 -3
  82. rapidtide/workflows/filttc.py +74 -3
  83. rapidtide/workflows/fitSimFuncMap.py +206 -48
  84. rapidtide/workflows/fixtr.py +73 -3
  85. rapidtide/workflows/gmscalc.py +113 -3
  86. rapidtide/workflows/happy.py +801 -199
  87. rapidtide/workflows/happy2std.py +144 -12
  88. rapidtide/workflows/happy_parser.py +138 -9
  89. rapidtide/workflows/histnifti.py +118 -2
  90. rapidtide/workflows/histtc.py +84 -3
  91. rapidtide/workflows/linfitfilt.py +117 -4
  92. rapidtide/workflows/localflow.py +328 -28
  93. rapidtide/workflows/mergequality.py +79 -3
  94. rapidtide/workflows/niftidecomp.py +322 -18
  95. rapidtide/workflows/niftistats.py +174 -4
  96. rapidtide/workflows/pairproc.py +88 -2
  97. rapidtide/workflows/pairwisemergenifti.py +85 -2
  98. rapidtide/workflows/parser_funcs.py +1421 -40
  99. rapidtide/workflows/physiofreq.py +137 -11
  100. rapidtide/workflows/pixelcomp.py +208 -5
  101. rapidtide/workflows/plethquality.py +103 -21
  102. rapidtide/workflows/polyfitim.py +151 -11
  103. rapidtide/workflows/proj2flow.py +75 -2
  104. rapidtide/workflows/rankimage.py +111 -4
  105. rapidtide/workflows/rapidtide.py +272 -15
  106. rapidtide/workflows/rapidtide2std.py +98 -2
  107. rapidtide/workflows/rapidtide_parser.py +109 -9
  108. rapidtide/workflows/refineDelayMap.py +143 -33
  109. rapidtide/workflows/refineRegressor.py +682 -93
  110. rapidtide/workflows/regressfrommaps.py +152 -31
  111. rapidtide/workflows/resamplenifti.py +85 -3
  112. rapidtide/workflows/resampletc.py +91 -3
  113. rapidtide/workflows/retrolagtcs.py +98 -6
  114. rapidtide/workflows/retroregress.py +165 -9
  115. rapidtide/workflows/roisummarize.py +173 -5
  116. rapidtide/workflows/runqualitycheck.py +71 -3
  117. rapidtide/workflows/showarbcorr.py +147 -4
  118. rapidtide/workflows/showhist.py +86 -2
  119. rapidtide/workflows/showstxcorr.py +160 -3
  120. rapidtide/workflows/showtc.py +159 -3
  121. rapidtide/workflows/showxcorrx.py +184 -4
  122. rapidtide/workflows/showxy.py +185 -15
  123. rapidtide/workflows/simdata.py +262 -36
  124. rapidtide/workflows/spatialfit.py +77 -2
  125. rapidtide/workflows/spatialmi.py +251 -27
  126. rapidtide/workflows/spectrogram.py +305 -32
  127. rapidtide/workflows/synthASL.py +154 -3
  128. rapidtide/workflows/tcfrom2col.py +76 -2
  129. rapidtide/workflows/tcfrom3col.py +74 -2
  130. rapidtide/workflows/tidepool.py +2969 -130
  131. rapidtide/workflows/utils.py +19 -14
  132. rapidtide/workflows/utils_doc.py +293 -0
  133. rapidtide/workflows/variabilityizer.py +116 -3
  134. {rapidtide-3.0.11.dist-info → rapidtide-3.1.dist-info}/METADATA +3 -2
  135. {rapidtide-3.0.11.dist-info → rapidtide-3.1.dist-info}/RECORD +139 -122
  136. {rapidtide-3.0.11.dist-info → rapidtide-3.1.dist-info}/entry_points.txt +1 -0
  137. {rapidtide-3.0.11.dist-info → rapidtide-3.1.dist-info}/WHEEL +0 -0
  138. {rapidtide-3.0.11.dist-info → rapidtide-3.1.dist-info}/licenses/LICENSE +0 -0
  139. {rapidtide-3.0.11.dist-info → rapidtide-3.1.dist-info}/top_level.txt +0 -0
rapidtide/resample.py CHANGED
@@ -31,14 +31,18 @@ with warnings.catch_warnings():
31
31
  else:
32
32
  pyfftwpresent = True
33
33
 
34
- import pylab as pl
34
+ from typing import Any, Callable, Optional, Tuple, Union
35
+
36
+ import matplotlib.pyplot as plt
35
37
  import scipy as sp
38
+ from numpy.typing import ArrayLike, NDArray
36
39
  from scipy import fftpack, signal
37
40
 
38
41
  import rapidtide.filter as tide_filt
39
42
  import rapidtide.fit as tide_fit
40
43
  import rapidtide.io as tide_io
41
44
  import rapidtide.util as tide_util
45
+ from rapidtide.decorators import conditionaljit, conditionaljit2
42
46
 
43
47
  if pyfftwpresent:
44
48
  fftpack = pyfftw.interfaces.scipy_fftpack
@@ -50,125 +54,77 @@ import warnings
50
54
 
51
55
  warnings.simplefilter(action="ignore", category=RuntimeWarning)
52
56
 
53
- # ---------------------------------------- Global constants -------------------------------------------
54
- donotbeaggressive = True
55
-
56
- # ----------------------------------------- Conditional imports ---------------------------------------
57
- try:
58
- from numba import jit
59
- except ImportError:
60
- donotusenumba = True
61
- else:
62
- donotusenumba = False
63
-
64
-
65
- def conditionaljit():
66
- def resdec(f):
67
- if donotusenumba:
68
- return f
69
- return jit(f, nopython=True)
70
-
71
- return resdec
72
-
73
-
74
- def conditionaljit2():
75
- def resdec(f):
76
- if donotusenumba or donotbeaggressive:
77
- return f
78
- return jit(f, nopython=True)
79
-
80
- return resdec
81
-
82
-
83
- def disablenumba():
84
- global donotusenumba
85
- donotusenumba = True
86
-
87
-
88
57
  # --------------------------- Resampling and time shifting functions -------------------------------------------
89
- """
90
- class ConvolutionGridder:
91
- def __init__(self, timeaxis, width, method='gauss', circular=True, upsampleratio=100, doplot=False, debug=False):
92
- self.upsampleratio = upsampleratio
93
- self.initstep = timeaxis[1] - timeaxis[0]
94
- self.initstart = timeaxis[0]
95
- self.initend = timeaxis[-1]
96
- self.hiresstep = self.initstep / np.float64(self.upsampleratio)
97
- if method == 'gauss':
98
- fullwidth = 2.355 * width
99
- fullwidthpts = int(np.round(fullwidth / self.hiresstep, 0))
100
- fullwidthpts += ((fullwidthpts % 2) - 1)
101
- self.hires_x = np.linspace(-fullwidth / 2.0, fullwidth / 2.0, numpts = fullwidthpts, endpoint=True)
102
- if method == 'gauss':
103
- self.hires_y = tide_fit.gauss_eval(self.hires_x, np.array([1.0, 0.0, width])
104
- if debug:
105
- print(self.hires_x)
106
- if doplot:
107
- fig = pl.figure()
108
- ax = fig.add_subplot(111)
109
- ax.set_title('congrid convolution function')
110
- pl.plot(self.hires_x, self.hires_y)
111
- pl.legend(('input', 'hires'))
112
- pl.show()
113
-
114
- def gridded(xvals, yvals):
115
- if len(xvals) != len(yvals):
116
- print('x and y vectors do not match - aborting')
117
- return None
118
- for i in range(len(xvals)):
119
- outindices = ((newtimeaxis - self.hiresstart) // self.hiresstep).astype(int)
120
- """
121
-
122
- congridyvals = {}
58
+ congridyvals: dict = {}
123
59
  congridyvals["kernel"] = "kaiser"
124
60
  congridyvals["width"] = 3.0
125
61
 
126
62
 
127
63
  def congrid(
128
- xaxis,
129
- loc,
130
- val,
131
- width,
132
- kernel="kaiser",
133
- cache=True,
134
- cyclic=True,
135
- debug=False,
136
- onlykeynotices=True,
137
- ):
64
+ xaxis: NDArray[np.floating[Any]],
65
+ loc: float,
66
+ val: float,
67
+ width: float,
68
+ kernel: str = "kaiser",
69
+ cache: bool = True,
70
+ cyclic: bool = True,
71
+ debug: bool = False,
72
+ onlykeynotices: bool = True,
73
+ ) -> Tuple[NDArray[np.floating[Any]], NDArray[np.floating[Any]], NDArray[np.floating[Any]]]:
138
74
  """
139
- Perform a convolution gridding operation with a Kaiser-Bessel or Gaussian kernel of width 'width'. Grid
140
- parameters are cached for performance.
75
+ Perform a convolution gridding operation with a Kaiser-Bessel or Gaussian kernel.
76
+
77
+ This function convolves a given value with a specified gridding kernel and projects
78
+ the result onto a target axis. It supports both cyclic and non-cyclic boundary
79
+ conditions and caches kernel values for performance optimization.
141
80
 
142
81
  Parameters
143
82
  ----------
144
- xaxis: array-like
145
- The target axis for resampling
146
- loc: float
147
- The location, in x-axis units, of the sample to be gridded
148
- val: float
149
- The value to be gridded
150
- width: float
151
- The width of the gridding kernel in target bins
152
- kernel: {'old', 'gauss', 'kaiser'}, optional
153
- The type of convolution gridding kernel. Default is 'kaiser'.
154
- cyclic: bool, optional
155
- When True, gridding wraps around the endpoints of xaxis. Default is True.
156
- debug: bool, optional
157
- When True, output additional information about the gridding process
83
+ xaxis : NDArray[np.floating[Any]]
84
+ The target axis for resampling. Should be a 1D array of evenly spaced points.
85
+ loc : float
86
+ The location, in x-axis units, of the sample to be gridded.
87
+ val : float
88
+ The value to be gridded.
89
+ width : float
90
+ The width of the gridding kernel in target bins. Must be a half-integral value
91
+ between 1.5 and 5.0 inclusive.
92
+ kernel : {'old', 'gauss', 'kaiser'}, optional
93
+ The type of convolution gridding kernel. Default is 'kaiser'.
94
+ - 'old': Uses a Gaussian kernel with fixed width.
95
+ - 'gauss': Uses a Gaussian kernel with optimized sigma.
96
+ - 'kaiser': Uses a Kaiser-Bessel kernel with optimized beta.
97
+ cache : bool, optional
98
+ If True, caches kernel values for performance. Default is True.
99
+ cyclic : bool, optional
100
+ When True, gridding wraps around the endpoints of xaxis. Default is True.
101
+ debug : bool, optional
102
+ When True, outputs additional information about the gridding process.
103
+ Default is False.
104
+ onlykeynotices : bool, optional
105
+ When True, suppresses certain debug messages. Default is True.
158
106
 
159
107
  Returns
160
108
  -------
161
- vals: array-like
162
- The input value, convolved with the gridding kernel, projected on to x axis points
163
- weights: array-like
164
- The values of convolution kernel, projected on to x axis points (used for normalization)
165
- indices: array-like
166
- The indices along the x axis where the vals and weights fall.
109
+ vals : NDArray[np.floating[Any]]
110
+ The input value, convolved with the gridding kernel, projected onto x-axis points.
111
+ weights : NDArray[np.floating[Any]]
112
+ The values of the convolution kernel, projected onto x-axis points (used for normalization).
113
+ indices : NDArray[int[Any]]
114
+ The indices along the x-axis where the vals and weights fall.
167
115
 
168
116
  Notes
169
117
  -----
170
- See IEEE TRANSACTIONS ON MEDICAL IMAGING. VOL. IO.NO. 3, SEPTEMBER 1991
171
-
118
+ This implementation is based on the method described in:
119
+ IEEE TRANSACTIONS ON MEDICAL IMAGING. VOL. 10, NO. 3, SEPTEMBER 1991
120
+
121
+ Examples
122
+ --------
123
+ >>> import numpy as np
124
+ >>> xaxis = np.linspace(0, 10, 100)
125
+ >>> vals, weights, indices = congrid(xaxis, 5.5, 1.0, 2.0)
126
+ >>> print(vals.shape)
127
+ (100,)
172
128
  """
173
129
  global congridyvals
174
130
 
@@ -247,7 +203,7 @@ def congrid(
247
203
  offsetinpts = center + offset
248
204
  startpt = int(np.ceil(offsetinpts - width / 2.0))
249
205
  endpt = int(np.floor(offsetinpts + width / 2.0))
250
- indices = np.remainder(range(startpt, endpt + 1), len(xaxis))
206
+ indices = np.remainder(np.array(list(range(startpt, endpt + 1))), len(xaxis))
251
207
  try:
252
208
  yvals = congridyvals[offsetkey]
253
209
  except KeyError:
@@ -283,6 +239,53 @@ class FastResampler:
283
239
  debug=False,
284
240
  method="univariate",
285
241
  ):
242
+ """
243
+ Initialize the FastResampler with given time axis and time course data.
244
+
245
+ This constructor prepares high-resolution time series data by resampling the input
246
+ time course using one of several methods, with optional padding and plotting.
247
+
248
+ Parameters
249
+ ----------
250
+ timeaxis : array-like
251
+ The time axis of the input data. Should be a 1D array of time points.
252
+ timecourse : array-like
253
+ The time course data corresponding to `timeaxis`. Should be a 1D array of values.
254
+ padtime : float, optional
255
+ Padding time in seconds to extend the resampled time axis on both ends.
256
+ Default is 30.0.
257
+ upsampleratio : int, optional
258
+ The upsampling ratio used for resampling. Default is 100.
259
+ doplot : bool, optional
260
+ If True, plot the original and high-resolution time courses. Default is False.
261
+ debug : bool, optional
262
+ If True, print debug information during initialization. Default is False.
263
+ method : str, optional
264
+ Resampling method to use. Options are:
265
+ - "univariate": Uses custom resampling logic.
266
+ - "poly": Uses `scipy.signal.resample_poly`.
267
+ - "fourier": Uses `scipy.signal.resample`.
268
+ Default is "univariate".
269
+
270
+ Returns
271
+ -------
272
+ None
273
+ This method initializes instance attributes and does not return a value.
274
+
275
+ Notes
276
+ -----
277
+ The resampled time axis (`hires_x`) is generated by extending the original time axis
278
+ by `padtime` on each side, using a step size that is `1 / upsampleratio` of the
279
+ original step size. The `hires_y` array contains the resampled time course values.
280
+
281
+ Examples
282
+ --------
283
+ >>> import numpy as np
284
+ >>> from scipy import signal
285
+ >>> timeaxis = np.linspace(0, 10, 100)
286
+ >>> timecourse = np.sin(timeaxis)
287
+ >>> resampler = FastResampler(timeaxis, timecourse, padtime=5.0, method="poly")
288
+ """
286
289
  self.timeaxis = timeaxis
287
290
  self.timecourse = timecourse
288
291
  self.upsampleratio = upsampleratio
@@ -331,17 +334,98 @@ class FastResampler:
331
334
  if doplot:
332
335
  import matplolib.pyplot as pl
333
336
 
334
- fig = pl.figure()
337
+ fig = plt.figure()
335
338
  ax = fig.add_subplot(111)
336
339
  ax.set_title("FastResampler initial timecourses")
337
- pl.plot(timeaxis, timecourse, self.hires_x, self.hires_y)
338
- pl.legend(("input", "hires"))
339
- pl.show()
340
+ plt.plot(timeaxis, timecourse, self.hires_x, self.hires_y)
341
+ plt.legend(("input", "hires"))
342
+ plt.show()
340
343
 
341
344
  def getdata(self):
345
+ """
346
+ Retrieve time series data and related parameters.
347
+
348
+ Returns
349
+ -------
350
+ tuple
351
+ A tuple containing:
352
+ - timeaxis : array_like
353
+ Time axis values
354
+ - timecourse : array_like
355
+ Time course data values
356
+ - hires_x : array_like
357
+ High resolution x-axis data
358
+ - hires_y : array_like
359
+ High resolution y-axis data
360
+ - inverse_initstep : float
361
+ Reciprocal of the initial step size (1.0 / self.initstep)
362
+
363
+ Notes
364
+ -----
365
+ This function provides access to all time series data and associated
366
+ high resolution parameters stored in the object instance. The returned
367
+ inverse_initstep value is commonly used for normalization or scaling
368
+ operations in time series analysis.
369
+
370
+ Examples
371
+ --------
372
+ >>> data = obj.getdata()
373
+ >>> time_axis, time_course, hires_x, hires_y, inv_step = data
374
+ >>> print(f"Time course shape: {time_course.shape}")
375
+ """
342
376
  return self.timeaxis, self.timecourse, self.hires_x, self.hires_y, 1.0 / self.initstep
343
377
 
344
378
  def info(self, prefix=""):
379
+ """
380
+ Print information about the object's time and sampling parameters.
381
+
382
+ This method displays various time-related attributes and sampling parameters
383
+ of the object, with optional prefix for better formatting in output.
384
+
385
+ Parameters
386
+ ----------
387
+ prefix : str, optional
388
+ String to prepend to each printed line, useful for indentation or
389
+ grouping related output. Default is empty string.
390
+
391
+ Returns
392
+ -------
393
+ None
394
+ This method prints information to stdout and does not return any value.
395
+
396
+ Notes
397
+ -----
398
+ The method prints the following attributes:
399
+ - timeaxis: Time axis values
400
+ - timecourse: Time course data
401
+ - upsampleratio: Upsampling ratio
402
+ - padtime: Padding time
403
+ - initstep: Initial step size
404
+ - initstart: Initial start time
405
+ - initend: Initial end time
406
+ - hiresstep: High-resolution step size
407
+ - hires_x[0]: First value of high-resolution x-axis
408
+ - hires_x[-1]: Last value of high-resolution x-axis
409
+ - hiresstart: High-resolution start time
410
+ - hiresend: High-resolution end time
411
+ - method: Interpolation/processing method used
412
+ - hires_y[0]: First value of high-resolution y-axis
413
+ - hires_y[-1]: Last value of high-resolution y-axis
414
+
415
+ Examples
416
+ --------
417
+ >>> obj.info()
418
+ timeaxis=100
419
+ timecourse=200
420
+ upsampleratio=4
421
+ ...
422
+
423
+ >>> obj.info(prefix=" ")
424
+ timeaxis=100
425
+ timecourse=200
426
+ upsampleratio=4
427
+ ...
428
+ """
345
429
  print(f"{prefix}{self.timeaxis=}")
346
430
  print(f"{prefix}{self.timecourse=}")
347
431
  print(f"{prefix}{self.upsampleratio=}")
@@ -359,6 +443,35 @@ class FastResampler:
359
443
  print(f"{prefix}{self.hires_y[-1]=}")
360
444
 
361
445
  def save(self, outputname):
446
+ """
447
+ Save the timecourse data to a TSV file.
448
+
449
+ This method writes the internal timecourse data to a tab-separated values file
450
+ with additional metadata in the header. The output includes the timecourse data
451
+ along with timing information derived from the object's initialization parameters.
452
+
453
+ Parameters
454
+ ----------
455
+ outputname : str
456
+ The path and filename where the TSV output will be saved.
457
+
458
+ Returns
459
+ -------
460
+ None
461
+ This method does not return any value.
462
+
463
+ Notes
464
+ -----
465
+ The method uses the `tide_io.writebidstsv` function to perform the actual file writing.
466
+ The time step is calculated as 1.0 divided by `self.initstep`, and the start time
467
+ is taken from `self.initstart`. The output file includes a header with description
468
+ metadata indicating this is a lagged timecourse generator.
469
+
470
+ Examples
471
+ --------
472
+ >>> obj.save("output_timecourse.tsv")
473
+ >>> # Creates a TSV file with the timecourse data and metadata
474
+ """
362
475
  tide_io.writebidstsv(
363
476
  outputname,
364
477
  self.timecourse,
@@ -370,6 +483,41 @@ class FastResampler:
370
483
  )
371
484
 
372
485
  def yfromx(self, newtimeaxis, doplot=False, debug=False):
486
+ """
487
+ Resample y-values from a high-resolution time axis to a new time axis.
488
+
489
+ This method maps values from a high-resolution y-array (`self.hires_y`) to a
490
+ new time axis (`newtimeaxis`) by linear interpolation based on the step size
491
+ and start of the high-resolution axis.
492
+
493
+ Parameters
494
+ ----------
495
+ newtimeaxis : array-like
496
+ The new time axis to which the y-values will be resampled.
497
+ doplot : bool, optional
498
+ If True, plot the original high-resolution y-values and the resampled
499
+ values for comparison. Default is False.
500
+ debug : bool, optional
501
+ If True, print debug information including internal parameters and
502
+ bounds checking. Default is False.
503
+
504
+ Returns
505
+ -------
506
+ out_y : ndarray
507
+ The resampled y-values corresponding to `newtimeaxis`.
508
+
509
+ Notes
510
+ -----
511
+ This function assumes that `self.hires_y` has been precomputed and that
512
+ the internal parameters (`self.hiresstart`, `self.hiresstep`) are valid.
513
+ An IndexError is raised if any index in `outindices` is out of bounds.
514
+
515
+ Examples
516
+ --------
517
+ >>> resampler = FastResampler()
518
+ >>> new_times = np.linspace(0, 10, 100)
519
+ >>> y_vals = resampler.yfromx(new_times, doplot=True)
520
+ """
373
521
  if debug:
374
522
  print("FastResampler: yfromx called with following parameters")
375
523
  print(" padtime:, ", self.padtime)
@@ -392,16 +540,59 @@ class FastResampler:
392
540
  print(" requested axis limits:", newtimeaxis[0], newtimeaxis[-1])
393
541
  sys.exit()
394
542
  if doplot:
395
- fig = pl.figure()
543
+ fig = plt.figure()
396
544
  ax = fig.add_subplot(111)
397
545
  ax.set_title("FastResampler timecourses")
398
- pl.plot(self.hires_x, self.hires_y, newtimeaxis, out_y)
399
- pl.legend(("hires", "output"))
400
- pl.show()
546
+ plt.plot(self.hires_x, self.hires_y, newtimeaxis, out_y)
547
+ plt.legend(("hires", "output"))
548
+ plt.show()
401
549
  return out_y
402
550
 
403
551
 
404
- def FastResamplerFromFile(inputname, colspec=None, debug=False, **kwargs):
552
+ def FastResamplerFromFile(
553
+ inputname: str, colspec: Optional[str] = None, debug: bool = False, **kwargs
554
+ ) -> FastResampler:
555
+ """
556
+ Create a FastResampler from a BIDS TSV file.
557
+
558
+ This function reads data from a BIDS TSV file and creates a FastResampler object
559
+ for efficient time series resampling operations. The input file must contain
560
+ exactly one column of data.
561
+
562
+ Parameters
563
+ ----------
564
+ inputname : str
565
+ Path to the input BIDS TSV file containing the time series data
566
+ colspec : str, optional
567
+ Column specification for selecting specific columns from the TSV file.
568
+ If None, all columns are read (default: None)
569
+ debug : bool, optional
570
+ Enable debug output printing (default: False)
571
+ **kwargs
572
+ Additional keyword arguments passed to the FastResampler constructor
573
+
574
+ Returns
575
+ -------
576
+ FastResampler
577
+ A FastResampler object initialized with the time axis and data from the input file
578
+
579
+ Raises
580
+ ------
581
+ ValueError
582
+ If the input file contains multiple columns of data
583
+
584
+ Notes
585
+ -----
586
+ The function internally calls `tide_io.readbidstsv` to read the input file and
587
+ constructs a time axis using `np.linspace` based on the sampling rate and
588
+ start time from the input file.
589
+
590
+ Examples
591
+ --------
592
+ >>> resampler = FastResamplerFromFile('data.tsv')
593
+ >>> resampler = FastResamplerFromFile('data.tsv', colspec='column1')
594
+ >>> resampler = FastResamplerFromFile('data.tsv', debug=True)
595
+ """
405
596
  (
406
597
  insamplerate,
407
598
  instarttime,
@@ -425,29 +616,65 @@ def FastResamplerFromFile(inputname, colspec=None, debug=False, **kwargs):
425
616
 
426
617
 
427
618
  def doresample(
428
- orig_x,
429
- orig_y,
430
- new_x,
431
- method="cubic",
432
- padlen=0,
433
- padtype="reflect",
434
- antialias=False,
435
- debug=False,
436
- ):
619
+ orig_x: ArrayLike,
620
+ orig_y: ArrayLike,
621
+ new_x: ArrayLike,
622
+ method: str = "cubic",
623
+ padlen: int = 0,
624
+ padtype: str = "reflect",
625
+ antialias: bool = False,
626
+ debug: bool = False,
627
+ ) -> NDArray:
437
628
  """
438
- Resample data from one spacing to another. By default, does not apply any antialiasing filter.
629
+ Resample data from one spacing to another.
630
+
631
+ By default, does not apply any antialiasing filter.
439
632
 
440
633
  Parameters
441
634
  ----------
442
- orig_x
443
- orig_y
444
- new_x
445
- method
446
- padlen
635
+ orig_x : array-like
636
+ Original x-coordinates of the data to be resampled.
637
+ orig_y : array-like
638
+ Original y-values corresponding to `orig_x`.
639
+ new_x : array-like
640
+ New x-coordinates at which to evaluate the resampled data.
641
+ method : str, optional
642
+ Interpolation method to use. Options are:
643
+ - "cubic": cubic spline interpolation (default)
644
+ - "quadratic": quadratic spline interpolation
645
+ - "univariate": univariate spline interpolation using `scipy.interpolate.UnivariateSpline`
646
+ padlen : int, optional
647
+ Number of elements to pad the input data at both ends. Default is 0.
648
+ padtype : str, optional
649
+ Type of padding to use when `padlen > 0`. Default is "reflect".
650
+ Passed to `tide_filt.padvec`.
651
+ antialias : bool, optional
652
+ If True, apply an antialiasing filter before resampling if the original
653
+ sampling frequency is higher than the target frequency. Default is False.
654
+ debug : bool, optional
655
+ If True, print debug information and display a plot of the original and
656
+ padded data. Default is False.
447
657
 
448
658
  Returns
449
659
  -------
660
+ ndarray
661
+ Resampled y-values at coordinates specified by `new_x`. If an invalid
662
+ interpolation method is specified, returns None.
450
663
 
664
+ Notes
665
+ -----
666
+ - The function uses padding to handle edge effects during interpolation.
667
+ - When `antialias=True`, a non-causal filter is applied to reduce aliasing
668
+ artifacts when downsampling.
669
+ - The `tide_filt` module is used for padding and filtering operations.
670
+
671
+ Examples
672
+ --------
673
+ >>> import numpy as np
674
+ >>> x = np.linspace(0, 10, 100)
675
+ >>> y = np.sin(x)
676
+ >>> new_x = np.linspace(0, 10, 200)
677
+ >>> y_resampled = doresample(x, y, new_x, method="cubic")
451
678
  """
452
679
  tstep = orig_x[1] - orig_x[0]
453
680
  if padlen > 0:
@@ -466,11 +693,11 @@ def doresample(
466
693
  print("lens:", len(pad_x), len(pad_y))
467
694
  print(pad_x)
468
695
  print(pad_y)
469
- fig = pl.figure()
696
+ fig = plt.figure()
470
697
  ax = fig.add_subplot(111)
471
698
  ax.set_title("Original and padded vector")
472
- pl.plot(orig_x, orig_y + 1.0, pad_x, pad_y)
473
- pl.show()
699
+ plt.plot(orig_x, orig_y + 1.0, pad_x, pad_y)
700
+ plt.show()
474
701
 
475
702
  # antialias and ringstop filter
476
703
  init_freq = len(pad_x) / (pad_x[-1] - pad_x[0])
@@ -501,31 +728,75 @@ def doresample(
501
728
 
502
729
 
503
730
  def arbresample(
504
- inputdata,
505
- init_freq,
506
- final_freq,
507
- intermed_freq=0.0,
508
- method="univariate",
509
- antialias=True,
510
- decimate=False,
511
- debug=False,
512
- ):
731
+ inputdata: ArrayLike,
732
+ init_freq: float,
733
+ final_freq: float,
734
+ intermed_freq: float = 0.0,
735
+ method: str = "univariate",
736
+ antialias: bool = True,
737
+ decimate: bool = False,
738
+ debug: bool = False,
739
+ ) -> NDArray:
513
740
  """
741
+ Resample input data from an initial frequency to a final frequency using either
742
+ direct resampling or a two-step process with intermediate frequency.
743
+
744
+ This function supports both upsampling and downsampling, with optional anti-aliasing
745
+ and decimation. It can operate in debug mode to print intermediate steps and
746
+ statistics.
514
747
 
515
748
  Parameters
516
749
  ----------
517
- inputdata
518
- init_freq
519
- final_freq
520
- intermed_freq
521
- method
522
- antialias
523
- decimate
524
- debug
750
+ inputdata : ArrayLike
751
+ Input signal or data to be resampled. Should be a 1-D array-like object.
752
+ init_freq : float
753
+ Initial sampling frequency of the input data in Hz.
754
+ final_freq : float
755
+ Target sampling frequency of the output data in Hz.
756
+ intermed_freq : float, optional
757
+ Intermediate sampling frequency used in the two-step resampling process.
758
+ If not specified (default: 0.0), it is automatically set to the maximum of
759
+ 2 * init_freq and 2 * final_freq.
760
+ method : str, optional
761
+ Interpolation method to use for resampling. Default is "univariate".
762
+ Other options may be supported depending on the underlying implementation.
763
+ antialias : bool, optional
764
+ If True (default), apply anti-aliasing filter during downsampling using
765
+ `scipy.signal.decimate`. If False, use simple interpolation for downsampling.
766
+ decimate : bool, optional
767
+ If True, perform upsampling followed by decimation for downsampling.
768
+ If False, use a two-step resampling approach with `dotwostepresample`.
769
+ Default is False.
770
+ debug : bool, optional
771
+ If True, print debug information including number of points before and after
772
+ resampling, and intermediate steps. Default is False.
525
773
 
526
774
  Returns
527
775
  -------
776
+ NDArray
777
+ Resampled data as a NumPy array with length adjusted according to `final_freq`.
528
778
 
779
+ Notes
780
+ -----
781
+ - When `decimate=True`, the function uses integer decimation for efficient downsampling.
782
+ - For downsampling, if `antialias=False`, the function uses linear interpolation
783
+ instead of filtering to reduce computational cost.
784
+ - The `intermed_freq` is automatically calculated when `decimate=True` and
785
+ `final_freq < init_freq`.
786
+
787
+ Examples
788
+ --------
789
+ >>> import numpy as np
790
+ >>> data = np.random.rand(100)
791
+ >>> resampled = arbresample(data, init_freq=100, final_freq=50, decimate=True)
792
+ >>> print(len(resampled))
793
+ 50
794
+
795
+ See Also
796
+ --------
797
+ upsample : Function used for upsampling when `decimate=True`.
798
+ dotwostepresample : Function used for two-step resampling when `decimate=False`.
799
+ scipy.signal.decimate : Anti-aliasing filter used when `antialias=True`.
529
800
  """
530
801
  if debug:
531
802
  print("arbresample - initial points:", len(inputdata))
@@ -597,7 +868,62 @@ def arbresample(
597
868
  return resampled
598
869
 
599
870
 
600
- def upsample(inputdata, Fs_init, Fs_higher, method="univariate", intfac=False, dofilt=True, debug=False):
871
+ def upsample(
872
+ inputdata: ArrayLike,
873
+ Fs_init: float,
874
+ Fs_higher: float,
875
+ method: str = "univariate",
876
+ intfac: bool = False,
877
+ dofilt: bool = True,
878
+ debug: bool = False,
879
+ ) -> NDArray:
880
+ """
881
+ Upsample input data to a higher sampling frequency.
882
+
883
+ This function increases the sampling rate of the input data using interpolation
884
+ and optional filtering. It supports different interpolation methods and allows
885
+ for control over the resampling factor and filtering behavior.
886
+
887
+ Parameters
888
+ ----------
889
+ inputdata : ArrayLike
890
+ Input time series data to be upsampled.
891
+ Fs_init : float
892
+ Initial sampling frequency of the input data (Hz).
893
+ Fs_higher : float
894
+ Target sampling frequency to upsample to (Hz). Must be greater than `Fs_init`.
895
+ method : str, optional
896
+ Interpolation method to use. Default is "univariate". Other options depend
897
+ on the implementation of `doresample`.
898
+ intfac : bool, optional
899
+ If True, use integer resampling factor based on `Fs_higher // Fs_init`.
900
+ If False, compute resampled points based on time duration. Default is False.
901
+ dofilt : bool, optional
902
+ If True, apply a non-causal filter to prevent aliasing. Default is True.
903
+ debug : bool, optional
904
+ If True, print timing information. Default is False.
905
+
906
+ Returns
907
+ -------
908
+ NDArray
909
+ Upsampled time series data with the new sampling frequency.
910
+
911
+ Notes
912
+ -----
913
+ - The function uses linear interpolation by default, but the actual method
914
+ depends on the `doresample` function implementation.
915
+ - If `dofilt` is True, a trapezoidal non-causal filter is applied with a
916
+ stop frequency set to the minimum of 1.1 * Fs_init / 2.0 and Fs_higher / 2.0.
917
+ - The function will terminate if `Fs_higher` is not greater than `Fs_init`.
918
+
919
+ Examples
920
+ --------
921
+ >>> import numpy as np
922
+ >>> data = np.sin(np.linspace(0, 4*np.pi, 100))
923
+ >>> upsampled = upsample(data, Fs_init=10.0, Fs_higher=20.0)
924
+ >>> print(len(upsampled))
925
+ 200
926
+ """
601
927
  starttime = time.time()
602
928
  if Fs_higher <= Fs_init:
603
929
  print("upsample: target frequency must be higher than initial frequency")
@@ -626,29 +952,60 @@ def upsample(inputdata, Fs_init, Fs_higher, method="univariate", intfac=False, d
626
952
 
627
953
 
628
954
  def dotwostepresample(
629
- orig_x,
630
- orig_y,
631
- intermed_freq,
632
- final_freq,
633
- method="univariate",
634
- antialias=True,
635
- debug=False,
636
- ):
955
+ orig_x: ArrayLike,
956
+ orig_y: ArrayLike,
957
+ intermed_freq: float,
958
+ final_freq: float,
959
+ method: str = "univariate",
960
+ antialias: bool = True,
961
+ debug: bool = False,
962
+ ) -> NDArray:
637
963
  """
964
+ Resample a signal from original frequency to final frequency using a two-step process:
965
+ first upsampling to an intermediate frequency, then downsampling to the final frequency.
966
+
967
+ This function performs resampling by first interpolating the input signal to an
968
+ intermediate frequency that is higher than the final desired frequency, followed by
969
+ downsampling to the target frequency. Optional antialiasing filtering is applied
970
+ during the upsampling step.
638
971
 
639
972
  Parameters
640
973
  ----------
641
- orig_x
642
- orig_y
643
- intermed_freq
644
- final_freq
645
- method
646
- debug
974
+ orig_x : array-like
975
+ Original time axis values (must be monotonically increasing).
976
+ orig_y : array-like
977
+ Original signal values corresponding to `orig_x`.
978
+ intermed_freq : float
979
+ Intermediate frequency to which the signal is upsampled.
980
+ Must be greater than `final_freq`.
981
+ final_freq : float
982
+ Target frequency to which the signal is downsampled.
983
+ method : str, optional
984
+ Interpolation method used for resampling. Default is "univariate".
985
+ Should be compatible with the `doresample` function.
986
+ antialias : bool, optional
987
+ If True, apply an antialiasing filter during upsampling. Default is True.
988
+ debug : bool, optional
989
+ If True, print timing and intermediate information. Default is False.
647
990
 
648
991
  Returns
649
992
  -------
650
- resampled_y
993
+ ndarray
994
+ Resampled signal values at the final frequency.
651
995
 
996
+ Notes
997
+ -----
998
+ - The intermediate frequency must be strictly greater than the final frequency.
999
+ - The function uses `doresample` for interpolation and `tide_filt.NoncausalFilter`
1000
+ for antialiasing if enabled.
1001
+ - Timing information is printed when `debug=True`.
1002
+
1003
+ Examples
1004
+ --------
1005
+ >>> import numpy as np
1006
+ >>> x = np.linspace(0, 10, 100)
1007
+ >>> y = np.sin(x)
1008
+ >>> resampled = dotwostepresample(x, y, intermed_freq=50.0, final_freq=10.0)
652
1009
  """
653
1010
  if intermed_freq <= final_freq:
654
1011
  print("intermediate frequency must be higher than final frequency")
@@ -698,20 +1055,56 @@ def dotwostepresample(
698
1055
  return resampled_y
699
1056
 
700
1057
 
701
- def calcsliceoffset(sotype, slicenum, numslices, tr, multiband=1):
1058
+ def calcsliceoffset(
1059
+ sotype: int, slicenum: int, numslices: int, tr: float, multiband: int = 1
1060
+ ) -> float:
702
1061
  """
1062
+ Calculate slice timing offset for slice timing correction.
1063
+
1064
+ This function computes the timing offset (in seconds) for a given slice
1065
+ based on the slice timing correction method specified by `sotype`. The
1066
+ offset is used to align slice acquisition times for functional MRI data
1067
+ preprocessing.
703
1068
 
704
1069
  Parameters
705
1070
  ----------
706
- sotype
707
- slicenum
708
- numslices
709
- tr
710
- multiband
1071
+ sotype : int
1072
+ Slice timing correction method:
1073
+ - 0: None
1074
+ - 1: Regular up (0, 1, 2, 3, ...)
1075
+ - 2: Regular down
1076
+ - 3: Use slice order file (not supported)
1077
+ - 4: Use slice timings file (not supported)
1078
+ - 5: Standard interleaved (0, 2, 4, ..., 1, 3, 5, ...)
1079
+ - 6: Siemens interleaved
1080
+ - 7: Siemens multiband interleaved
1081
+ slicenum : int
1082
+ The index of the slice for which to compute the timing offset.
1083
+ numslices : int
1084
+ Total number of slices in the volume.
1085
+ tr : float
1086
+ Repetition time (TR) in seconds.
1087
+ multiband : int, optional
1088
+ Multiband factor (default is 1). Used only for sotype 7 (Siemens
1089
+ multiband interleaved).
711
1090
 
712
1091
  Returns
713
1092
  -------
1093
+ float
1094
+ Slice timing offset in seconds.
714
1095
 
1096
+ Notes
1097
+ -----
1098
+ For sotypes 3 and 4, the function returns 0.0 as these methods are not
1099
+ implemented.
1100
+
1101
+ Examples
1102
+ --------
1103
+ >>> calcsliceoffset(1, 5, 32, 2.0)
1104
+ 0.3125
1105
+
1106
+ >>> calcsliceoffset(5, 3, 16, 1.5)
1107
+ 0.28125
715
1108
  """
716
1109
  # Slice timing correction
717
1110
  # 0 : None
@@ -802,19 +1195,61 @@ def calcsliceoffset(sotype, slicenum, numslices, tr, multiband=1):
802
1195
 
803
1196
  # NB: a positive value of shifttrs delays the signal, a negative value advances it
804
1197
  # timeshift using fourier phase multiplication
805
- def timeshift(inputtc, shifttrs, padtrs, doplot=False, debug=False):
1198
+ def timeshift(
1199
+ inputtc: ArrayLike, shifttrs: float, padtrs: int, doplot: bool = False, debug: bool = False
1200
+ ) -> Tuple[NDArray, NDArray, NDArray, NDArray]:
806
1201
  """
1202
+ Apply a time shift to a signal using FFT-based modulation and padding.
1203
+
1204
+ This function performs a time shift on an input time course by applying
1205
+ phase modulation in the frequency domain, followed by inverse FFT. It uses
1206
+ padding and reflection to avoid edge discontinuities. The function also
1207
+ returns the corresponding shifted weights and the full padded results.
807
1208
 
808
1209
  Parameters
809
1210
  ----------
810
- inputtc
811
- shifttrs
812
- padtrs
813
- doplot
1211
+ inputtc : array-like
1212
+ Input time course to be shifted. Should be a 1D array of real values.
1213
+ shifttrs : float
1214
+ Time shift in units of samples. Positive values shift the signal forward,
1215
+ negative values shift it backward.
1216
+ padtrs : int
1217
+ Number of samples to pad the input signal on each side before shifting.
1218
+ This helps reduce edge effects.
1219
+ doplot : bool, optional
1220
+ If True, plots the original and shifted signals. Default is False.
1221
+ debug : bool, optional
1222
+ If True, prints debug information during execution. Default is False.
814
1223
 
815
1224
  Returns
816
1225
  -------
1226
+ tuple of ndarray
1227
+ A tuple containing:
1228
+ - shifted_y : ndarray
1229
+ The time-shifted signal, cropped to the original length.
1230
+ - shifted_weights : ndarray
1231
+ The corresponding shifted weights, cropped to the original length.
1232
+ - shifted_y_full : ndarray
1233
+ The full time-shifted signal including padding.
1234
+ - shifted_weights_full : ndarray
1235
+ The full shifted weights including padding.
817
1236
 
1237
+ Notes
1238
+ -----
1239
+ The function uses reflection padding to minimize edge artifacts. The phase
1240
+ modulation is applied in the frequency domain using FFT and inverse FFT.
1241
+ The shift is implemented as a complex exponential modulation.
1242
+
1243
+ Examples
1244
+ --------
1245
+ >>> import numpy as np
1246
+ >>> from scipy import fftpack
1247
+ >>> input_signal = np.sin(np.linspace(0, 4*np.pi, 100))
1248
+ >>> shifted_sig, weights, full_shifted, full_weights = timeshift(
1249
+ ... input_signal, shifttrs=5.0, padtrs=10, doplot=False
1250
+ ... )
1251
+ >>> print(shifted_sig.shape)
1252
+ (100,)
818
1253
  """
819
1254
  # set up useful parameters
820
1255
  thelen = np.shape(inputtc)[0]
@@ -861,17 +1296,17 @@ def timeshift(inputtc, shifttrs, padtrs, doplot=False, debug=False):
861
1296
  print("thelen:", thelen)
862
1297
  print("thepaddedlen:", thepaddedlen)
863
1298
 
864
- fig = pl.figure()
1299
+ fig = plt.figure()
865
1300
  ax = fig.add_subplot(111)
866
1301
  ax.set_title("Initial vector")
867
- pl.plot(xvec, preshifted_y)
1302
+ plt.plot(xvec, preshifted_y)
868
1303
 
869
- fig = pl.figure()
1304
+ fig = plt.figure()
870
1305
  ax = fig.add_subplot(111)
871
1306
  ax.set_title("Initial and shifted vector")
872
- pl.plot(xvec, preshifted_y, xvec, shifted_y)
1307
+ plt.plot(xvec, preshifted_y, xvec, shifted_y)
873
1308
 
874
- pl.show()
1309
+ plt.show()
875
1310
 
876
1311
  return [
877
1312
  shifted_y[padtrs : padtrs + thelen],
@@ -881,16 +1316,67 @@ def timeshift(inputtc, shifttrs, padtrs, doplot=False, debug=False):
881
1316
  ]
882
1317
 
883
1318
 
884
- def timewarp(orig_x, orig_y, timeoffset, demean=True, method="univariate", debug=False):
1319
+ def timewarp(
1320
+ orig_x: ArrayLike,
1321
+ orig_y: ArrayLike,
1322
+ timeoffset: ArrayLike,
1323
+ demean: bool = True,
1324
+ method: str = "univariate",
1325
+ debug: bool = False,
1326
+ ) -> NDArray:
1327
+ """
1328
+ Apply time warping to align time series data based on time offsets.
1329
+
1330
+ This function performs time warping by resampling input data according to
1331
+ provided time offsets. It can optionally remove the mean of the time offsets
1332
+ before resampling to center the data around zero.
1333
+
1334
+ Parameters
1335
+ ----------
1336
+ orig_x : ArrayLike
1337
+ Original time axis values (x-coordinates) for the data to be warped.
1338
+ orig_y : ArrayLike
1339
+ Original signal values (y-coordinates) corresponding to orig_x.
1340
+ timeoffset : ArrayLike
1341
+ Time offsets to be applied to each point in the time axis. Positive values
1342
+ shift data forward in time, negative values shift backward.
1343
+ demean : bool, optional
1344
+ If True, remove the mean of timeoffset before resampling. Default is True.
1345
+ method : str, optional
1346
+ Resampling method to use. Options are 'univariate' or other methods
1347
+ supported by the underlying doresample function. Default is 'univariate'.
1348
+ debug : bool, optional
1349
+ If True, print debugging information about the warping process.
1350
+ Default is False.
1351
+
1352
+ Returns
1353
+ -------
1354
+ NDArray
1355
+ Warped time series data after applying the time offsets and resampling.
1356
+
1357
+ Notes
1358
+ -----
1359
+ The function calculates the maximum deviation in samples and uses half the
1360
+ length of the input data (or 30 seconds worth of samples, whichever is smaller)
1361
+ as padding length for the resampling operation.
1362
+
1363
+ Examples
1364
+ --------
1365
+ >>> import numpy as np
1366
+ >>> x = np.linspace(0, 10, 100)
1367
+ >>> y = np.sin(x)
1368
+ >>> offsets = np.random.normal(0, 0.1, 100)
1369
+ >>> warped_y = timewarp(x, y, offsets)
1370
+ """
885
1371
  if demean:
886
1372
  demeanedoffset = timeoffset - np.mean(timeoffset)
887
1373
  if debug:
888
1374
  print("mean delay of ", np.mean(timeoffset), "seconds removed prior to resampling")
889
1375
  else:
890
1376
  demeanedoffset = timeoffset
891
- sampletime = orig_x[1] - orig_x[0]
892
- maxdevs = (np.min(demeanedoffset), np.max(demeanedoffset))
893
- maxsamps = maxdevs / sampletime
1377
+ sampletime = float(orig_x[1] - orig_x[0])
1378
+ maxdevs = (float(np.min(demeanedoffset)), float(np.max(demeanedoffset)))
1379
+ maxsamps = (maxdevs[0] / sampletime, maxdevs[1] / sampletime)
894
1380
  padlen = np.min([int(len(orig_x) // 2), int(30.0 / sampletime)])
895
1381
  if debug:
896
1382
  print("maximum deviation in samples:", maxsamps)