From 7f4b302ab916de4d6257cd76f9eba7ef0931c948 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Wed, 13 Dec 2023 16:52:53 -0500 Subject: [PATCH 1/3] MNT: Update requirements.txt --- requirements.txt | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/requirements.txt b/requirements.txt index b401dd76a..0973720b1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -54,11 +54,11 @@ contourpy==1.2.0 # via # bokeh # matplotlib -cryptography==41.0.5 +cryptography==41.0.7 # via secretstorage cycler==0.12.1 # via matplotlib -datalad==0.19.3 +datalad==0.19.4 # via # datalad-next # datalad-osf @@ -87,7 +87,7 @@ greenlet==3.0.1 # via sqlalchemy h5py==3.10.0 # via nitransforms -humanize==4.8.0 +humanize==4.9.0 # via # datalad # datalad-next @@ -95,10 +95,11 @@ idna==3.4 # via requests imageio==2.33.0 # via scikit-image -importlib-metadata==6.8.0 +importlib-metadata==7.0.0 # via keyring importlib-resources==6.1.1 # via + # nireports # niworkflows # sdcflows # templateflow @@ -163,7 +164,6 @@ matplotlib==3.8.2 # tedana migas==0.4.0 # via - # file:///home/chris/projects/nipreps/fmriprep-ng # fmriprep more-itertools==10.1.0 # via jaraco-classes @@ -202,7 +202,7 @@ nipype==1.8.6 # niworkflows # sdcflows # smriprep -nireports==23.1.0 +nireports==23.2.0 # via # fmriprep # fmriprep (pyproject.toml) @@ -216,7 +216,7 @@ nitransforms==23.0.1 # fmriprep (pyproject.toml) # niworkflows # sdcflows -niworkflows==1.9.0 +niworkflows==1.10.0 # via # fmriprep # fmriprep (pyproject.toml) @@ -289,7 +289,7 @@ pillow==10.1.0 # imageio # matplotlib # scikit-image -platformdirs==4.0.0 +platformdirs==4.1.0 # via datalad prometheus-client==0.19.0 # via codecarbon @@ -329,7 +329,7 @@ python-dateutil==2.8.2 # nipype # pandas # prov -python-gitlab==4.1.1 +python-gitlab==4.2.0 # via datalad pytz==2023.3.post1 # via @@ -392,9 +392,8 @@ seaborn==0.13.0 # niworkflows secretstorage==3.3.3 # via keyring -sentry-sdk==1.36.0 +sentry-sdk==1.39.0 # via - # file:///home/chris/projects/nipreps/fmriprep-ng # fmriprep simplejson==3.19.2 # via nipype @@ -404,7 +403,7 @@ six==1.16.0 # isodate # osfclient # python-dateutil -smriprep==0.13.1 +smriprep==0.13.2 # via # fmriprep # fmriprep (pyproject.toml) From fcdbb542d59f931977720dcf325160eb7e2296fb Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Fri, 8 Dec 2023 16:35:05 -0500 Subject: [PATCH 2/3] ENH: Allow Jacobian determinant modulation to be selected --- fmriprep/interfaces/resampling.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/fmriprep/interfaces/resampling.py b/fmriprep/interfaces/resampling.py index f997765ea..6111623cb 100644 --- a/fmriprep/interfaces/resampling.py +++ b/fmriprep/interfaces/resampling.py @@ -49,6 +49,7 @@ class ResampleSeriesInputSpec(TraitedSpec): "k-", desc="the phase-encoding direction corresponding to in_data", ) + jacobian = traits.Bool(mandatory=True, desc="Whether to apply Jacobian correction") num_threads = traits.Int(1, usedefault=True, desc="Number of threads to use for resampling") output_data_type = traits.Str("float32", usedefault=True, desc="Data type of output image") order = traits.Int(3, usedefault=True, desc="Order of interpolation (0=nearest, 3=cubic)") @@ -105,6 +106,7 @@ def _run_interface(self, runtime): transforms=transforms, fieldmap=fieldmap, pe_info=pe_info, + jacobian=self.inputs.jacobian, nthreads=self.inputs.num_threads, output_dtype=self.inputs.output_data_type, order=self.inputs.order, @@ -217,6 +219,7 @@ def resample_vol( data: np.ndarray, coordinates: np.ndarray, pe_info: tuple[int, float], + jacobian: bool, hmc_xfm: np.ndarray | None, fmap_hz: np.ndarray, output: np.dtype | np.ndarray | None = None, @@ -282,8 +285,6 @@ def resample_vol( vsm = fmap_hz * pe_info[1] coordinates[pe_info[0], ...] += vsm - jacobian = 1 + np.gradient(vsm, axis=pe_info[0]) - result = ndi.map_coordinates( data, coordinates, @@ -293,7 +294,10 @@ def resample_vol( cval=cval, prefilter=prefilter, ) - result *= jacobian + + if jacobian: + result *= 1 + np.gradient(vsm, axis=pe_info[0]) + return result @@ -301,6 +305,7 @@ async def resample_series_async( data: np.ndarray, coordinates: np.ndarray, pe_info: list[tuple[int, float]], + jacobian: bool, hmc_xfms: list[np.ndarray] | None, fmap_hz: np.ndarray, output_dtype: np.dtype | None = None, @@ -361,6 +366,7 @@ async def resample_series_async( data, coordinates, pe_info[0], + jacobian, hmc_xfms[0] if hmc_xfms else None, fmap_hz, output_dtype, @@ -384,6 +390,7 @@ async def resample_series_async( data=volume, coordinates=coordinates, pe_info=pe_info[volid], + jacobian=jacobian, hmc_xfm=hmc_xfms[volid] if hmc_xfms else None, fmap_hz=fmap_hz, output=out_array[..., volid], @@ -407,6 +414,7 @@ def resample_series( data: np.ndarray, coordinates: np.ndarray, pe_info: list[tuple[int, float]], + jacobian: bool, hmc_xfms: list[np.ndarray] | None, fmap_hz: np.ndarray, output_dtype: np.dtype | None = None, @@ -467,6 +475,7 @@ def resample_series( data=data, coordinates=coordinates, pe_info=pe_info, + jacobian=jacobian, hmc_xfms=hmc_xfms, fmap_hz=fmap_hz, output_dtype=output_dtype, @@ -485,6 +494,7 @@ def resample_image( transforms: nt.TransformChain, fieldmap: nb.Nifti1Image | None, pe_info: list[tuple[int, float]] | None, + jacobian: bool = True, nthreads: int = 1, output_dtype: np.dtype | str | None = 'f4', order: int = 3, @@ -566,6 +576,7 @@ def resample_image( data=source.get_fdata(dtype='f4'), coordinates=mapped_coordinates.T.reshape((3, *target.shape[:3])), pe_info=pe_info, + jacobian=jacobian, hmc_xfms=hmc_xfms, fmap_hz=fieldmap.get_fdata(dtype='f4'), output_dtype=output_dtype, From 3090f68021985e8fe3521fe0bcb49eb1db6520c3 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Fri, 8 Dec 2023 16:40:02 -0500 Subject: [PATCH 3/3] ENH: Add fmap-jacobian to ignore list, thread through workflows --- fmriprep/cli/parser.py | 2 +- fmriprep/workflows/bold/apply.py | 3 ++- fmriprep/workflows/bold/base.py | 3 +++ fmriprep/workflows/bold/fit.py | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/fmriprep/cli/parser.py b/fmriprep/cli/parser.py index 69ac637e4..5da912240 100644 --- a/fmriprep/cli/parser.py +++ b/fmriprep/cli/parser.py @@ -285,7 +285,7 @@ def _slice_time_ref(value, parser): action="store", nargs="+", default=[], - choices=["fieldmaps", "slicetiming", "sbref", "t2w", "flair"], + choices=["fieldmaps", "slicetiming", "sbref", "t2w", "flair", "fmap-jacobian"], help="Ignore selected aspects of the input dataset to disable corresponding " "parts of the workflow (a space delimited list)", ) diff --git a/fmriprep/workflows/bold/apply.py b/fmriprep/workflows/bold/apply.py index 90aecfcbf..c5ff2fd8b 100644 --- a/fmriprep/workflows/bold/apply.py +++ b/fmriprep/workflows/bold/apply.py @@ -16,6 +16,7 @@ def init_bold_volumetric_resample_wf( *, metadata: dict, mem_gb: dict[str, float], + jacobian: bool, fieldmap_id: str | None = None, omp_nthreads: int = 1, name: str = 'bold_volumetric_resample_wf', @@ -123,7 +124,7 @@ def init_bold_volumetric_resample_wf( boldref2target = pe.Node(niu.Merge(2), name='boldref2target', run_without_submitting=True) bold2target = pe.Node(niu.Merge(2), name='bold2target', run_without_submitting=True) resample = pe.Node( - ResampleSeries(), + ResampleSeries(jacobian=jacobian), name="resample", n_procs=omp_nthreads, mem_gb=mem_gb['resampled'], diff --git a/fmriprep/workflows/bold/base.py b/fmriprep/workflows/bold/base.py index a87a7a360..c7289c6d0 100644 --- a/fmriprep/workflows/bold/base.py +++ b/fmriprep/workflows/bold/base.py @@ -380,6 +380,7 @@ def init_bold_wf( fieldmap_id=fieldmap_id if not multiecho else None, omp_nthreads=omp_nthreads, mem_gb=mem_gb, + jacobian='fmap-jacobian' not in config.workflow.ignore, name='bold_anat_wf', ) bold_anat_wf.inputs.inputnode.resolution = "native" @@ -437,6 +438,7 @@ def init_bold_wf( fieldmap_id=fieldmap_id if not multiecho else None, omp_nthreads=omp_nthreads, mem_gb=mem_gb, + jacobian='fmap-jacobian' not in config.workflow.ignore, name='bold_std_wf', ) ds_bold_std_wf = init_ds_volumes_wf( @@ -521,6 +523,7 @@ def init_bold_wf( fieldmap_id=fieldmap_id if not multiecho else None, omp_nthreads=omp_nthreads, mem_gb=mem_gb, + jacobian='fmap-jacobian' not in config.workflow.ignore, name='bold_MNI6_wf', ) diff --git a/fmriprep/workflows/bold/fit.py b/fmriprep/workflows/bold/fit.py index 9c584b7b1..f81285e62 100644 --- a/fmriprep/workflows/bold/fit.py +++ b/fmriprep/workflows/bold/fit.py @@ -838,7 +838,7 @@ def init_bold_native_wf( # Resample to boldref boldref_bold = pe.Node( - ResampleSeries(), + ResampleSeries(jacobian="fmap-jacobian" not in config.workflow.ignore), name="boldref_bold", n_procs=omp_nthreads, mem_gb=mem_gb["resampled"],