junifer 0.0.4.dev493__py3-none-any.whl → 0.0.4.dev530__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.
- junifer/_version.py +2 -2
- junifer/api/res/ants/ResampleImage +3 -0
- junifer/data/coordinates.py +83 -44
- junifer/data/masks.py +46 -37
- junifer/data/parcellations.py +46 -40
- junifer/markers/falff/falff_estimator.py +33 -72
- junifer/markers/reho/reho_estimator.py +7 -54
- junifer/preprocess/ants/__init__.py +4 -0
- junifer/preprocess/ants/ants_apply_transforms_warper.py +224 -0
- junifer/preprocess/ants/tests/test_ants_apply_transforms_warper.py +124 -0
- junifer/preprocess/bold_warper.py +40 -9
- junifer/preprocess/fsl/apply_warper.py +5 -56
- junifer/preprocess/fsl/tests/test_apply_warper.py +53 -22
- junifer/preprocess/tests/test_bold_warper.py +64 -14
- junifer/utils/__init__.py +1 -0
- junifer/utils/helpers.py +53 -0
- junifer/utils/tests/test_helpers.py +35 -0
- {junifer-0.0.4.dev493.dist-info → junifer-0.0.4.dev530.dist-info}/METADATA +1 -1
- {junifer-0.0.4.dev493.dist-info → junifer-0.0.4.dev530.dist-info}/RECORD +24 -18
- {junifer-0.0.4.dev493.dist-info → junifer-0.0.4.dev530.dist-info}/AUTHORS.rst +0 -0
- {junifer-0.0.4.dev493.dist-info → junifer-0.0.4.dev530.dist-info}/LICENSE.md +0 -0
- {junifer-0.0.4.dev493.dist-info → junifer-0.0.4.dev530.dist-info}/WHEEL +0 -0
- {junifer-0.0.4.dev493.dist-info → junifer-0.0.4.dev530.dist-info}/entry_points.txt +0 -0
- {junifer-0.0.4.dev493.dist-info → junifer-0.0.4.dev530.dist-info}/top_level.txt +0 -0
junifer/_version.py
CHANGED
@@ -12,5 +12,5 @@ __version__: str
|
|
12
12
|
__version_tuple__: VERSION_TUPLE
|
13
13
|
version_tuple: VERSION_TUPLE
|
14
14
|
|
15
|
-
__version__ = version = '0.0.4.
|
16
|
-
__version_tuple__ = version_tuple = (0, 0, 4, '
|
15
|
+
__version__ = version = '0.0.4.dev530'
|
16
|
+
__version_tuple__ = version_tuple = (0, 0, 4, 'dev530')
|
junifer/data/coordinates.py
CHANGED
@@ -4,7 +4,6 @@
|
|
4
4
|
# Synchon Mandal <s.mandal@fz-juelich.de>
|
5
5
|
# License: AGPL
|
6
6
|
|
7
|
-
import subprocess
|
8
7
|
import typing
|
9
8
|
from pathlib import Path
|
10
9
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
@@ -14,7 +13,7 @@ import pandas as pd
|
|
14
13
|
from numpy.typing import ArrayLike
|
15
14
|
|
16
15
|
from ..pipeline import WorkDirManager
|
17
|
-
from ..utils
|
16
|
+
from ..utils import logger, raise_error, run_ext_cmd, warn_with_log
|
18
17
|
|
19
18
|
|
20
19
|
# Path to the VOIs
|
@@ -231,6 +230,8 @@ def get_coordinates(
|
|
231
230
|
|
232
231
|
Raises
|
233
232
|
------
|
233
|
+
RuntimeError
|
234
|
+
If warp / transformation file extension is not ".mat" or ".h5".
|
234
235
|
ValueError
|
235
236
|
If ``extra_input`` is None when ``target_data``'s space is native.
|
236
237
|
|
@@ -251,12 +252,6 @@ def get_coordinates(
|
|
251
252
|
# Create component-scoped tempdir
|
252
253
|
tempdir = WorkDirManager().get_tempdir(prefix="coordinates")
|
253
254
|
|
254
|
-
# Save existing coordinates to a component-scoped tempfile
|
255
|
-
pretransform_coordinates_path = (
|
256
|
-
tempdir / "pretransform_coordinates.txt"
|
257
|
-
)
|
258
|
-
np.savetxt(pretransform_coordinates_path, seeds)
|
259
|
-
|
260
255
|
# Create element-scoped tempdir so that transformed coordinates is
|
261
256
|
# available later as numpy stores file path reference for
|
262
257
|
# loading on computation
|
@@ -264,48 +259,92 @@ def get_coordinates(
|
|
264
259
|
prefix="coordinates"
|
265
260
|
)
|
266
261
|
|
267
|
-
#
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
262
|
+
# Check for warp file type to use correct tool
|
263
|
+
warp_file_ext = extra_input["Warp"]["path"].suffix
|
264
|
+
if warp_file_ext == ".mat":
|
265
|
+
# Save existing coordinates to a component-scoped tempfile
|
266
|
+
pretransform_coordinates_path = (
|
267
|
+
tempdir / "pretransform_coordinates.txt"
|
268
|
+
)
|
269
|
+
np.savetxt(pretransform_coordinates_path, seeds)
|
270
|
+
|
271
|
+
# Create an element-scoped tempfile for transformed coordinates
|
272
|
+
# output
|
273
|
+
transformed_coords_path = (
|
274
|
+
element_tempdir / "coordinates_transformed.txt"
|
275
|
+
)
|
276
|
+
|
277
|
+
logger.debug("Using FSL for coordinates transformation")
|
278
|
+
# Set img2imgcoord command
|
279
|
+
img2imgcoord_cmd = [
|
280
|
+
"cat",
|
281
|
+
f"{pretransform_coordinates_path.resolve()}",
|
282
|
+
"| img2imgcoord -mm",
|
283
|
+
f"-src {target_data['path'].resolve()}",
|
284
|
+
f"-dest {target_data['reference_path'].resolve()}",
|
285
|
+
f"-warp {extra_input['Warp']['path'].resolve()}",
|
286
|
+
f"> {transformed_coords_path.resolve()};",
|
287
|
+
f"sed -i 1d {transformed_coords_path.resolve()}",
|
288
|
+
]
|
289
|
+
# Call img2imgcoord
|
290
|
+
run_ext_cmd(name="img2imgcoord", cmd=img2imgcoord_cmd)
|
291
|
+
|
292
|
+
# Load coordinates
|
293
|
+
seeds = np.loadtxt(transformed_coords_path)
|
294
|
+
|
295
|
+
elif warp_file_ext == ".h5":
|
296
|
+
# Save existing coordinates to a component-scoped tempfile
|
297
|
+
pretransform_coordinates_path = (
|
298
|
+
tempdir / "pretransform_coordinates.csv"
|
299
|
+
)
|
300
|
+
np.savetxt(
|
301
|
+
pretransform_coordinates_path,
|
302
|
+
seeds,
|
303
|
+
delimiter=",",
|
304
|
+
# Add header while saving to make ANTs work
|
305
|
+
header="x,y,z",
|
298
306
|
)
|
307
|
+
|
308
|
+
# Create an element-scoped tempfile for transformed coordinates
|
309
|
+
# output
|
310
|
+
transformed_coords_path = (
|
311
|
+
element_tempdir / "coordinates_transformed.csv"
|
312
|
+
)
|
313
|
+
|
314
|
+
logger.debug("Using ANTs for coordinates transformation")
|
315
|
+
# Set antsApplyTransformsToPoints command
|
316
|
+
apply_transforms_to_points_cmd = [
|
317
|
+
"antsApplyTransformsToPoints",
|
318
|
+
"-d 3",
|
319
|
+
"-p 1",
|
320
|
+
"-f 0",
|
321
|
+
f"-i {pretransform_coordinates_path.resolve()}",
|
322
|
+
f"-o {transformed_coords_path.resolve()}",
|
323
|
+
f"-t {extra_input['Warp']['path'].resolve()};",
|
324
|
+
]
|
325
|
+
# Call antsApplyTransformsToPoints
|
326
|
+
run_ext_cmd(
|
327
|
+
name="antsApplyTransformsToPoints",
|
328
|
+
cmd=apply_transforms_to_points_cmd,
|
329
|
+
)
|
330
|
+
|
331
|
+
# Load coordinates
|
332
|
+
seeds = np.loadtxt(
|
333
|
+
# Skip header when reading
|
334
|
+
transformed_coords_path,
|
335
|
+
delimiter=",",
|
336
|
+
skiprows=1,
|
337
|
+
)
|
338
|
+
|
299
339
|
else:
|
300
340
|
raise_error(
|
301
|
-
msg=
|
302
|
-
|
341
|
+
msg=(
|
342
|
+
"Unknown warp / transformation file extension: "
|
343
|
+
f"{warp_file_ext}"
|
344
|
+
),
|
303
345
|
klass=RuntimeError,
|
304
346
|
)
|
305
347
|
|
306
|
-
# Load coordinates
|
307
|
-
seeds = np.loadtxt(img2imgcoord_out_path)
|
308
|
-
|
309
348
|
# Delete tempdir
|
310
349
|
WorkDirManager().delete_tempdir(tempdir)
|
311
350
|
|
junifer/data/masks.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
"""Provide functions for masks."""
|
2
2
|
|
3
3
|
# Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
|
4
|
+
# Synchon Mandal <s.mandal@fz-juelich.de>
|
4
5
|
# License: AGPL
|
5
6
|
|
6
|
-
import subprocess
|
7
7
|
import typing
|
8
8
|
from pathlib import Path
|
9
9
|
from typing import (
|
@@ -29,7 +29,7 @@ from nilearn.masking import (
|
|
29
29
|
)
|
30
30
|
|
31
31
|
from ..pipeline import WorkDirManager
|
32
|
-
from ..utils
|
32
|
+
from ..utils import logger, raise_error, run_ext_cmd
|
33
33
|
from .utils import closest_resolution
|
34
34
|
|
35
35
|
|
@@ -199,7 +199,8 @@ def get_mask( # noqa: C901
|
|
199
199
|
------
|
200
200
|
RuntimeError
|
201
201
|
If masks are in different spaces and they need to be intersected /
|
202
|
-
unionized
|
202
|
+
unionized or
|
203
|
+
if warp / transformation file extension is not ".mat" or ".h5".
|
203
204
|
ValueError
|
204
205
|
If extra key is provided in addition to mask name in ``masks`` or
|
205
206
|
if no mask is provided or
|
@@ -364,50 +365,58 @@ def get_mask( # noqa: C901
|
|
364
365
|
element_tempdir = WorkDirManager().get_element_tempdir(prefix="masks")
|
365
366
|
|
366
367
|
# Create an element-scoped tempfile for warped output
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
#
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
"
|
393
|
-
|
394
|
-
|
368
|
+
warped_mask_path = element_tempdir / "mask_warped.nii.gz"
|
369
|
+
|
370
|
+
# Check for warp file type to use correct tool
|
371
|
+
warp_file_ext = extra_input["Warp"]["path"].suffix
|
372
|
+
if warp_file_ext == ".mat":
|
373
|
+
logger.debug("Using FSL for mask warping")
|
374
|
+
# Set applywarp command
|
375
|
+
applywarp_cmd = [
|
376
|
+
"applywarp",
|
377
|
+
"--interp=nn",
|
378
|
+
f"-i {prewarp_mask_path.resolve()}",
|
379
|
+
# use resampled reference
|
380
|
+
f"-r {target_data['reference_path'].resolve()}",
|
381
|
+
f"-w {extra_input['Warp']['path'].resolve()}",
|
382
|
+
f"-o {warped_mask_path.resolve()}",
|
383
|
+
]
|
384
|
+
# Call applywarp
|
385
|
+
run_ext_cmd(name="applywarp", cmd=applywarp_cmd)
|
386
|
+
|
387
|
+
elif warp_file_ext == ".h5":
|
388
|
+
logger.debug("Using ANTs for mask warping")
|
389
|
+
# Set antsApplyTransforms command
|
390
|
+
apply_transforms_cmd = [
|
391
|
+
"antsApplyTransforms",
|
392
|
+
"-d 3",
|
393
|
+
"-e 3",
|
394
|
+
"-n 'GenericLabel[NearestNeighbor]'",
|
395
|
+
f"-i {prewarp_mask_path.resolve()}",
|
396
|
+
# use resampled reference
|
397
|
+
f"-r {target_data['reference_path'].resolve()}",
|
398
|
+
f"-t {extra_input['Warp']['path'].resolve()}",
|
399
|
+
f"-o {warped_mask_path.resolve()}",
|
400
|
+
]
|
401
|
+
# Call antsApplyTransforms
|
402
|
+
run_ext_cmd(name="antsApplyTransforms", cmd=apply_transforms_cmd)
|
403
|
+
|
395
404
|
else:
|
396
405
|
raise_error(
|
397
|
-
msg=
|
398
|
-
|
406
|
+
msg=(
|
407
|
+
"Unknown warp / transformation file extension: "
|
408
|
+
f"{warp_file_ext}"
|
409
|
+
),
|
399
410
|
klass=RuntimeError,
|
400
411
|
)
|
401
412
|
|
402
413
|
# Load nifti
|
403
|
-
mask_img = nib.load(
|
414
|
+
mask_img = nib.load(warped_mask_path)
|
404
415
|
|
405
416
|
# Delete tempdir
|
406
417
|
WorkDirManager().delete_tempdir(tempdir)
|
407
418
|
|
408
|
-
#
|
409
|
-
mask_img = typing.cast("Nifti1Image", mask_img)
|
410
|
-
return mask_img
|
419
|
+
return mask_img # type: ignore
|
411
420
|
|
412
421
|
|
413
422
|
def load_mask(
|
junifer/data/parcellations.py
CHANGED
@@ -7,7 +7,6 @@
|
|
7
7
|
|
8
8
|
import io
|
9
9
|
import shutil
|
10
|
-
import subprocess
|
11
10
|
import tarfile
|
12
11
|
import tempfile
|
13
12
|
import typing
|
@@ -23,7 +22,7 @@ from nilearn import datasets, image
|
|
23
22
|
from requests.exceptions import ConnectionError, HTTPError, ReadTimeout
|
24
23
|
|
25
24
|
from ..pipeline import WorkDirManager
|
26
|
-
from ..utils
|
25
|
+
from ..utils import logger, raise_error, run_ext_cmd, warn_with_log
|
27
26
|
from .utils import closest_resolution
|
28
27
|
|
29
28
|
|
@@ -231,7 +230,8 @@ def get_parcellation(
|
|
231
230
|
Raises
|
232
231
|
------
|
233
232
|
RuntimeError
|
234
|
-
If parcellations are in different spaces and they need to be merged
|
233
|
+
If parcellations are in different spaces and they need to be merged or
|
234
|
+
if warp / transformation file extension is not ".mat" or ".h5".
|
235
235
|
ValueError
|
236
236
|
If ``extra_input`` is None when ``target_data``'s space is native.
|
237
237
|
|
@@ -302,55 +302,61 @@ def get_parcellation(
|
|
302
302
|
element_tempdir = WorkDirManager().get_element_tempdir(
|
303
303
|
prefix="parcellations"
|
304
304
|
)
|
305
|
-
|
306
305
|
# Create an element-scoped tempfile for warped output
|
307
|
-
|
308
|
-
|
309
|
-
applywarp_cmd = [
|
310
|
-
"applywarp",
|
311
|
-
"--interp=nn",
|
312
|
-
f"-i {prewarp_parcellation_path.resolve()}",
|
313
|
-
# use resampled reference
|
314
|
-
f"-r {target_data['reference_path'].resolve()}",
|
315
|
-
f"-w {extra_input['Warp']['path'].resolve()}",
|
316
|
-
f"-o {applywarp_out_path.resolve()}",
|
317
|
-
]
|
318
|
-
# Call applywarp
|
319
|
-
applywarp_cmd_str = " ".join(applywarp_cmd)
|
320
|
-
logger.info(f"applywarp command to be executed: {applywarp_cmd_str}")
|
321
|
-
applywarp_process = subprocess.run(
|
322
|
-
applywarp_cmd_str, # string needed with shell=True
|
323
|
-
stdin=subprocess.DEVNULL,
|
324
|
-
stdout=subprocess.PIPE,
|
325
|
-
stderr=subprocess.STDOUT,
|
326
|
-
shell=True, # needed for respecting $PATH
|
327
|
-
check=False,
|
306
|
+
warped_parcellation_path = (
|
307
|
+
element_tempdir / "parcellation_warped.nii.gz"
|
328
308
|
)
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
309
|
+
|
310
|
+
# Check for warp file type to use correct tool
|
311
|
+
warp_file_ext = extra_input["Warp"]["path"].suffix
|
312
|
+
if warp_file_ext == ".mat":
|
313
|
+
logger.debug("Using FSL for parcellation warping")
|
314
|
+
# Set applywarp command
|
315
|
+
applywarp_cmd = [
|
316
|
+
"applywarp",
|
317
|
+
"--interp=nn",
|
318
|
+
f"-i {prewarp_parcellation_path.resolve()}",
|
319
|
+
# use resampled reference
|
320
|
+
f"-r {target_data['reference_path'].resolve()}",
|
321
|
+
f"-w {extra_input['Warp']['path'].resolve()}",
|
322
|
+
f"-o {warped_parcellation_path.resolve()}",
|
323
|
+
]
|
324
|
+
# Call applywarp
|
325
|
+
run_ext_cmd(name="applywarp", cmd=applywarp_cmd)
|
326
|
+
|
327
|
+
elif warp_file_ext == ".h5":
|
328
|
+
logger.debug("Using ANTs for parcellation warping")
|
329
|
+
# Set antsApplyTransforms command
|
330
|
+
apply_transforms_cmd = [
|
331
|
+
"antsApplyTransforms",
|
332
|
+
"-d 3",
|
333
|
+
"-e 3",
|
334
|
+
"-n 'GenericLabel[NearestNeighbor]'",
|
335
|
+
f"-i {prewarp_parcellation_path.resolve()}",
|
336
|
+
# use resampled reference
|
337
|
+
f"-r {target_data['reference_path'].resolve()}",
|
338
|
+
f"-t {extra_input['Warp']['path'].resolve()}",
|
339
|
+
f"-o {warped_parcellation_path.resolve()}",
|
340
|
+
]
|
341
|
+
# Call antsApplyTransforms
|
342
|
+
run_ext_cmd(name="antsApplyTransforms", cmd=apply_transforms_cmd)
|
343
|
+
|
335
344
|
else:
|
336
345
|
raise_error(
|
337
|
-
msg=
|
338
|
-
|
346
|
+
msg=(
|
347
|
+
"Unknown warp / transformation file extension: "
|
348
|
+
f"{warp_file_ext}"
|
349
|
+
),
|
339
350
|
klass=RuntimeError,
|
340
351
|
)
|
341
352
|
|
342
353
|
# Load nifti
|
343
|
-
resampled_parcellation_img = nib.load(
|
354
|
+
resampled_parcellation_img = nib.load(warped_parcellation_path)
|
344
355
|
|
345
356
|
# Delete tempdir
|
346
357
|
WorkDirManager().delete_tempdir(tempdir)
|
347
358
|
|
348
|
-
|
349
|
-
resampled_parcellation_img = typing.cast(
|
350
|
-
"Nifti1Image", resampled_parcellation_img
|
351
|
-
)
|
352
|
-
|
353
|
-
return resampled_parcellation_img, labels
|
359
|
+
return resampled_parcellation_img, labels # type: ignore
|
354
360
|
|
355
361
|
|
356
362
|
def load_parcellation(
|
@@ -4,11 +4,10 @@
|
|
4
4
|
# Federico Raimondo <f.raimondo@fz-juelich.de>
|
5
5
|
# License: AGPL
|
6
6
|
|
7
|
-
import subprocess
|
8
7
|
import typing
|
9
8
|
from functools import lru_cache
|
10
9
|
from pathlib import Path
|
11
|
-
from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Union
|
10
|
+
from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Union
|
12
11
|
|
13
12
|
import nibabel as nib
|
14
13
|
import numpy as np
|
@@ -17,7 +16,7 @@ from scipy.fft import fft, fftfreq
|
|
17
16
|
|
18
17
|
from ...pipeline import WorkDirManager
|
19
18
|
from ...pipeline.singleton import singleton
|
20
|
-
from ...utils import logger,
|
19
|
+
from ...utils import logger, run_ext_cmd
|
21
20
|
|
22
21
|
|
23
22
|
if TYPE_CHECKING:
|
@@ -54,42 +53,6 @@ class ALFFEstimator:
|
|
54
53
|
if self.temp_dir_path is not None:
|
55
54
|
WorkDirManager().delete_tempdir(self.temp_dir_path)
|
56
55
|
|
57
|
-
@staticmethod
|
58
|
-
def _run_afni_cmd(cmd: str) -> None:
|
59
|
-
"""Run AFNI command.
|
60
|
-
|
61
|
-
Parameters
|
62
|
-
----------
|
63
|
-
cmd : str
|
64
|
-
AFNI command to be executed.
|
65
|
-
|
66
|
-
Raises
|
67
|
-
------
|
68
|
-
RuntimeError
|
69
|
-
If AFNI command fails.
|
70
|
-
|
71
|
-
"""
|
72
|
-
logger.info(f"AFNI command to be executed: {cmd}")
|
73
|
-
process = subprocess.run(
|
74
|
-
cmd,
|
75
|
-
stdin=subprocess.DEVNULL,
|
76
|
-
stdout=subprocess.PIPE,
|
77
|
-
stderr=subprocess.STDOUT,
|
78
|
-
shell=True,
|
79
|
-
check=False,
|
80
|
-
)
|
81
|
-
if process.returncode == 0:
|
82
|
-
logger.info(
|
83
|
-
"AFNI command succeeded with the following output: "
|
84
|
-
f"{process.stdout}"
|
85
|
-
)
|
86
|
-
else:
|
87
|
-
raise_error(
|
88
|
-
msg="AFNI command failed with the following error: "
|
89
|
-
f"{process.stdout}",
|
90
|
-
klass=RuntimeError,
|
91
|
-
)
|
92
|
-
|
93
56
|
def _compute_alff_afni(
|
94
57
|
self,
|
95
58
|
data: Union["Nifti1Image", "Nifti2Image"],
|
@@ -121,11 +84,6 @@ class ALFFEstimator:
|
|
121
84
|
pathlib.Path
|
122
85
|
The path to the fALFF map as NIfTI.
|
123
86
|
|
124
|
-
Raises
|
125
|
-
------
|
126
|
-
RuntimeError
|
127
|
-
If the AFNI commands fails due to some issues.
|
128
|
-
|
129
87
|
"""
|
130
88
|
# Note: self.temp_dir_path is sure to exist before proceeding, so
|
131
89
|
# types checks are ignored further on.
|
@@ -150,31 +108,36 @@ class ALFFEstimator:
|
|
150
108
|
self.temp_dir_path / "temp_falff" # type: ignore
|
151
109
|
)
|
152
110
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
f"-
|
157
|
-
f"-
|
158
|
-
"-
|
159
|
-
|
111
|
+
# Set 3dRSFC command
|
112
|
+
bp_cmd = [
|
113
|
+
"3dRSFC",
|
114
|
+
f"-prefix {falff_afni_out_path_prefix.resolve()}",
|
115
|
+
f"-input {nifti_in_file_path.resolve()}",
|
116
|
+
f"-band {highpass} {lowpass}",
|
117
|
+
"-no_rsfa -nosat -nodetrend",
|
118
|
+
]
|
160
119
|
if tr is not None:
|
161
|
-
bp_cmd
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
f"{
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
120
|
+
bp_cmd.append(f"-dt {tr}")
|
121
|
+
# Call 3dRSFC
|
122
|
+
run_ext_cmd(name="3dRSFC", cmd=bp_cmd)
|
123
|
+
|
124
|
+
# Convert alff output to nifti
|
125
|
+
convert_alff_cmd = [
|
126
|
+
"3dAFNItoNIFTI",
|
127
|
+
f"-prefix {alff_fname.resolve()}",
|
128
|
+
f"{falff_afni_out_path_prefix}_ALFF+tlrc.BRIK",
|
129
|
+
]
|
130
|
+
# Call 3dAFNItoNIFTI
|
131
|
+
run_ext_cmd(name="3dAFNItoNIFTI", cmd=convert_alff_cmd)
|
132
|
+
|
133
|
+
# Convert falff output to nifti
|
134
|
+
convert_falff_cmd = [
|
135
|
+
"3dAFNItoNIFTI",
|
136
|
+
f"-prefix {falff_fname.resolve()}",
|
137
|
+
f"{falff_afni_out_path_prefix}_fALFF+tlrc.BRIK",
|
138
|
+
]
|
139
|
+
# Call 3dAFNItoNIFTI
|
140
|
+
run_ext_cmd(name="3dAFNItoNIFTI", cmd=convert_falff_cmd)
|
178
141
|
|
179
142
|
# Cleanup intermediate files
|
180
143
|
for fname in self.temp_dir_path.glob("temp_*"): # type: ignore
|
@@ -183,10 +146,8 @@ class ALFFEstimator:
|
|
183
146
|
# Load niftis
|
184
147
|
alff_img = nib.load(alff_fname)
|
185
148
|
falff_img = nib.load(falff_fname)
|
186
|
-
|
187
|
-
alff_img
|
188
|
-
falff_img = cast("Nifti1Image", falff_img)
|
189
|
-
return alff_img, falff_img, alff_fname, falff_fname
|
149
|
+
|
150
|
+
return alff_img, falff_img, alff_fname, falff_fname # type: ignore
|
190
151
|
|
191
152
|
def _compute_alff_python(
|
192
153
|
self,
|