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.
- rapidtide/Colortables.py +492 -27
- rapidtide/OrthoImageItem.py +1049 -46
- rapidtide/RapidtideDataset.py +1533 -86
- rapidtide/_version.py +3 -3
- rapidtide/calccoherence.py +196 -29
- rapidtide/calcnullsimfunc.py +188 -40
- rapidtide/calcsimfunc.py +242 -42
- rapidtide/correlate.py +1203 -383
- rapidtide/data/examples/src/testLD +56 -0
- rapidtide/data/examples/src/testalign +1 -1
- rapidtide/data/examples/src/testdelayvar +0 -1
- rapidtide/data/examples/src/testfmri +53 -3
- rapidtide/data/examples/src/testglmfilt +5 -5
- rapidtide/data/examples/src/testhappy +29 -7
- rapidtide/data/examples/src/testppgproc +17 -0
- rapidtide/data/examples/src/testrolloff +11 -0
- rapidtide/data/models/model_cnn_pytorch/best_model.pth +0 -0
- rapidtide/data/models/model_cnn_pytorch/loss.png +0 -0
- rapidtide/data/models/model_cnn_pytorch/loss.txt +1 -0
- rapidtide/data/models/model_cnn_pytorch/model.pth +0 -0
- rapidtide/data/models/model_cnn_pytorch/model_meta.json +68 -0
- rapidtide/decorators.py +91 -0
- rapidtide/dlfilter.py +2226 -110
- rapidtide/dlfiltertorch.py +4842 -0
- rapidtide/externaltools.py +327 -12
- rapidtide/fMRIData_class.py +79 -40
- rapidtide/filter.py +1899 -810
- rapidtide/fit.py +2011 -581
- rapidtide/genericmultiproc.py +93 -18
- rapidtide/happy_supportfuncs.py +2047 -172
- rapidtide/helper_classes.py +584 -43
- rapidtide/io.py +2370 -372
- rapidtide/linfitfiltpass.py +346 -99
- rapidtide/makelaggedtcs.py +210 -24
- rapidtide/maskutil.py +448 -62
- rapidtide/miscmath.py +827 -121
- rapidtide/multiproc.py +210 -22
- rapidtide/patchmatch.py +242 -42
- rapidtide/peakeval.py +31 -31
- rapidtide/ppgproc.py +2203 -0
- rapidtide/qualitycheck.py +352 -39
- rapidtide/refinedelay.py +431 -57
- rapidtide/refineregressor.py +494 -189
- rapidtide/resample.py +671 -185
- rapidtide/scripts/applyppgproc.py +28 -0
- rapidtide/scripts/showxcorr_legacy.py +7 -7
- rapidtide/scripts/stupidramtricks.py +15 -17
- rapidtide/simFuncClasses.py +1052 -77
- rapidtide/simfuncfit.py +269 -69
- rapidtide/stats.py +540 -238
- rapidtide/tests/happycomp +9 -0
- rapidtide/tests/test_cleanregressor.py +1 -2
- rapidtide/tests/test_dlfiltertorch.py +627 -0
- rapidtide/tests/test_findmaxlag.py +24 -8
- rapidtide/tests/test_fullrunhappy_v1.py +0 -2
- rapidtide/tests/test_fullrunhappy_v2.py +0 -2
- rapidtide/tests/test_fullrunhappy_v3.py +11 -4
- rapidtide/tests/test_fullrunhappy_v4.py +10 -2
- rapidtide/tests/test_fullrunrapidtide_v7.py +1 -1
- rapidtide/tests/test_getparsers.py +11 -3
- rapidtide/tests/test_refinedelay.py +0 -1
- rapidtide/tests/test_simroundtrip.py +16 -8
- rapidtide/tests/test_stcorrelate.py +3 -1
- rapidtide/tests/utils.py +9 -8
- rapidtide/tidepoolTemplate.py +142 -38
- rapidtide/tidepoolTemplate_alt.py +165 -44
- rapidtide/tidepoolTemplate_big.py +189 -52
- rapidtide/util.py +1217 -118
- rapidtide/voxelData.py +684 -37
- rapidtide/wiener.py +136 -23
- rapidtide/wiener2.py +113 -7
- rapidtide/workflows/adjustoffset.py +105 -3
- rapidtide/workflows/aligntcs.py +85 -2
- rapidtide/workflows/applydlfilter.py +87 -10
- rapidtide/workflows/applyppgproc.py +540 -0
- rapidtide/workflows/atlasaverage.py +210 -47
- rapidtide/workflows/atlastool.py +100 -3
- rapidtide/workflows/calcSimFuncMap.py +288 -69
- rapidtide/workflows/calctexticc.py +201 -9
- rapidtide/workflows/ccorrica.py +101 -6
- rapidtide/workflows/cleanregressor.py +165 -31
- rapidtide/workflows/delayvar.py +171 -23
- rapidtide/workflows/diffrois.py +81 -3
- rapidtide/workflows/endtidalproc.py +144 -4
- rapidtide/workflows/fdica.py +195 -15
- rapidtide/workflows/filtnifti.py +70 -3
- rapidtide/workflows/filttc.py +74 -3
- rapidtide/workflows/fitSimFuncMap.py +202 -51
- rapidtide/workflows/fixtr.py +73 -3
- rapidtide/workflows/gmscalc.py +113 -3
- rapidtide/workflows/happy.py +801 -199
- rapidtide/workflows/happy2std.py +144 -12
- rapidtide/workflows/happy_parser.py +163 -23
- rapidtide/workflows/histnifti.py +118 -2
- rapidtide/workflows/histtc.py +84 -3
- rapidtide/workflows/linfitfilt.py +117 -4
- rapidtide/workflows/localflow.py +328 -28
- rapidtide/workflows/mergequality.py +79 -3
- rapidtide/workflows/niftidecomp.py +322 -18
- rapidtide/workflows/niftistats.py +174 -4
- rapidtide/workflows/pairproc.py +98 -4
- rapidtide/workflows/pairwisemergenifti.py +85 -2
- rapidtide/workflows/parser_funcs.py +1421 -40
- rapidtide/workflows/physiofreq.py +137 -11
- rapidtide/workflows/pixelcomp.py +207 -5
- rapidtide/workflows/plethquality.py +103 -21
- rapidtide/workflows/polyfitim.py +151 -11
- rapidtide/workflows/proj2flow.py +75 -2
- rapidtide/workflows/rankimage.py +111 -4
- rapidtide/workflows/rapidtide.py +368 -76
- rapidtide/workflows/rapidtide2std.py +98 -2
- rapidtide/workflows/rapidtide_parser.py +109 -9
- rapidtide/workflows/refineDelayMap.py +144 -33
- rapidtide/workflows/refineRegressor.py +675 -96
- rapidtide/workflows/regressfrommaps.py +161 -37
- rapidtide/workflows/resamplenifti.py +85 -3
- rapidtide/workflows/resampletc.py +91 -3
- rapidtide/workflows/retrolagtcs.py +99 -9
- rapidtide/workflows/retroregress.py +176 -26
- rapidtide/workflows/roisummarize.py +174 -5
- rapidtide/workflows/runqualitycheck.py +71 -3
- rapidtide/workflows/showarbcorr.py +149 -6
- rapidtide/workflows/showhist.py +86 -2
- rapidtide/workflows/showstxcorr.py +160 -3
- rapidtide/workflows/showtc.py +159 -3
- rapidtide/workflows/showxcorrx.py +190 -10
- rapidtide/workflows/showxy.py +185 -15
- rapidtide/workflows/simdata.py +264 -38
- rapidtide/workflows/spatialfit.py +77 -2
- rapidtide/workflows/spatialmi.py +250 -27
- rapidtide/workflows/spectrogram.py +305 -32
- rapidtide/workflows/synthASL.py +154 -3
- rapidtide/workflows/tcfrom2col.py +76 -2
- rapidtide/workflows/tcfrom3col.py +74 -2
- rapidtide/workflows/tidepool.py +2971 -130
- rapidtide/workflows/utils.py +19 -14
- rapidtide/workflows/utils_doc.py +293 -0
- rapidtide/workflows/variabilityizer.py +116 -3
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/METADATA +10 -8
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/RECORD +144 -128
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/entry_points.txt +1 -0
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/WHEEL +0 -0
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/licenses/LICENSE +0 -0
- {rapidtide-3.0.11.dist-info → rapidtide-3.1.1.dist-info}/top_level.txt +0 -0
|
@@ -18,19 +18,54 @@
|
|
|
18
18
|
#
|
|
19
19
|
import argparse
|
|
20
20
|
import sys
|
|
21
|
+
from typing import Any, Tuple, Union
|
|
21
22
|
|
|
22
23
|
import matplotlib.pyplot as plt
|
|
23
24
|
import numpy as np
|
|
24
25
|
from mpl_toolkits.axes_grid1 import make_axes_locatable
|
|
25
|
-
from
|
|
26
|
+
from numpy.typing import NDArray
|
|
27
|
+
from scipy.signal import ShortTimeFFT, check_NOLA, stft
|
|
26
28
|
|
|
27
29
|
import rapidtide.io as tide_io
|
|
28
30
|
from rapidtide.workflows.parser_funcs import is_float, is_int, is_valid_file
|
|
29
31
|
|
|
32
|
+
NPFloat2DArray = NDArray[Union[np.float32, np.float64]]
|
|
30
33
|
|
|
31
|
-
|
|
34
|
+
|
|
35
|
+
def _get_parser() -> Any:
|
|
32
36
|
"""
|
|
33
|
-
Argument parser for spectrogram
|
|
37
|
+
Argument parser for spectrogram.
|
|
38
|
+
|
|
39
|
+
This function creates and configures an argument parser for the spectrogram
|
|
40
|
+
command-line tool that computes and displays spectrograms from text files
|
|
41
|
+
containing timecourse data.
|
|
42
|
+
|
|
43
|
+
Returns
|
|
44
|
+
-------
|
|
45
|
+
argparse.ArgumentParser
|
|
46
|
+
Configured argument parser object with all required and optional
|
|
47
|
+
arguments for spectrogram computation.
|
|
48
|
+
|
|
49
|
+
Notes
|
|
50
|
+
-----
|
|
51
|
+
The parser expects a text file containing one data point per line and a
|
|
52
|
+
specified sample rate. The spectrogram is computed using the Short-Time
|
|
53
|
+
Fourier Transform (STFT) with configurable segment length.
|
|
54
|
+
|
|
55
|
+
Examples
|
|
56
|
+
--------
|
|
57
|
+
>>> parser = _get_parser()
|
|
58
|
+
>>> args = parser.parse_args(['input.txt', '44100'])
|
|
59
|
+
>>> print(args.textfilename)
|
|
60
|
+
'input.txt'
|
|
61
|
+
>>> print(args.samplerate)
|
|
62
|
+
44100
|
|
63
|
+
|
|
64
|
+
See Also
|
|
65
|
+
--------
|
|
66
|
+
is_valid_file : Validates input file existence and readability
|
|
67
|
+
is_float : Validates float conversion
|
|
68
|
+
is_int : Validates integer conversion
|
|
34
69
|
"""
|
|
35
70
|
parser = argparse.ArgumentParser(
|
|
36
71
|
prog="spectrogram",
|
|
@@ -38,15 +73,14 @@ def _get_parser():
|
|
|
38
73
|
allow_abbrev=False,
|
|
39
74
|
)
|
|
40
75
|
|
|
41
|
-
# Required
|
|
76
|
+
# Required argument
|
|
42
77
|
parser.add_argument(
|
|
43
|
-
"
|
|
78
|
+
"inputfile",
|
|
44
79
|
type=lambda x: is_valid_file(parser, x),
|
|
45
80
|
help="The input data file (text file containing a timecourse, one point per line).",
|
|
46
81
|
)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
)
|
|
82
|
+
|
|
83
|
+
# Optional arguments
|
|
50
84
|
parser.add_argument(
|
|
51
85
|
"--nperseg",
|
|
52
86
|
dest="nperseg",
|
|
@@ -55,6 +89,15 @@ def _get_parser():
|
|
|
55
89
|
help=("The number of points to include in each spectrogram (default is 128)."),
|
|
56
90
|
default=128,
|
|
57
91
|
)
|
|
92
|
+
parser.add_argument(
|
|
93
|
+
"--samplerate",
|
|
94
|
+
dest="samplerate",
|
|
95
|
+
metavar="RATE",
|
|
96
|
+
action="store",
|
|
97
|
+
type=lambda x: is_float(parser, x),
|
|
98
|
+
help="Sample rate in Hz.",
|
|
99
|
+
default=None,
|
|
100
|
+
)
|
|
58
101
|
parser.add_argument(
|
|
59
102
|
"--debug",
|
|
60
103
|
dest="debug",
|
|
@@ -66,32 +109,138 @@ def _get_parser():
|
|
|
66
109
|
return parser
|
|
67
110
|
|
|
68
111
|
|
|
69
|
-
def calcspecgram(
|
|
70
|
-
|
|
112
|
+
def calcspecgram(
|
|
113
|
+
x: NDArray[np.floating[Any]],
|
|
114
|
+
time: NDArray[np.floating[Any]],
|
|
115
|
+
nperseg: int = 32,
|
|
116
|
+
windowtype: str = "hann",
|
|
117
|
+
) -> Tuple[NDArray, NDArray, NDArray, bool]:
|
|
118
|
+
"""
|
|
119
|
+
Make and plot a log-scaled spectrogram.
|
|
120
|
+
|
|
121
|
+
This function computes a spectrogram using the Short-Time Fourier Transform (STFT)
|
|
122
|
+
with configurable window parameters and returns frequency, time, and STFT data
|
|
123
|
+
along with a check for invertibility.
|
|
124
|
+
|
|
125
|
+
Parameters
|
|
126
|
+
----------
|
|
127
|
+
x : NDArray[np.floating[Any]]
|
|
128
|
+
Input signal data to compute the spectrogram for.
|
|
129
|
+
time : NDArray[np.floating[Any]]
|
|
130
|
+
Time vector corresponding to the input signal. Used to calculate sampling
|
|
131
|
+
frequency from the time differences.
|
|
132
|
+
nperseg : int, optional
|
|
133
|
+
Length of each segment for the STFT, by default 32.
|
|
134
|
+
windowtype : str, optional
|
|
135
|
+
Type of window to use for the STFT, by default "hann".
|
|
136
|
+
|
|
137
|
+
Returns
|
|
138
|
+
-------
|
|
139
|
+
freq : ndarray
|
|
140
|
+
Array of frequencies corresponding to the spectrogram rows.
|
|
141
|
+
segtimes : ndarray
|
|
142
|
+
Array of time points corresponding to the spectrogram columns.
|
|
143
|
+
thestft : ndarray
|
|
144
|
+
Short-Time Fourier Transform of the input signal.
|
|
145
|
+
isinvertable : bool
|
|
146
|
+
Boolean flag indicating whether the window satisfies the Non-Overlap
|
|
147
|
+
Additivity of Overlapped Windows (NOLA) constraint for invertibility.
|
|
148
|
+
|
|
149
|
+
Notes
|
|
150
|
+
-----
|
|
151
|
+
The function calculates the sampling frequency from the time vector and uses
|
|
152
|
+
the ShortTimeFFT library to compute the STFT. The window overlap is set to
|
|
153
|
+
ensure maximum overlap (nperseg - 1) for optimal spectrogram resolution.
|
|
154
|
+
|
|
155
|
+
Examples
|
|
156
|
+
--------
|
|
157
|
+
>>> import numpy as np
|
|
158
|
+
>>> from scipy.signal import chirp
|
|
159
|
+
>>> t = np.linspace(0, 1, 1000)
|
|
160
|
+
>>> x = chirp(t, f0=1, f1=10, t1=1, method='linear')
|
|
161
|
+
>>> freq, times, stft, invertible = calcspecgram(x, t)
|
|
162
|
+
>>> print(f"Frequency range: {freq[0]:.2f} to {freq[-1]:.2f} Hz")
|
|
163
|
+
>>> print(f"Time range: {times[0]:.2f} to {times[-1]:.2f} seconds")
|
|
164
|
+
"""
|
|
71
165
|
dt = np.diff(time)[0] # In days...
|
|
72
166
|
fs = 1.0 / dt
|
|
73
|
-
nfft = nperseg
|
|
74
167
|
noverlap = nperseg - 1
|
|
75
168
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
fs
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
boundary="zeros",
|
|
86
|
-
padded=True,
|
|
87
|
-
axis=-1,
|
|
169
|
+
SFT = ShortTimeFFT.from_window(
|
|
170
|
+
windowtype,
|
|
171
|
+
fs,
|
|
172
|
+
nperseg,
|
|
173
|
+
noverlap,
|
|
174
|
+
mfft=nperseg,
|
|
175
|
+
fft_mode="onesided",
|
|
176
|
+
scale_to="magnitude",
|
|
177
|
+
phase_shift=None,
|
|
88
178
|
)
|
|
179
|
+
freq = SFT.f
|
|
180
|
+
thestft = SFT.stft(x, p0=0, p1=(len(x) - noverlap) // SFT.hop, k_offset=nperseg // 2)
|
|
181
|
+
segtimes = SFT.t(len(x), p0=0, p1=(len(x) - noverlap) // SFT.hop, k_offset=nperseg // 2)
|
|
89
182
|
|
|
90
183
|
isinvertable = check_NOLA(windowtype, nperseg, noverlap, tol=1e-10)
|
|
91
184
|
return freq, segtimes, thestft, isinvertable
|
|
92
185
|
|
|
93
186
|
|
|
94
|
-
def showspecgram(
|
|
187
|
+
def showspecgram(
|
|
188
|
+
thestft: Any, time: Any, freq: Any, ax: Any, fig: Any, mode: str = "mag"
|
|
189
|
+
) -> Tuple[Any, Any]:
|
|
190
|
+
"""
|
|
191
|
+
Display a spectrogram plot based on the provided STFT data.
|
|
192
|
+
|
|
193
|
+
This function visualizes the Short-Time Fourier Transform (STFT) of a signal
|
|
194
|
+
in the form of a spectrogram. It supports multiple display modes including
|
|
195
|
+
magnitude, phase, real, and imaginary components. The function also handles
|
|
196
|
+
logarithmic scaling for amplitude values and includes a colorbar with appropriate
|
|
197
|
+
labeling.
|
|
198
|
+
|
|
199
|
+
Parameters
|
|
200
|
+
----------
|
|
201
|
+
thestft : Any
|
|
202
|
+
The Short-Time Fourier Transform (STFT) of the signal. Typically a 2D array
|
|
203
|
+
where rows correspond to frequency bins and columns to time frames.
|
|
204
|
+
time : Any
|
|
205
|
+
Time vector corresponding to the STFT columns. Used for x-axis labeling.
|
|
206
|
+
freq : Any
|
|
207
|
+
Frequency vector corresponding to the STFT rows. Used for y-axis labeling.
|
|
208
|
+
ax : Any
|
|
209
|
+
Matplotlib axis object on which the spectrogram will be plotted.
|
|
210
|
+
fig : Any
|
|
211
|
+
Matplotlib figure object used to create the colorbar.
|
|
212
|
+
mode : str, optional
|
|
213
|
+
The mode of visualization. Options are:
|
|
214
|
+
- "mag": Magnitude of the STFT (default)
|
|
215
|
+
- "phase": Phase of the STFT
|
|
216
|
+
- "real": Real part of the STFT
|
|
217
|
+
- "imag": Imaginary part of the STFT
|
|
218
|
+
|
|
219
|
+
Returns
|
|
220
|
+
-------
|
|
221
|
+
Tuple[Any, Any]
|
|
222
|
+
A tuple containing:
|
|
223
|
+
- im: The image object returned by `pcolormesh`
|
|
224
|
+
- cbar: The colorbar object added to the plot
|
|
225
|
+
|
|
226
|
+
Notes
|
|
227
|
+
-----
|
|
228
|
+
- For magnitude mode, the data is log-scaled using `log10`.
|
|
229
|
+
- For phase mode, the data is scaled between -π and π.
|
|
230
|
+
- The y-axis is set to range from `freq[1]` to `freq.max()` to avoid potential
|
|
231
|
+
issues with zero frequency bins.
|
|
232
|
+
- X-axis tick labels are hidden for cleaner visualization.
|
|
233
|
+
- If an invalid `mode` is provided, the function will print an error and exit.
|
|
234
|
+
|
|
235
|
+
Examples
|
|
236
|
+
--------
|
|
237
|
+
>>> import numpy as np
|
|
238
|
+
>>> import matplotlib.pyplot as plt
|
|
239
|
+
>>> # Assuming `sft` is your STFT data, `t` is time, `f` is frequency
|
|
240
|
+
>>> fig, ax = plt.subplots()
|
|
241
|
+
>>> im, cbar = showspecgram(sft, t, f, ax, fig, mode="mag")
|
|
242
|
+
>>> plt.show()
|
|
243
|
+
"""
|
|
95
244
|
# Log scaling for amplitude values
|
|
96
245
|
if mode == "mag":
|
|
97
246
|
spec_img = np.log10(np.abs(thestft))
|
|
@@ -145,13 +294,84 @@ def showspecgram(thestft, time, freq, ax, fig, mode="mag"):
|
|
|
145
294
|
return im, cbar
|
|
146
295
|
|
|
147
296
|
|
|
148
|
-
def make_legend_axes(ax):
|
|
297
|
+
def make_legend_axes(ax: Any) -> object:
|
|
298
|
+
"""
|
|
299
|
+
Create a new axes for legend placement next to the given axes.
|
|
300
|
+
|
|
301
|
+
This function creates a new axes object positioned to the right of the
|
|
302
|
+
provided axes, which can be used for placing legends. The new axes is
|
|
303
|
+
created using matplotlib's make_axes_locatable utility.
|
|
304
|
+
|
|
305
|
+
Parameters
|
|
306
|
+
----------
|
|
307
|
+
ax : matplotlib.axes.Axes
|
|
308
|
+
The original axes object to which the legend axes will be appended.
|
|
309
|
+
|
|
310
|
+
Returns
|
|
311
|
+
-------
|
|
312
|
+
matplotlib.axes.Axes
|
|
313
|
+
The newly created axes object that can be used for legend placement.
|
|
314
|
+
|
|
315
|
+
Notes
|
|
316
|
+
-----
|
|
317
|
+
The legend axes is positioned to the right of the original axes with:
|
|
318
|
+
- Size: 0.4 inches width
|
|
319
|
+
- Padding: 0.2 inches from the original axes
|
|
320
|
+
|
|
321
|
+
Examples
|
|
322
|
+
--------
|
|
323
|
+
>>> import matplotlib.pyplot as plt
|
|
324
|
+
>>> fig, ax = plt.subplots()
|
|
325
|
+
>>> ax.plot([1, 2, 3], [1, 4, 9])
|
|
326
|
+
>>> legend_ax = make_legend_axes(ax)
|
|
327
|
+
>>> ax.legend(['data'], bbox_to_anchor=(1.05, 1), loc='upper left')
|
|
328
|
+
>>> plt.show()
|
|
329
|
+
"""
|
|
149
330
|
divider = make_axes_locatable(ax)
|
|
150
331
|
legend_ax = divider.append_axes("right", 0.4, pad=0.2)
|
|
151
332
|
return legend_ax
|
|
152
333
|
|
|
153
334
|
|
|
154
|
-
def ndplot(x, time, thelabel, nperseg=32):
|
|
335
|
+
def ndplot(x: Any, time: Any, thelabel: Any, nperseg: int = 32) -> None:
|
|
336
|
+
"""
|
|
337
|
+
Plot spectrogram magnitude, phase, and time-domain signal.
|
|
338
|
+
|
|
339
|
+
This function computes and displays a spectrogram of the input signal `x` using
|
|
340
|
+
the Short-Time Fourier Transform (STFT). It shows the magnitude and phase of
|
|
341
|
+
the spectrogram in separate subplots, and overlays the original time-domain
|
|
342
|
+
signal on a third subplot.
|
|
343
|
+
|
|
344
|
+
Parameters
|
|
345
|
+
----------
|
|
346
|
+
x : array-like
|
|
347
|
+
Input signal to be analyzed.
|
|
348
|
+
time : array-like
|
|
349
|
+
Time vector corresponding to the signal `x`.
|
|
350
|
+
thelabel : str
|
|
351
|
+
Label used for plotting titles.
|
|
352
|
+
nperseg : int, optional
|
|
353
|
+
Length of each segment for the STFT. Default is 32.
|
|
354
|
+
|
|
355
|
+
Returns
|
|
356
|
+
-------
|
|
357
|
+
None
|
|
358
|
+
This function does not return any value. It displays the plot directly.
|
|
359
|
+
|
|
360
|
+
Notes
|
|
361
|
+
-----
|
|
362
|
+
- The function uses `calcspecgram` to compute the STFT and checks if the
|
|
363
|
+
spectrogram is invertible.
|
|
364
|
+
- The magnitude and phase are plotted in the first two subplots.
|
|
365
|
+
- The time-domain signal is overlaid in the third subplot.
|
|
366
|
+
- The function relies on `showspecgram` for plotting the spectrograms.
|
|
367
|
+
|
|
368
|
+
Examples
|
|
369
|
+
--------
|
|
370
|
+
>>> import numpy as np
|
|
371
|
+
>>> t = np.linspace(0, 1, 1000)
|
|
372
|
+
>>> x = np.sin(2 * np.pi * 50 * t)
|
|
373
|
+
>>> ndplot(x, t, "Example Signal")
|
|
374
|
+
"""
|
|
155
375
|
print("arrived in ndplot")
|
|
156
376
|
fig = plt.figure()
|
|
157
377
|
|
|
@@ -196,7 +416,45 @@ def ndplot(x, time, thelabel, nperseg=32):
|
|
|
196
416
|
# plt.subplots_adjust(hspace=0.0)
|
|
197
417
|
|
|
198
418
|
|
|
199
|
-
def spectrogram(args):
|
|
419
|
+
def spectrogram(args: Any) -> None:
|
|
420
|
+
"""
|
|
421
|
+
Compute and display spectrogram of time series data from text file.
|
|
422
|
+
|
|
423
|
+
This function reads time series data from a text file, computes its spectrogram
|
|
424
|
+
using Welch's method, and displays the result. The spectrogram shows how
|
|
425
|
+
the frequency content of the signal changes over time.
|
|
426
|
+
|
|
427
|
+
Parameters
|
|
428
|
+
----------
|
|
429
|
+
args : Any
|
|
430
|
+
Command line arguments containing:
|
|
431
|
+
- textfilename : str
|
|
432
|
+
Path to the text file containing time series data
|
|
433
|
+
- samplerate : float
|
|
434
|
+
Sampling rate of the tidal data in Hz
|
|
435
|
+
- nperseg : int, optional
|
|
436
|
+
Length of each segment for FFT (default: 256)
|
|
437
|
+
- debug : bool, optional
|
|
438
|
+
Enable debug output (default: False)
|
|
439
|
+
|
|
440
|
+
Returns
|
|
441
|
+
-------
|
|
442
|
+
None
|
|
443
|
+
This function displays the spectrogram plot and does not return any value.
|
|
444
|
+
|
|
445
|
+
Notes
|
|
446
|
+
-----
|
|
447
|
+
The function uses Welch's method for spectral estimation, which divides the
|
|
448
|
+
signal into overlapping segments and averages their periodograms. The time
|
|
449
|
+
axis is automatically calculated based on the sampling rate and data length.
|
|
450
|
+
|
|
451
|
+
Examples
|
|
452
|
+
--------
|
|
453
|
+
>>> import argparse
|
|
454
|
+
>>> args = argparse.Namespace(textfilename='tidal_data.txt',
|
|
455
|
+
... samplerate=10.0, nperseg=512, debug=False)
|
|
456
|
+
>>> spectrogram(args)
|
|
457
|
+
"""
|
|
200
458
|
# get the command line parameters
|
|
201
459
|
try:
|
|
202
460
|
args = _get_parser().parse_args()
|
|
@@ -206,12 +464,27 @@ def spectrogram(args):
|
|
|
206
464
|
if args.debug:
|
|
207
465
|
print(args)
|
|
208
466
|
|
|
209
|
-
#
|
|
210
|
-
|
|
467
|
+
# read in data
|
|
468
|
+
(
|
|
469
|
+
samplerate,
|
|
470
|
+
starttime,
|
|
471
|
+
colnames,
|
|
472
|
+
yvec,
|
|
473
|
+
compressed,
|
|
474
|
+
filetype,
|
|
475
|
+
) = tide_io.readvectorsfromtextfile(args.inputfile, onecol=True)
|
|
476
|
+
|
|
477
|
+
# get the sample rate squared away
|
|
478
|
+
if args.samplerate is not None:
|
|
479
|
+
samplerate = args.samplerate
|
|
480
|
+
else:
|
|
481
|
+
if samplerate is None:
|
|
482
|
+
print("Sample rate must be specified in input file or with --samplerate")
|
|
483
|
+
sys.exit()
|
|
484
|
+
timestep = 1.0 / samplerate
|
|
211
485
|
|
|
212
|
-
|
|
213
|
-
xvec = np.arange(0.0, len(yvec), 1.0) * timestep
|
|
486
|
+
xvec = np.arange(0.0, len(yvec), 1.0) * timestep + starttime
|
|
214
487
|
|
|
215
|
-
thelabel = args.
|
|
488
|
+
thelabel = args.inputfile
|
|
216
489
|
ndplot(yvec, xvec, thelabel, nperseg=args.nperseg)
|
|
217
490
|
plt.show()
|
rapidtide/workflows/synthASL.py
CHANGED
|
@@ -17,14 +17,42 @@
|
|
|
17
17
|
#
|
|
18
18
|
#
|
|
19
19
|
import argparse
|
|
20
|
+
from argparse import Namespace
|
|
21
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
|
20
22
|
|
|
21
23
|
import numpy as np
|
|
24
|
+
from numpy.typing import NDArray
|
|
22
25
|
|
|
23
26
|
import rapidtide.io as tide_io
|
|
24
27
|
from rapidtide.RapidtideDataset import RapidtideDataset
|
|
25
28
|
|
|
26
29
|
|
|
27
|
-
def _get_parser():
|
|
30
|
+
def _get_parser() -> Any:
|
|
31
|
+
"""
|
|
32
|
+
Get the argument parser for the synthASL command-line tool.
|
|
33
|
+
|
|
34
|
+
This function constructs and returns an `argparse.ArgumentParser` object configured
|
|
35
|
+
with the necessary arguments for running the synthASL tool, which uses rapidtide
|
|
36
|
+
output to predict ASL (Arterial Spin Labeling) images.
|
|
37
|
+
|
|
38
|
+
Returns
|
|
39
|
+
-------
|
|
40
|
+
argparse.ArgumentParser
|
|
41
|
+
Configured argument parser with required and optional arguments for synthASL.
|
|
42
|
+
|
|
43
|
+
Notes
|
|
44
|
+
-----
|
|
45
|
+
The parser includes both required positional arguments and several optional
|
|
46
|
+
arguments that control the ASL synthesis process. Default values are set according
|
|
47
|
+
to typical parameters used in ASL analysis.
|
|
48
|
+
|
|
49
|
+
Examples
|
|
50
|
+
--------
|
|
51
|
+
>>> parser = _get_parser()
|
|
52
|
+
>>> args = parser.parse_args(['dataset_name', 'output.nii.gz'])
|
|
53
|
+
>>> print(args.dataset)
|
|
54
|
+
'dataset_name'
|
|
55
|
+
"""
|
|
28
56
|
# get the command line parameters
|
|
29
57
|
parser = argparse.ArgumentParser(
|
|
30
58
|
prog="synthASL",
|
|
@@ -70,7 +98,72 @@ def _get_parser():
|
|
|
70
98
|
return parser
|
|
71
99
|
|
|
72
100
|
|
|
73
|
-
def calcASL(
|
|
101
|
+
def calcASL(
|
|
102
|
+
lags: Any,
|
|
103
|
+
strengths: Any,
|
|
104
|
+
widths: Any,
|
|
105
|
+
mask: Any,
|
|
106
|
+
tagoffset: float = 2.945,
|
|
107
|
+
pld: float = 1.8,
|
|
108
|
+
TI: float = 1.8,
|
|
109
|
+
bloodT1: float = 1.841,
|
|
110
|
+
) -> None:
|
|
111
|
+
"""
|
|
112
|
+
Calculate ASL (Arterial Spin Labeling) signal based on lags, strengths, and timing parameters.
|
|
113
|
+
|
|
114
|
+
This function computes the ASL signal by applying temporal dynamics to the input lags and
|
|
115
|
+
strengths, considering blood T1 relaxation effects and tagging timing parameters.
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
lags : array-like
|
|
120
|
+
Time lags for the ASL signal calculation
|
|
121
|
+
strengths : array-like
|
|
122
|
+
Signal strengths corresponding to the lags
|
|
123
|
+
widths : array-like
|
|
124
|
+
Widths parameter (not used in current implementation)
|
|
125
|
+
mask : array-like
|
|
126
|
+
Binary mask for region of interest
|
|
127
|
+
tagoffset : float, optional
|
|
128
|
+
Tagging offset in seconds, default is 2.945
|
|
129
|
+
pld : float, optional
|
|
130
|
+
Preparation delay in seconds, default is 1.8
|
|
131
|
+
TI : float, optional
|
|
132
|
+
Inversion time in seconds, default is 1.8
|
|
133
|
+
bloodT1 : float, optional
|
|
134
|
+
Blood T1 relaxation time in seconds, default is 1.841
|
|
135
|
+
|
|
136
|
+
Returns
|
|
137
|
+
-------
|
|
138
|
+
tuple
|
|
139
|
+
A tuple containing:
|
|
140
|
+
- theaslimage : array-like
|
|
141
|
+
Calculated ASL image signal
|
|
142
|
+
- tagdecayfac : array-like
|
|
143
|
+
Tagging decay factor
|
|
144
|
+
- oxyfac : array-like
|
|
145
|
+
Oxygenation factor (constant value of 1.0)
|
|
146
|
+
- cbvfac : array-like
|
|
147
|
+
CBV (Cerebral Blood Volume) factor
|
|
148
|
+
- calcmask : array-like
|
|
149
|
+
Calculated mask with time constraints
|
|
150
|
+
- offsets : array-like
|
|
151
|
+
Time offsets after adding tagoffset
|
|
152
|
+
|
|
153
|
+
Notes
|
|
154
|
+
-----
|
|
155
|
+
The function applies exponential decay based on blood T1 relaxation and only considers
|
|
156
|
+
positive delays after the preparation delay (pld). The calculation uses a linear
|
|
157
|
+
interpolation over 50 time points between pld and pld + TI.
|
|
158
|
+
|
|
159
|
+
Examples
|
|
160
|
+
--------
|
|
161
|
+
>>> import numpy as np
|
|
162
|
+
>>> lags = np.array([0.5, 1.0, 1.5])
|
|
163
|
+
>>> strengths = np.array([1.0, 1.5, 2.0])
|
|
164
|
+
>>> mask = np.array([1, 1, 1])
|
|
165
|
+
>>> result = calcASL(lags, strengths, None, mask)
|
|
166
|
+
"""
|
|
74
167
|
theaslimage = lags * 0.0
|
|
75
168
|
|
|
76
169
|
# convert rapidtide delays to time from tagging, and only keep positive delays after pld
|
|
@@ -85,7 +178,65 @@ def calcASL(lags, strengths, widths, mask, tagoffset=2.945, pld=1.8, TI=1.8, blo
|
|
|
85
178
|
return theaslimage, tagdecayfac, oxyfac, cbvfac, calcmask, offsets
|
|
86
179
|
|
|
87
180
|
|
|
88
|
-
def synthASL(args):
|
|
181
|
+
def synthASL(args: Any) -> None:
|
|
182
|
+
"""
|
|
183
|
+
Generate synthetic ASL (Arterial Spin Labeling) images and associated parameters.
|
|
184
|
+
|
|
185
|
+
This function reads ASL dataset parameters from a specified input dataset,
|
|
186
|
+
computes synthetic ASL signal using the `calcASL` function, and saves the
|
|
187
|
+
resulting images and intermediate outputs as NIfTI files.
|
|
188
|
+
|
|
189
|
+
Parameters
|
|
190
|
+
----------
|
|
191
|
+
args : Any
|
|
192
|
+
Command-line arguments object containing the following attributes:
|
|
193
|
+
- dataset : str
|
|
194
|
+
Path to the input dataset.
|
|
195
|
+
- outputfilename : str
|
|
196
|
+
Base name for output NIfTI files.
|
|
197
|
+
- bloodT1 : float
|
|
198
|
+
Blood T1 relaxation time in seconds.
|
|
199
|
+
- tagoffset : float
|
|
200
|
+
Tag offset in seconds.
|
|
201
|
+
- pld : float
|
|
202
|
+
Post-labeling delay in seconds.
|
|
203
|
+
- labelduration : float
|
|
204
|
+
Labeling pulse duration in seconds.
|
|
205
|
+
|
|
206
|
+
Returns
|
|
207
|
+
-------
|
|
208
|
+
None
|
|
209
|
+
This function does not return a value but writes multiple NIfTI files
|
|
210
|
+
to disk, including:
|
|
211
|
+
- `<outputfilename>_ASL.nii.gz`
|
|
212
|
+
- `<outputfilename>_tagdecayfac.nii.gz`
|
|
213
|
+
- `<outputfilename>_oxyfac.nii.gz`
|
|
214
|
+
- `<outputfilename>_cbvfac.nii.gz`
|
|
215
|
+
- `<outputfilename>_calcmask.nii.gz`
|
|
216
|
+
- `<outputfilename>_offsets.nii.gz`
|
|
217
|
+
- `<outputfilename>_lagmask.nii.gz`
|
|
218
|
+
- `<outputfilename>_lagtimes.nii.gz`
|
|
219
|
+
- `<outputfilename>_lagstrengths.nii.gz`
|
|
220
|
+
|
|
221
|
+
Notes
|
|
222
|
+
-----
|
|
223
|
+
The function relies on the `RapidtideDataset` class to load overlay data
|
|
224
|
+
and uses `calcASL` to compute the synthetic ASL signal. All outputs are
|
|
225
|
+
saved using `tide_io.savetonifti`.
|
|
226
|
+
|
|
227
|
+
Examples
|
|
228
|
+
--------
|
|
229
|
+
>>> import argparse
|
|
230
|
+
>>> args = argparse.Namespace(
|
|
231
|
+
... dataset="path/to/dataset",
|
|
232
|
+
... outputfilename="output",
|
|
233
|
+
... bloodT1=1.6,
|
|
234
|
+
... tagoffset=0.0,
|
|
235
|
+
... pld=1.5,
|
|
236
|
+
... labelduration=1.0
|
|
237
|
+
... )
|
|
238
|
+
>>> synthASL(args)
|
|
239
|
+
"""
|
|
89
240
|
# get the command line parameters
|
|
90
241
|
try:
|
|
91
242
|
args = _get_parser().parse_args()
|
|
@@ -17,14 +17,42 @@
|
|
|
17
17
|
#
|
|
18
18
|
#
|
|
19
19
|
import argparse
|
|
20
|
+
from argparse import Namespace
|
|
21
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
|
20
22
|
|
|
21
23
|
import numpy as np
|
|
24
|
+
from numpy.typing import NDArray
|
|
22
25
|
|
|
23
26
|
import rapidtide.io as tide_io
|
|
24
27
|
import rapidtide.util as tide_util
|
|
25
28
|
|
|
26
29
|
|
|
27
|
-
def _get_parser():
|
|
30
|
+
def _get_parser() -> Any:
|
|
31
|
+
"""
|
|
32
|
+
Create and configure argument parser for tcfrom2col command line tool.
|
|
33
|
+
|
|
34
|
+
This function sets up an argument parser with required and optional arguments
|
|
35
|
+
for processing two-column data files into time course output.
|
|
36
|
+
|
|
37
|
+
Returns
|
|
38
|
+
-------
|
|
39
|
+
argparse.ArgumentParser
|
|
40
|
+
Configured argument parser object with all required and optional arguments
|
|
41
|
+
for the tcfrom2col tool.
|
|
42
|
+
|
|
43
|
+
Notes
|
|
44
|
+
-----
|
|
45
|
+
The parser includes the following required arguments:
|
|
46
|
+
- infilename: input two column file name
|
|
47
|
+
- timestep: time step of output time course in seconds
|
|
48
|
+
- numpoints: number of output time points
|
|
49
|
+
- outfilename: output time course file name
|
|
50
|
+
|
|
51
|
+
Examples
|
|
52
|
+
--------
|
|
53
|
+
>>> parser = _get_parser()
|
|
54
|
+
>>> args = parser.parse_args()
|
|
55
|
+
"""
|
|
28
56
|
# get the command line parameters
|
|
29
57
|
parser = argparse.ArgumentParser(
|
|
30
58
|
prog="tcfrom2col",
|
|
@@ -48,7 +76,53 @@ def _get_parser():
|
|
|
48
76
|
return parser
|
|
49
77
|
|
|
50
78
|
|
|
51
|
-
def tcfrom2col(args):
|
|
79
|
+
def tcfrom2col(args: Any) -> None:
|
|
80
|
+
"""
|
|
81
|
+
Convert two-column data to tidal constituent data.
|
|
82
|
+
|
|
83
|
+
This function reads two-column input data, processes it to extract tidal constituents,
|
|
84
|
+
and writes the results to an output file. The input data is expected to be in a format
|
|
85
|
+
suitable for tidal analysis, and the output contains the computed tidal constituents.
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
args : Any
|
|
90
|
+
An object containing the following attributes:
|
|
91
|
+
- infilename : str
|
|
92
|
+
Path to the input file containing two-column data
|
|
93
|
+
- outfilename : str
|
|
94
|
+
Path to the output file for writing tidal constituent data
|
|
95
|
+
- numpoints : int
|
|
96
|
+
Number of data points in the time series
|
|
97
|
+
- timestep : float
|
|
98
|
+
Time step between data points
|
|
99
|
+
- debug : bool
|
|
100
|
+
Flag to enable debug printing
|
|
101
|
+
|
|
102
|
+
Returns
|
|
103
|
+
-------
|
|
104
|
+
None
|
|
105
|
+
This function does not return a value but writes output to a file.
|
|
106
|
+
|
|
107
|
+
Notes
|
|
108
|
+
-----
|
|
109
|
+
The function uses `tide_io.readvecs` to read input data and `tide_util.maketcfrom2col`
|
|
110
|
+
to perform the tidal constituent calculation. The time axis is generated based on the
|
|
111
|
+
number of points and time step provided in the args object.
|
|
112
|
+
|
|
113
|
+
Examples
|
|
114
|
+
--------
|
|
115
|
+
>>> class Args:
|
|
116
|
+
... def __init__(self):
|
|
117
|
+
... self.infilename = 'input.txt'
|
|
118
|
+
... self.outfilename = 'output.txt'
|
|
119
|
+
... self.numpoints = 1000
|
|
120
|
+
... self.timestep = 300.0
|
|
121
|
+
... self.debug = False
|
|
122
|
+
...
|
|
123
|
+
>>> args = Args()
|
|
124
|
+
>>> tcfrom2col(args)
|
|
125
|
+
"""
|
|
52
126
|
if args.debug:
|
|
53
127
|
print(args)
|
|
54
128
|
|