Comments (25)
I spent today working through the straightening code. I did find a few things that really look like bugs, but none of them improved the shearing effect we're seeing on the images here. I'll keep looking.
-
In this code, there's a linear algebra mistake: the projection formula used only works when the vectors
self.derivatives[indexes]
are unit-length vectors. But (empirically) the vectorsself.derivatives[indexes]
are not unit-length.
spinalcordtoolbox/spinalcordtoolbox/types.py
Lines 323 to 324 in a7a3f8d
-
In this code, the
centerline_straight
is initialized with a mix of physical space points, and voxel space derivatives. I'm pretty sure the derivatives should also be given in physical space.
spinalcordtoolbox/spinalcordtoolbox/straightening.py
Lines 346 to 357 in a7a3f8d
-
This bit of code for
straight2curved
doesn't match the corresponding code forcurved2straight
. It should almost certainly be usingcenterline_straight.get_inverse_plans_coordinates
instead of doing manual matrix manipulations.
spinalcordtoolbox/spinalcordtoolbox/straightening.py
Lines 481 to 483 in a7a3f8d
from spinalcordtoolbox.
A quick experiment:
Looking at sub-DEV202 and sub-DEV203, which have the same dimensions and very similar (but different) qforms:
- sub-DEV202 looks bijective
- sub-DEV203 shows the problem
- copying the header of sub-DEV202 to sub-DEV203 fixes the problem (looks bijective)
- copying the header of sub-DEV203 to sub-DEV202 introduces the problem
Looking at both versions of sub-DEV202, it looks like the problem shows up when there's a significant forward tilt. I don't know the cause yet, but maybe having the SI axis at a significant angle from vertical creates a problem? I'll look into it.
from spinalcordtoolbox.
I guess this is the same issue with this subject; the vertebral bodies don't align well between the UNI image (blue arrow) and the T1 template after registration (green)
.
PAM50_t1_reg.nii.gz
sub-AM273_UNIT1.nii.gz
[sub-AM273_UNIT1_crop.nii.gz](https://github.com/spinal
sub-AM273_UNIT1_seg.nii.gz
cordtoolbox/spinalcordtoolbox/files/15312748/sub-AM273_UNIT1_crop.nii.gz)
batch_processing_sub-AM273.log
from spinalcordtoolbox.
none of the curve2straight/straight2curve transform pairs are technically bijective, the effect is just much more pronounced for some subjects
Right. Thank you for clarifying this, @joshuacwnewton. This is indeed what I meant.
from spinalcordtoolbox.
Thank you, hope the issue can be solved!
from spinalcordtoolbox.
Input resolution of sub-DEV169Sujet03_T2.nii.gz
is:
pixdim1 0.781250
pixdim2 0.781250
pixdim3 0.800000
NIfTI header
filename sub-DEV169Sujet03_T2.nii.gz
sizeof_hdr 348
data_type INT16
dim0 3
dim1 320
dim2 320
dim3 64
dim4 1
dim5 1
dim6 1
dim7 1
vox_units mm
time_units s
datatype 4
nbyper 2
bitpix 16
pixdim0 -1.000000
pixdim1 0.781250
pixdim2 0.781250
pixdim3 0.800000
pixdim4 1.500000
pixdim5 0.000000
pixdim6 0.000000
pixdim7 0.000000
vox_offset 352
cal_max 0.000000
cal_min 0.000000
scl_slope 1.000000
scl_inter 0.000000
phase_dim 2
freq_dim 1
slice_dim 3
slice_name Unknown
slice_code 0
slice_start 0
slice_end 0
slice_duration 0.000000
toffset 0.000000
intent Unknown
intent_code 0
intent_name
intent_p1 0.000000
intent_p2 0.000000
intent_p3 0.000000
qform_name Scanner Anat
qform_code 1
qto_xyz:1 -0.000000 -0.000000 0.800000 -30.983202
qto_xyz:2 -0.734600 0.265922 -0.000000 65.615944
qto_xyz:3 0.265922 0.734600 0.000000 -223.927170
qto_xyz:4 0.000000 0.000000 0.000000 1.000000
qform_xorient Anterior-to-Posterior
qform_yorient Inferior-to-Superior
qform_zorient Left-to-Right
sform_name Scanner Anat
sform_code 1
sto_xyz:1 0.000000 0.000000 0.800001 -30.983202
sto_xyz:2 -0.734600 0.265922 -0.000000 65.615944
sto_xyz:3 0.265922 0.734600 0.000000 -223.927170
sto_xyz:4 0.000000 0.000000 0.000000 1.000000
sform_xorient Anterior-to-Posterior
sform_yorient Inferior-to-Superior
sform_zorient Left-to-Right
file_type NIFTI-1+
file_code 1
descrip TE=1.3e+02;Time=121014.520;phase=1
aux_file
from spinalcordtoolbox.
Trying with another (longer FOV) file, from the spine-generic project, results are as expected (ie: very similar original image vs. curve2straight2curve):
NIfTI header
filename sub-unf02_T2w.nii.gz
sizeof_hdr 348
data_type FLOAT64
dim0 3
dim1 64
dim2 320
dim3 320
dim4 1
dim5 1
dim6 1
dim7 1
vox_units mm
time_units s
datatype 64
nbyper 8
bitpix 64
pixdim0 1.000000
pixdim1 0.799999
pixdim2 0.800000
pixdim3 0.800000
pixdim4 0.000000
pixdim5 0.000000
pixdim6 0.000000
pixdim7 0.000000
vox_offset 352
cal_max 0.000000
cal_min 0.000000
scl_slope 0.000000
scl_inter 0.000000
phase_dim 2
freq_dim 1
slice_dim 3
slice_name Unknown
slice_code 0
slice_start 0
slice_end 0
slice_duration 0.000000
toffset 0.000000
intent Unknown
intent_code 0
intent_name
intent_p1 0.000000
intent_p2 0.000000
intent_p3 0.000000
qform_name Scanner Anat
qform_code 1
qto_xyz:1 0.799999 -0.000000 0.000000 -24.385565
qto_xyz:2 0.000000 0.800000 0.000000 -122.899323
qto_xyz:3 -0.000000 -0.000000 0.800000 -121.175903
qto_xyz:4 0.000000 0.000000 0.000000 1.000000
qform_xorient Left-to-Right
qform_yorient Posterior-to-Anterior
qform_zorient Inferior-to-Superior
sform_name Scanner Anat
sform_code 1
sto_xyz:1 0.799999 0.000000 0.000000 -24.385565
sto_xyz:2 0.000000 0.800000 0.000000 -122.899323
sto_xyz:3 0.000000 -0.000000 0.800000 -121.175903
sto_xyz:4 0.000000 0.000000 0.000000 1.000000
sform_xorient Left-to-Right
sform_yorient Posterior-to-Anterior
sform_zorient Inferior-to-Superior
file_type NIFTI-1+
file_code 1
descrip TE=1.2e+02;Time=131904.995;phase=1
aux_file
from spinalcordtoolbox.
Trying with another image from Lydia: sub-BB277
: I notice the same issue:
NIfTI header
filename sub-BB277_T2.nii.gz
sizeof_hdr 348
data_type INT16
dim0 3
dim1 320
dim2 320
dim3 64
dim4 1
dim5 1
dim6 1
dim7 1
vox_units mm
time_units s
datatype 4
nbyper 2
bitpix 16
pixdim0 -1.000000
pixdim1 0.781250
pixdim2 0.781250
pixdim3 0.800000
pixdim4 1.500000
pixdim5 0.000000
pixdim6 0.000000
pixdim7 0.000000
vox_offset 352
cal_max 0.000000
cal_min 0.000000
scl_slope 1.000000
scl_inter 0.000000
phase_dim 2
freq_dim 1
slice_dim 3
slice_name Unknown
slice_code 0
slice_start 0
slice_end 0
slice_duration 0.000000
toffset 0.000000
intent Unknown
intent_code 0
intent_name
intent_p1 0.000000
intent_p2 0.000000
intent_p3 0.000000
qform_name Scanner Anat
qform_code 1
qto_xyz:1 0.000000 0.000000 0.800000 -22.308386
qto_xyz:2 -0.762136 0.171755 0.000000 88.849670
qto_xyz:3 0.171755 0.762136 -0.000000 -165.046005
qto_xyz:4 0.000000 0.000000 0.000000 1.000000
qform_xorient Anterior-to-Posterior
qform_yorient Inferior-to-Superior
qform_zorient Left-to-Right
sform_name Scanner Anat
sform_code 1
sto_xyz:1 0.000000 0.000000 0.799999 -22.308386
sto_xyz:2 -0.762136 0.171755 -0.000000 88.849670
sto_xyz:3 0.171755 0.762136 0.000000 -165.046005
sto_xyz:4 0.000000 0.000000 0.000000 1.000000
sform_xorient Anterior-to-Posterior
sform_yorient Inferior-to-Superior
sform_zorient Left-to-Right
file_type NIFTI-1+
file_code 1
descrip TE=1.3e+02;Time=84748.520;phase=1
aux_file
So, is this related to the slightly longer FOV on Lydia's images? Let's try with a bigger FOV from our database
from spinalcordtoolbox.
Another image from PAM50 data (larger FOV) no issue observed:
I think this has to do with the dimension and/or the q/sform. Here's the one for this image
Terminal output
filename sub-amuPAM50005_T1w.nii.gz
sizeof_hdr 348
data_type INT16
dim0 3
dim1 264
dim2 384
dim3 176
dim4 1
dim5 1
dim6 1
dim7 1
vox_units mm
time_units s
datatype 4
nbyper 2
bitpix 16
pixdim0 -1.000000
pixdim1 1.000000
pixdim2 1.000000
pixdim3 1.000000
pixdim4 1.900000
pixdim5 1.000000
pixdim6 1.000000
pixdim7 63136.269531
vox_offset 352
cal_max 0.000000
cal_min 0.000000
scl_slope 1.000000
scl_inter 0.000000
phase_dim 0
freq_dim 0
slice_dim 3
slice_name sequential_increasing
slice_code 1
slice_start 0
slice_end 175
slice_duration 0.000000
toffset 0.000000
intent Unknown
intent_code 0
intent_name
intent_p1 0.000000
intent_p2 0.000000
intent_p3 0.000000
qform_name Scanner Anat
qform_code 1
qto_xyz:1 0.000000 0.000000 1.000000 -86.773605
qto_xyz:2 -1.000000 0.000000 -0.000000 81.023537
qto_xyz:3 0.000000 1.000000 -0.000000 -232.477036
qto_xyz:4 0.000000 0.000000 0.000000 1.000000
qform_xorient Anterior-to-Posterior
qform_yorient Inferior-to-Superior
qform_zorient Left-to-Right
sform_name Scanner Anat
sform_code 1
sto_xyz:1 0.000000 0.000000 1.000000 -86.773605
sto_xyz:2 -1.000000 0.000000 0.000000 81.023537
sto_xyz:3 0.000000 1.000000 0.000000 -232.477036
sto_xyz:4 0.000000 0.000000 0.000000 1.000000
sform_xorient Anterior-to-Posterior
sform_yorient Inferior-to-Superior
sform_zorient Left-to-Right
file_type NIFTI-1+
file_code 1
descrip TE=3.019999981;sec=63136.2700;phaseDir=+
aux_file
from spinalcordtoolbox.
Resampled our internal image to the dimension of the image from Lydia, but it did not reproduce the issue:
sct_resample -i sub-unf02_T2w.nii.gz -mm 0.78x0.78x0.8
sct_deepseg -i sub-unf02_T2w_r.nii.gz -task seg_sc_contrast_agnostic
sct_straighten_spinalcord -i sub-unf02_T2w_r.nii.gz -s sub-unf02_T2w_r_seg.nii.gz
sct_apply_transfo -i sub-unf02_T2w_r_straight.nii.gz -d sub-unf02_T2w_r.nii.gz -w warp_straight2curve.nii.gz
from spinalcordtoolbox.
tagging @benjamindeleener who implemented the method-- maybe he has some insights
from spinalcordtoolbox.
(Quick sanity check: Installed SCT v5.0.0, and this behavior persists. So, I don't think it's been caused by any of the small tweaks/refactors to straightening since 2020.)
As another way of visualizing the problem: I tested the following command on the DEV202/DEV203 subjects highlighted by @mguaypaq's #4477 (comment):
sct_concat_transfo -d {input_img} -w warp_curve2straight.nii.gz warp_straight2curve.nii.gz
This produces a concatenated warping field that can be directly applied to the input image to reproduce the "sheared" results. If I open the concatenated warp_final
in FSLeyes and set the brightness/contrast to -0.5
/0.5
minmax with a divergent colormap, I get:
(Left: DEV203, Right: DEV202)
DEV203 is much more extreme, but DEV202 still shows visible +/- shifts, indicated by the blue and red patterns. So, I reckon that whatever the issue is, the affected subjects are just the extreme versions of the behavior that already exists. In other words, none of the curve2straight/straight2curve transform pairs are technically bijective, the effect is just much more pronounced for some subjects.
(Maybe this is stating something that was already apparent? But, I thought it would be helpful to potentially reframe the problem as "behavior inherent to sct_straighten_spinalcord
's algorithm" rather than "bug that is completely separate from the normal behavior". Meaning, there may not be a smoking gun that we can find here.)
from spinalcordtoolbox.
(Quick sanity check: Installed SCT v5.0.0, and this behavior persists. So, I don't think it's been caused by any of the small tweaks/refactors to straightening since 2020.)
Great! I was wondering this actually. Thank you for checking
from spinalcordtoolbox.
Hi, any updates on this issue?
from spinalcordtoolbox.
Hi, any updates on this issue?
We discussed this in our most recent SCT dev meeting (2024-05-15), and we came to the conclusion that debugging this issue would require a deeper understanding of the underlying straightening code (most likely this transform step of the overall algorithm).
Fully understanding the underlying code may take some time, as the person who is looking into this issue (@mguaypaq) is a different person than the person who originally developed this method some years ago (@benjamindeleener).
Note
Benjamin did share some thoughts in our internal Slack, which I can copy to this issue since Benjamin is currently locked out of his GitHub account:
@benjamindeleener: To give some insights, straightening does not produce a bijective transformation. The script computes the two transformations by calculating them two times. The issue was known originally (I believe it is mentioned in the manuscript), but the results should be very close in most cases. We assumed it would not be a problem in the future. It is possible to transform the method to produce a bijective transformation but it may require some time, mainly because of edge issues (the problem is an ill-posed problem without regularization when calculating the transformation far from the centerline.
@jcohenadad: for some reasons, some subjects are waaaaaaay less bijective than others. This is documented in the issue, with some examples. In some cases, depending on the q/form it seems (Mathieu did some tests), there is an abnormal shearing that is being applied on the transformation matrix. This is very strange, and i was wondering if you had some ideas about the cause for it
from spinalcordtoolbox.
Related Issues (20)
- Debian Rolling Release CI runs are failing due to `libglib2.0-0` dependency installation
- Integration of EPI segmentation nnUNet model in SCT HOT 3
- Outdated Node.js 16 action present in `automate-changelog-PR.yml` HOT 1
- What colormap should be used for soft segmentation QCs? (single color vs. gradient) HOT 15
- Sagittal mosaic QC report is tiny for 1.0mm istropic image with 75 slices HOT 5
- Running SCT commands in 3DSlicer GUI? HOT 3
- Fix issues with `sct_deepseg` rootlets QC report HOT 1
- Should we issue certificates for the SCT course?
- Indicate versions of `sct_deepseg` models HOT 5
- `Keyword=CombinedLabels` incompatible with `combine=1`
- pytest issue `assert not changed` and how to run in IDE HOT 3
- Custom argparse formatter fails for blank lines in multiline strings HOT 2
- Usage of `sct_label_utils -disc <file>` is unclear
- Project discs orthogonally to the spinal cord segmentation or centerline
- viewer syntax at the end does not provide correct output file name HOT 1
- Add postprocessing functionality for the new monai/nnunet models
- qc report to display manual segmentation HOT 6
- Lesion mask not properly overlaid HOT 3
- Dipy denoising functions are duplicated between `sct_maths` and `sct_denoising_onlm`/`sct_dmri_denoise_patch2self`
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from spinalcordtoolbox.