Skip to content

Conversation

@oesteban
Copy link
Member

@oesteban oesteban commented Nov 13, 2025

Summary

  • switch the DWI data structure and serialization helpers to use row-major (N×C) gradient tables
  • update diffusion models, shell-selection utilities, and unit tests to follow the new layout
  • refresh usage documentation and the data-structures notebook to describe the row-major convention

Testing

  • pytest test/test_filtering.py::test_dwi_select_shells -q (fails: ModuleNotFoundError: nifreeze._version)

Codex Task

Fixes #316.

@codecov
Copy link

codecov bot commented Nov 13, 2025

Codecov Report

❌ Patch coverage is 59.37500% with 26 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.27%. Comparing base (e15d600) to head (9dbe77a).
⚠️ Report is 9 commits behind head on main.

Files with missing lines Patch % Lines
src/nifreeze/data/dmri.py 56.86% 12 Missing and 10 partials ⚠️
src/nifreeze/model/_dipy.py 63.63% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #325      +/-   ##
==========================================
- Coverage   77.01%   76.27%   -0.74%     
==========================================
  Files          28       28              
  Lines        1775     1821      +46     
  Branches      177      193      +16     
==========================================
+ Hits         1367     1389      +22     
- Misses        348      361      +13     
- Partials       60       71      +11     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@oesteban oesteban requested a review from jhlegarreta November 13, 2025 17:50
@oesteban
Copy link
Member Author

In reviewing this codex-generated PR, I've remembered why we chose the fsl convention (column major): to make it consistent with the NIfTI order of axes (i.e., orientation indexed by the last axis). Not that we need to keep the fsl convention, but good to mention. cc/ @jhlegarreta @arokem

@arokem
Copy link
Contributor

arokem commented Nov 13, 2025 via email

raise ValueError("Gradient table must be a 2D array")

n_volumes = None
if self.dataobj is not None:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jhlegarreta I think we disallowed this right (dataobj to be None)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not fully yet: see #302 and PR #305.

Copy link
Contributor

@jhlegarreta jhlegarreta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In reviewing this codex-generated PR, I've remembered why we chose the fsl convention (column major): to make it consistent with the NIfTI order of axes (i.e., orientation indexed by the last axis). Not that we need to keep the fsl convention, but good to mention. cc/ @jhlegarreta @arokem

👍 Makes sense.

I still think that we should keep the row major convention, because
modeling that uses the gradients (e.g., DTI) more naturally thinks of this
as a matrix of n_directions by 4.

I am fine with whatever convention is most convenient internally; have not revisited since some time how GPR likes things vs how DIPY likes them.

This PR seems to do a good job documenting the dimensionality expected and checks pass. If we revisit this in the future, hopefully we will be in a better position to weigh in advantages/drawbacks or things that do not work smoothly and change the internal convention if necessary.

I have left a minor suggestion: we only have a pre-release, so we are not forced to respect the API or to refer to previous versions.

Co-authored-by: Jon Haitz Legarreta Gorroño <[email protected]>
@oesteban oesteban merged commit 359b03b into main Nov 14, 2025
9 of 11 checks passed
@oesteban oesteban deleted the codex/analyze-and-report-gradient-data-update-points branch November 14, 2025 08:19
jhlegarreta added a commit to jhlegarreta/nifreeze that referenced this pull request Nov 17, 2025
Prefer colon over ellipsis to index remaining gradient dimension:
gradients can only be two-dimensional arrays.

Cross-reference nipreps#325.
jhlegarreta added a commit to jhlegarreta/nifreeze that referenced this pull request Nov 17, 2025
Refactor gradient data checks in DWI data class: PR
nipreps#325 introduced the row-major
convention for gradient data in NiFreeze. However, gradient loading was
not tested thoroughly. This resulted in some execution flows that would
not guarantee a row-major internal convention or would crash under some
circumstances.

This commit refactors the gradient data checks and adds thorough
testing:
- Define all error or warning messages as global variables so that they
  can be checked exactly in tests.
- Ensure that gradients conform to the row-major convention when
  instantiating the DWI class directly. This allows to separate the
  gradient reformatting from the dimensionality check with the DWI
  volume sequence. This simplifies the flow, as the gradient
  reformatting to the row-major convention does not depend on the number
  of volumes in the DWI sequence. Also, this makes the flow more
  consistent with the refactored checks of the NIfTI file-based loading
  utility function (`from_nii`).
- Ensure that the gradients conform to the row-major convention
  immediately after loading the gradients file in the NIfTI file-based
  loading utility function (`from_nii`). As opposed to the previous
  implementation, this allows to load the gradients from a file where
  data follows either column-major or row-major convention. e.g. In the
  previous implementation the `if grad.shape[1] < 2:` was making an
  assumption about the layout and/or one that was wrong because we
  require 4 columns (direction (x,y,z) + b-value) or rows (if in
  column-major). The new implementation simplifies the execution flow.
jhlegarreta added a commit to jhlegarreta/nifreeze that referenced this pull request Nov 17, 2025
Refactor gradient data checks in DWI data class: PR
nipreps#325 introduced the row-major
convention for gradient data in NiFreeze. However, gradient loading was
not tested thoroughly. This resulted in some execution flows that would
not guarantee a row-major internal convention or would crash under some
circumstances.

This commit refactors the gradient data checks and adds thorough
testing:
- Define all error or warning messages as global variables so that they
  can be checked exactly in tests.
- Ensure that gradients conform to the row-major convention when
  instantiating the DWI class directly. This allows to separate the
  gradient reformatting from the dimensionality check with the DWI
  volume sequence. This simplifies the flow, as the gradient
  reformatting to the row-major convention does not depend on the number
  of volumes in the DWI sequence. Also, this makes the flow more
  consistent with the refactored checks of the NIfTI file-based loading
  utility function (`from_nii`).
- Ensure that the gradients conform to the row-major convention
  immediately after loading the gradients file in the NIfTI file-based
  loading utility function (`from_nii`). As opposed to the previous
  implementation, this allows to load the gradients from a file where
  data follows either column-major or row-major convention. e.g. In the
  previous implementation the `if grad.shape[1] < 2:` was making an
  assumption about the layout and/or one that was wrong because we
  require 4 columns (direction (x,y,z) + b-value) or rows (if in
  column-major). The new implementation simplifies the execution flow.
jhlegarreta added a commit to jhlegarreta/nifreeze that referenced this pull request Nov 17, 2025
Refactor gradient data checks in DWI data class: PR
nipreps#325 introduced the row-major
convention for gradient data in NiFreeze. However, gradient loading was
not tested thoroughly. This resulted in some execution flows that would
not guarantee a row-major internal convention or would crash under some
circumstances.

This commit refactors the gradient data checks and adds thorough
testing:
- Define all error or warning messages as global variables so that they
  can be checked exactly in tests.
- Ensure that gradients conform to the row-major convention when
  instantiating the DWI class directly. This allows to separate the
  gradient reformatting from the dimensionality check with the DWI
  volume sequence. This simplifies the flow, as the gradient
  reformatting to the row-major convention does not depend on the number
  of volumes in the DWI sequence. Also, this makes the flow more
  consistent with the refactored checks of the NIfTI file-based loading
  utility function (`from_nii`).
- Ensure that the gradients conform to the row-major convention
  immediately after loading the gradients file in the NIfTI file-based
  loading utility function (`from_nii`). As opposed to the previous
  implementation, this allows to load the gradients from a file where
  data follows either column-major or row-major convention. e.g. In the
  previous implementation the `if grad.shape[1] < 2:` was making an
  assumption about the layout and/or one that was wrong because we
  require 4 columns (direction (x,y,z) + b-value) or rows (if in
  column-major). The new implementation simplifies the execution flow.
jhlegarreta added a commit to jhlegarreta/nifreeze that referenced this pull request Nov 17, 2025
Refactor gradient data checks in DWI data class: PR
nipreps#325 introduced the row-major
convention for gradient data in NiFreeze. However, gradient loading was
not tested thoroughly. This resulted in some execution flows that would
not guarantee a row-major internal convention or would crash under some
circumstances.

This commit refactors the gradient data checks and adds thorough
testing:
- Define all error or warning messages as global variables so that they
  can be checked exactly in tests.
- Ensure that gradients conform to the row-major convention when
  instantiating the DWI class directly. This allows to separate the
  gradient reformatting from the dimensionality check with the DWI
  volume sequence. This simplifies the flow, as the gradient
  reformatting to the row-major convention does not depend on the number
  of volumes in the DWI sequence. Also, this makes the flow more
  consistent with the refactored checks of the NIfTI file-based loading
  utility function (`from_nii`).
- Ensure that the gradients conform to the row-major convention
  immediately after loading the gradients file in the NIfTI file-based
  loading utility function (`from_nii`). As opposed to the previous
  implementation, this allows to load the gradients from a file where
  data follows either column-major or row-major convention. e.g. In the
  previous implementation the `if grad.shape[1] < 2:` was making an
  assumption about the layout and/or one that was wrong because we
  require 4 columns (direction (x,y,z) + b-value) or rows (if in
  column-major). The new implementation simplifies the execution flow.
jhlegarreta added a commit to jhlegarreta/nifreeze that referenced this pull request Nov 20, 2025
Refactor gradient data checks in DWI data class: PR
nipreps#325 introduced the row-major
convention for gradient data in NiFreeze. However, gradient loading was
not tested thoroughly. This resulted in some execution flows that would
not guarantee a row-major internal convention or would crash under some
circumstances.

This commit refactors the gradient data checks and adds thorough
testing:
- Define all error or warning messages as global variables so that they
  can be checked exactly in tests.
- Ensure that gradients conform to the row-major convention when
  instantiating the DWI class directly. This allows to separate the
  gradient reformatting from the dimensionality check with the DWI
  volume sequence. This simplifies the flow, as the gradient
  reformatting to the row-major convention does not depend on the number
  of volumes in the DWI sequence. Also, this makes the flow more
  consistent with the refactored checks of the NIfTI file-based loading
  utility function (`from_nii`).
- Ensure that the gradients conform to the row-major convention
  immediately after loading the gradients file in the NIfTI file-based
  loading utility function (`from_nii`). As opposed to the previous
  implementation, this allows to load the gradients from a file where
  data follows either column-major or row-major convention. e.g. In the
  previous implementation the `if grad.shape[1] < 2:` was making an
  assumption about the layout and/or one that was wrong because we
  require 4 columns (direction (x,y,z) + b-value) or rows (if in
  column-major). The new implementation simplifies the execution flow.
jhlegarreta added a commit to jhlegarreta/nifreeze that referenced this pull request Nov 21, 2025
Refactor gradient data checks in DWI data class: PR
nipreps#325 introduced the row-major
convention for gradient data in NiFreeze. However, gradient loading was
not tested thoroughly. This resulted in some execution flows that would
not guarantee a row-major internal convention or would crash under some
circumstances.

This commit refactors the gradient data checks and adds thorough
testing:
- Define all error or warning messages as global variables so that they
  can be checked exactly in tests.
- Ensure that gradients conform to the row-major convention when
  instantiating the DWI class directly. This allows to separate the
  gradient reformatting from the dimensionality check with the DWI
  volume sequence. This simplifies the flow, as the gradient
  reformatting to the row-major convention does not depend on the number
  of volumes in the DWI sequence. Also, this makes the flow more
  consistent with the refactored checks of the NIfTI file-based loading
  utility function (`from_nii`).
- Ensure that the gradients conform to the row-major convention
  immediately after loading the gradients file in the NIfTI file-based
  loading utility function (`from_nii`). As opposed to the previous
  implementation, this allows to load the gradients from a file where
  data follows either column-major or row-major convention. e.g. In the
  previous implementation the `if grad.shape[1] < 2:` was making an
  assumption about the layout and/or one that was wrong because we
  require 4 columns (direction (x,y,z) + b-value) or rows (if in
  column-major). The new implementation simplifies the execution flow.
jhlegarreta added a commit to jhlegarreta/nifreeze that referenced this pull request Nov 21, 2025
Refactor gradient data checks in DWI data class: PR
nipreps#325 introduced the row-major
convention for gradient data in NiFreeze. However, gradient loading was
not tested thoroughly. This resulted in some execution flows that would
not guarantee a row-major internal convention or would crash under some
circumstances.

This commit refactors the gradient data checks and adds thorough
testing:
- Define all error or warning messages as global variables so that they
  can be checked exactly in tests.
- Ensure that gradients conform to the row-major convention when
  instantiating the DWI class directly. This allows to separate the
  gradient reformatting from the dimensionality check with the DWI
  volume sequence. This simplifies the flow, as the gradient
  reformatting to the row-major convention does not depend on the number
  of volumes in the DWI sequence. Also, this makes the flow more
  consistent with the refactored checks of the NIfTI file-based loading
  utility function (`from_nii`).
- Ensure that the gradients conform to the row-major convention
  immediately after loading the gradients file in the NIfTI file-based
  loading utility function (`from_nii`). As opposed to the previous
  implementation, this allows to load the gradients from a file where
  data follows either column-major or row-major convention. e.g. In the
  previous implementation the `if grad.shape[1] < 2:` was making an
  assumption about the layout and/or one that was wrong because we
  require 4 columns (direction (x,y,z) + b-value) or rows (if in
  column-major). The new implementation simplifies the execution flow.
jhlegarreta added a commit to jhlegarreta/nifreeze that referenced this pull request Nov 22, 2025
Refactor gradient data checks in DWI data class: PR
nipreps#325 introduced the row-major
convention for gradient data in NiFreeze. However, gradient loading was
not tested thoroughly. This resulted in some execution flows that would
not guarantee a row-major internal convention or would crash under some
circumstances.

This commit refactors the gradient data checks and adds thorough
testing:
- Define all error or warning messages as global variables so that they
  can be checked exactly in tests.
- Ensure that gradients conform to the row-major convention when
  instantiating the DWI class directly. This allows to separate the
  gradient reformatting from the dimensionality check with the DWI
  volume sequence. This simplifies the flow, as the gradient
  reformatting to the row-major convention does not depend on the number
  of volumes in the DWI sequence. Also, this makes the flow more
  consistent with the refactored checks of the NIfTI file-based loading
  utility function (`from_nii`).
- Ensure that the gradients conform to the row-major convention
  immediately after loading the gradients file in the NIfTI file-based
  loading utility function (`from_nii`). As opposed to the previous
  implementation, this allows to load the gradients from a file where
  data follows either column-major or row-major convention. e.g. In the
  previous implementation the `if grad.shape[1] < 2:` was making an
  assumption about the layout and/or one that was wrong because we
  require 4 columns (direction (x,y,z) + b-value) or rows (if in
  column-major). The new implementation simplifies the execution flow.
jhlegarreta added a commit to jhlegarreta/nifreeze that referenced this pull request Nov 22, 2025
Refactor gradient data checks in DWI data class: PR
nipreps#325 introduced the row-major
convention for gradient data in NiFreeze. However, gradient loading was
not tested thoroughly. This resulted in some execution flows that would
not guarantee a row-major internal convention or would crash under some
circumstances.

This commit refactors the gradient data checks and adds thorough
testing:
- Define all error or warning messages as global variables so that they
  can be checked exactly in tests.
- Ensure that gradients conform to the row-major convention when
  instantiating the DWI class directly. This allows to separate the
  gradient reformatting from the dimensionality check with the DWI
  volume sequence. This simplifies the flow, as the gradient
  reformatting to the row-major convention does not depend on the number
  of volumes in the DWI sequence. Also, this makes the flow more
  consistent with the refactored checks of the NIfTI file-based loading
  utility function (`from_nii`).
- Ensure that the gradients conform to the row-major convention
  immediately after loading the gradients file in the NIfTI file-based
  loading utility function (`from_nii`). As opposed to the previous
  implementation, this allows to load the gradients from a file where
  data follows either column-major or row-major convention. e.g. In the
  previous implementation the `if grad.shape[1] < 2:` was making an
  assumption about the layout and/or one that was wrong because we
  require 4 columns (direction (x,y,z) + b-value) or rows (if in
  column-major). The new implementation simplifies the execution flow.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dMRI gradient data implementation is inconsistent

4 participants