Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dwicat: Support different voxel grids #2702

Merged
merged 12 commits into from
Feb 28, 2024
Merged

dwicat: Support different voxel grids #2702

merged 12 commits into from
Feb 28, 2024

Conversation

Lestropie
Copy link
Member

Follows discussion in #1741.

Relates to question in #2697. Got around the uncertainty there by essentially preserving the current behaviour and implementing alternatives alongside them.

Needed to implement this to facilitate processing of a minority of session data coming through the lab, where series with opposing phase encoding directions aren't always on precisely the same voxel grid, but voxel spacings and axis dimensions are identical.

Plan is to use this to resolve bids-apps/MRtrix3_connectome#123.

1203d74 has an extensive description of changes.

I can't say that for DWI series with different voxel sizes this is 100% the best way to proceed, but I can at least say that it would proceed.

The dwicat script now serves two key purposes. In addition to estimating a global intensity shift between two or more series based on the aggregate b=0 intensity, it will now also interrogate the voxel grids of the input images, and decide how best to combine those data; whether it be straight concatenation, rigid-body transformation to a central unbiased header, or resampling all data onto a new common voxel grid if necessary.
Other changes to facilitate this / made in the process:
- dwicat new command-line option -nointensity to disable the intensity matching functionality of the script.
- mraverageheader: -resolution command-line option removed, and replaced with -spacing. There are now four options to choose from rather than two, and "resolution" was no longer the appropriate term to disambiguate them / describe the mechanism. In particular, the ability to set the voxel spacings based on either the minimum or mean of the input image axes closest to the average header axes, means that in the scenario where one has two DWI series with the same voxel spacing but different affine transforms, one can calculate an average voxel grid that lies between the two input voxel grids but has precisely the same voxel spacing, such that it is not necessary to perform interpolation to get the data from both series onto that common grid.
- transformcalc: Tweaked example description of "header" function.
Axes::get_permutation_to_make_axial(): Renamed to get_shuffle_to_make_axial() as the result is not constrained to axis permutations only, and also broke calculation of specifically the permutations into its own function as that could be used for the new functionalities in mraverageheader.
This change is necessary for dwicat to process successfully in the scenario where inputs must be conformed to a new average voxel grid, but one of the input series happens to contain a number of volumes corresponding to a spherical harmonic series.
@Lestropie
Copy link
Member Author

Something I failed to previously report explicitly here:

Because the default behaviour of mraverageheader is being altered (mean of the voxel spacings of the nearest axes, rather than the mean projected spacing), the behaviour of population_template will also change in the scenario where the desired voxel spacing of the template image is not specified.
I have a suspicion that many have been explicitly specifying their desired voxel size specifically because mraverageheader was producing template images with voxel spacings not quite identical to their input data. Therefore I would view this as a beneficial change, even if it wasn't the original target. It is nevertheless a change that needs to be reported.

Conflicts:
	cmd/mraverageheader.cpp
	core/math/average_space.cpp
	core/math/average_space.h
@Lestropie
Copy link
Member Author

  • Add test with input data on different voxel grids that causes dwicat to fail, but succeeds with PR changes.
  • Investigate determination of centre of FoV
    (A quick test just now suggests that the centre of the output FoV is dominated by the location of the first image, rather than the mean of all images)

github-actions[bot]

This comment was marked as outdated.

@Lestropie Lestropie added this to the 3.1.0 updates milestone Feb 27, 2024
github-actions[bot]

This comment was marked as outdated.

@Lestropie
Copy link
Member Author

Not part of tests, but showcasing mraverageheader modifications on script test data:

Inputs:

************************************************
Image name:          "BIDS/sub-01/anat/sub-01_T1w.nii.gz"
************************************************
  Dimensions:        96 x 128 x 128
  Voxel size:        1.8 x 1.875 x 1.875
  Data strides:      [ 1 2 3 ]
  Format:            NIfTI-1.1 (GZip compressed)
  Data type:         32 bit float (little endian)
  Intensity scaling: offset = 0, multiplier = 1
  Transform:               0.9994    -0.02016     0.02959      -86.45
                          0.02067      0.9996    -0.01723      -131.3
                         -0.02923     0.01784      0.9994      -144.6
  comments:          untitled
  mrtrix_version:    3.0_RC3-419-g3b7533ba-dirty
************************************************
Image name:          "BIDS/sub-01/dwi/sub-01_dwi.nii.gz"
************************************************
  Dimensions:        28 x 39 x 30 x 104
  Voxel size:        5 x 4.9359 x 5 x 1
  Data strides:      [ 1 2 3 4 ]
  Format:            NIfTI-1.1 (GZip compressed)
  Data type:         32 bit float (little endian)
  Intensity scaling: offset = 0, multiplier = 1
  Transform:               0.9996   7.793e-05     0.02957      -70.87
                         0.002244      0.9969    -0.07846      -110.5
                         -0.02949     0.07849      0.9965         -81
  comments:          5.0.11
  mrtrix_version:    3.0_RC3-419-g3b7533ba-dirty

Outputs:

************************************************
Image name:          "mean_nearest.mif"
************************************************
  Dimensions:        52 x 73 x 72
  Voxel size:        3.4 x 3.40545 x 3.4375
  Data strides:      [ 1 2 3 ]
  Format:            MRtrix
  Data type:         bitwise
  Intensity scaling: offset = 0, multiplier = 1
  Transform:               0.9995    -0.01004     0.02973      -88.87
                          0.01146      0.9988    -0.04787        -131
                         -0.02922     0.04819      0.9984      -151.9
  command_history:   /home/unimelb.edu.au/robertes/src/mrtrix3/build_cmake/bin/mraverageheader BIDS/sub-01/anat/sub-01_T1w.nii.gz BIDS/sub-01/dwi/sub-01_dwi.nii.gz mraverageheader/mean_nearest.mif  (version=3.0.4-623-g4f3836b9-dirty)
  mrtrix_version:    3.0.4-623-g4f3836b9-dirty
************************************************
Image name:          "mean_projection.mif"
************************************************
  Dimensions:        51 x 71 x 70
  Voxel size:        3.43203 x 3.53943 x 3.54253
  Data strides:      [ 1 2 3 ]
  Format:            MRtrix
  Data type:         bitwise
  Intensity scaling: offset = 0, multiplier = 1
  Transform:               0.9995    -0.01004     0.02973      -88.87
                          0.01146      0.9988    -0.04787        -131
                         -0.02922     0.04819      0.9984      -151.9
  command_history:   /home/unimelb.edu.au/robertes/src/mrtrix3/build_cmake/bin/mraverageheader BIDS/sub-01/anat/sub-01_T1w.nii.gz BIDS/sub-01/dwi/sub-01_dwi.nii.gz -spacing mean_projection mraverageheader/mean_projection.mif  (version=3.0.4-623-g4f3836b9-dirty)
  mrtrix_version:    3.0.4-623-g4f3836b9-dirty
************************************************
Image name:          "min_nearest.mif"
************************************************
  Dimensions:        97 x 133 x 132
  Voxel size:        1.8 x 1.875 x 1.875
  Data strides:      [ 1 2 3 ]
  Format:            MRtrix
  Data type:         bitwise
  Intensity scaling: offset = 0, multiplier = 1
  Transform:               0.9995    -0.01004     0.02973      -88.87
                          0.01146      0.9988    -0.04787        -131
                         -0.02922     0.04819      0.9984      -151.9
  command_history:   /home/unimelb.edu.au/robertes/src/mrtrix3/build_cmake/bin/mraverageheader BIDS/sub-01/anat/sub-01_T1w.nii.gz BIDS/sub-01/dwi/sub-01_dwi.nii.gz -spacing min_nearest mraverageheader/min_nearest.mif  (version=3.0.4-623-g4f3836b9-dirty)
  mrtrix_version:    3.0.4-623-g4f3836b9-dirty
************************************************
Image name:          "min_projection.mif"
************************************************
  Dimensions:        97 x 133 x 132
  Voxel size:        1.79992 x 1.87404 x 1.87412
  Data strides:      [ 1 2 3 ]
  Format:            MRtrix
  Data type:         bitwise
  Intensity scaling: offset = 0, multiplier = 1
  Transform:               0.9995    -0.01004     0.02973      -88.87
                          0.01146      0.9988    -0.04787        -131
                         -0.02922     0.04819      0.9984      -151.9
  command_history:   /home/unimelb.edu.au/robertes/src/mrtrix3/build_cmake/bin/mraverageheader BIDS/sub-01/anat/sub-01_T1w.nii.gz BIDS/sub-01/dwi/sub-01_dwi.nii.gz -spacing min_projection mraverageheader/min_projection.mif  (version=3.0.4-623-g4f3836b9-dirty)
  mrtrix_version:    3.0.4-623-g4f3836b9-dirty

Note that "-spacing min_projection" and "-spacing mean_projection" correspond to the former "-resolution max" and "-resolution mean" (the new mraverageheader test data shows that the verification outputs for both of these variants were generated from 3.0.4 code).

@Lestropie Lestropie force-pushed the dwicat_varying_grids branch from a57cdcc to 479187e Compare February 28, 2024 01:54
github-actions[bot]

This comment was marked as resolved.

Lestropie added a commit that referenced this pull request Feb 28, 2024
This change reverts mraverageheader to use the method now referred to as "mean_projection", which was the default behaviour prior to #2702.
Scripts dwicat and population_template explicitly request the "mean_nearest" method where deemed appropriate.
Tests for mraverageheader updated to reflect change in default behaviour.
Lestropie added a commit that referenced this pull request Feb 28, 2024
This change reverts mraverageheader to use the method now referred to as "mean_projection", which was the default behaviour prior to #2702.
Scripts dwicat and population_template explicitly request the "mean_nearest" method where deemed appropriate.
Tests for mraverageheader updated to reflect change in default behaviour.
@Lestropie Lestropie force-pushed the dwicat_varying_grids branch from 9be5337 to d686ba1 Compare February 28, 2024 03:46
@Lestropie
Copy link
Member Author

There was a trap here that is resolved in 9be5337.

Before that, I had altered the default behaviour of average header calculation, such that the outcomes of mraverageheader would change in both dwicat and population_template. However the same code is also used by mrregister, and so that change resulted in a lot of mrregister tests failing. In trying to finally tie this one off, I have reverted the default behaviour of that average header calculation, which will be reflected in both mrregister operation and mraverageheader default behaviour; dwicat and population_template instead explicitly request the mechanism that is IMO more appropriate in those scenarios.

There's an argument to be made about the generation of unbiased midway spaces in mrregister using this new spacing calculation rather than the legacy one. But I'm at the point now where I'd prefer to defer that. I don't have the background in registration to be making an informed call. The changes for dwicat and population_template are out of necessity in the former case, and to produce user-intuitive outcomes in the latter case (ie. generating a template from all 2mm isotropic input images should produce a 2mm isotropic template).

This change reverts mraverageheader to use the method now referred to as "mean_projection", which was the default behaviour prior to #2702.
Scripts dwicat and population_template explicitly request the "mean_nearest" method where deemed appropriate.
Tests for mraverageheader updated to reflect change in default behaviour.
Script was erroneously triggering the use of rigid body average header generation due to the input series containing different numbers of volumes.
@Lestropie Lestropie force-pushed the dwicat_varying_grids branch from d686ba1 to 7ed618e Compare February 28, 2024 04:04
@Lestropie Lestropie merged commit 3561d27 into dev Feb 28, 2024
6 checks passed
@Lestropie Lestropie deleted the dwicat_varying_grids branch February 28, 2024 06:57
@Lestropie
Copy link
Member Author

Both test data repositories have been updated such that the dev branch points to the same SHA1 as the dev branch of this repository now points to, and the corresponding feature branches in the test data repositories have been deleted.

Lestropie added a commit that referenced this pull request Feb 28, 2024
Updates chages in #2702 to fit with #2678.
Lestropie added a commit that referenced this pull request Mar 4, 2024
Failed to properly resolve #2702 against #2839.
Lestropie added a commit that referenced this pull request Mar 4, 2024
Failed to properly resolve #2702 against #2839.
@Lestropie Lestropie mentioned this pull request May 8, 2024
9 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant