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

dwifslpreproc: MIF files don't retain gradient table #2577

Closed
araikes opened this issue Jan 31, 2023 · 24 comments
Closed

dwifslpreproc: MIF files don't retain gradient table #2577

araikes opened this issue Jan 31, 2023 · 24 comments

Comments

@araikes
Copy link

araikes commented Jan 31, 2023

I have data that I've processed (successfully) using v 3.0.3. The data is converted to MIF with the gradient table and passed to dwifslpreproc and then dwibiascorrect without issue. I upgraded to 3.0.4 and get an error that there is no gradient table in eddy_corrected.mif. I tried using dwifslpreproc ... -export_grad_fsl ... in order to export the gradient table but it also throws and error about the table being missing. This appears to be unique to v. 3.0.4

@araikes araikes added the bug label Jan 31, 2023
@jdtournier
Copy link
Member

Ouch, that doesn't sound good...

Can you provide the exact commands that cause the issue? And if possible, run dwifslpreproc with the -debug and -nocleanup options, so we can inspect exactly what's going on at every stage of the process?

@araikes
Copy link
Author

araikes commented Jan 31, 2023

Log file attached. Let me know how you want the folder from -nocleanup. Note: this is a mouse, hence some the options.

Input file:

************************************************
Image name:          "unringed.mif.gz"
************************************************
  Dimensions:        64 x 128 x 64 x 102
  Voxel size:        0.2 x 0.2 x 0.2 x 1
  Data strides:      [ 1 2 3 4 ]
  Format:            MRtrix (GZip compressed)
  Data type:         32 bit float (little endian)
  Intensity scaling: offset = 0, multiplier = 1
  Transform:                    1   -0.007121   2.553e-08       -7.62
                         0.007121           1  -7.171e-06      -12.65
                        2.553e-08   7.171e-06           1      -1.544
  command_history:   mrconvert unringed.nii.gz unringed.mif.gz -fslgrad bvecs bvals  (version=3.0.4)
  comments:          untitled
  dw_scheme:         0,0,0,19.50365589
  [102 entries]      0,0,0,19.50365589
                     ...
                     -0.06252636476,0.8446384465,-0.5316731594,3006.220658
                     -0.9674016712,-0.09727114581,0.233821151,3003.228201
  mrtrix_version:    3.0.4

Command:
dwifslpreproc unringed.mif.gz eddy_tmp.mif.gz -rpe_none -pe_dir IS -readout_time 0.1 -eddyqc_all eddy_tmp -eddy_options ' --slm=linear --repol' -nthreads 12 -debug -nocleanup

Output:

************************************************
Image name:          "eddy_tmp.mif.gz"
************************************************
  Dimensions:        64 x 128 x 64 x 102
  Voxel size:        0.2 x 0.2 x 0.2 x 1
  Data strides:      [ 1 2 3 4 ]
  Format:            MRtrix (GZip compressed)
  Data type:         32 bit float (little endian)
  Intensity scaling: offset = 0, multiplier = 1
  Transform:                    1   -0.007121   2.553e-08       -7.62
                         0.007121           1  -7.171e-06      -12.65
                        2.553e-08   7.171e-06           1      -1.544
  command_history:   mrconvert unringed.nii.gz unringed.mif.gz -fslgrad bvecs bvals  (version=3.0.4)
                     /opt/miniconda-latest/bin/dwifslpreproc unringed.mif.gz eddy_tmp.mif.gz -rpe_none -pe_dir IS -readout_time 0.1 -eddyqc_all eddy_tmp -eddy_options ' --slm=linear --repol' -nthreads 12 -debug -nocleanup  (version=3.0.4)
  comments:          untitled
  mrtrix_version:    3.0.4

dwifslpreproc_log.txt

@jdtournier
Copy link
Member

OK, that's odd... The last command to run is:

/opt/miniconda-latest/bin/mrconvert result.mif /xdisk/adamraikes/p3/derivatives/dmri_prep/sub-AT7894/dwi/tmp/full_data/eddy_tmp.mif.gz -copy_properties output.json -append_property command_history "/opt/miniconda-latest/bin/dwifslpreproc unringed.mif.gz eddy_tmp.mif.gz -rpe_none -pe_dir IS -readout_time 0.1 -eddyqc_all eddy_tmp -eddy_options ' --slm=linear --repol' -nthreads 12 -debug -nocleanup  (version=3.0.4)" -nthreads 12

which happily reports:

          mrconvert: [INFO] found 102x4 diffusion gradient table

Yet the output image seems not to contain any DW gradient scheme...

Can you post the output of:

mrinfo /xdisk/adamraikes/p3/derivatives/dmri_prep/sub-AT7894/dwi/tmp/full_data/dwifslpreproc-tmp-QD4HV1/result.mif

Just to check that this image did indeed contain a valid DW scheme...?

Right now, I'm struggling to see what could have caused that... Any ideas, @Lestropie...?

@araikes
Copy link
Author

araikes commented Jan 31, 2023

Information below. Interestingly, I can run the very final mrconvert command that moves result.mif to the intended output file without issue (mrconvert result.mif /xdisk/adamraikes/p3/derivatives/dmri_prep/sub-AT7894/dwi/tmp/full_data/eddy_tmp.mif.gz).

Also the nans seem like they'll be a problem.

************************************************
Image name:          "result.mif"
************************************************
  Dimensions:        64 x 128 x 64 x 102
  Voxel size:        0.2 x 0.2 x 0.2 x 1
  Data strides:      [ 1 2 3 4 ]
  Format:            MRtrix
  Data type:         32 bit float (little endian)
  Intensity scaling: offset = 0, multiplier = 1
  Transform:                    1   -0.007121   2.553e-08       -7.62
                         0.007121           1  -7.171e-06      -12.65
                        2.553e-08   7.171e-06           1      -1.544
  command_history:   /opt/miniconda-latest/bin/mrconvert dwi_post_eddy.nii.gz result.mif -strides '1,2,3,4' -fslgrad dwi_post_eddy.eddy_rotated_bvecs bvals -nthreads 12  (version=3.0.4)
  comments:          6.0.5:9e026117
  dw_scheme:         nan,nan,-nan,19.50365589
  [102 entries]      nan,nan,-nan,19.50365589
                     ...
                     -0.05677371844,0.8427828121,-0.5352512274,3006.220658
                     -0.9689936093,-0.09208267537,0.22928621,3003.228201
  mrtrix_version:    3.0.4

And for completeness:

bvecs:

-0 -0 -0 -0 0.0100367475446016 0.947418304570552 0.104425884098225 -0.835696772647387 -0.449742148713184 0.393250255049596 -0.752775327538722 -0.310346714029372 0.461805792476849 -0.719934706445747 0.371419720643724 0.830529810839831 -0.10484990530785 0.366502421275865 -0.774564981523671 0.477760237108003 -0.372918454089102 0.953263006664 -0.739427906659804 0.794274225484626 -0.0860506889914598 -0.262079333736669 0.00475629985469737 0.0280356434662155 -0.977697465034983 0.389452080431156 -0.493920654585494 0.488533119256244 0.705608791333099 0.670749073705513 -0 -0 -0 -0 0.473703151978698 -0.396912634222226 0.801151656596171 -0.254548734398599 0.1879402692692 -0.933870717341881 0.377283100956642 -0.844225177718984 -0.495016908301024 0.885012045932369 0.0875697741090885 0.151581689905252 -0.61739809930513 -0.595813753888473 0.856347132983497 -0.596355570862974 0.171521096402311 0.690726685386525 0.123144106764907 0.240777334784494 0.988573515915087 -0.563865061285475 0.472623163746212 -0.248119882086629 -0.917687829645411 0.720994073139966 -0.20246003818325 -0.33903159733509 -0.618670190304643 0.260840931376421 0.38525058230796 -0.88383303918526 -0.647170169557551 -0.273611348017325 0.370228064778473 -0.117686944108981 0.79951979278369 0.749107591702782 -0.920678880817699 -0.145647990854472 -0.307810460342925 0.701036428009371 -0.735645196739624 0.438189561676915 -0.552743081779726 -0.637286546592646 -0.0531243438653329 0.984322179424118 0.331758214499732 0.0167288761375533 0.0192695520391877 -0.898364275696238 0.760272718218764 -0.0612220051687819 0.763347385484327 0.516390951641732 -0.574390373185842 0.141053361295837 0.780213259707094 0.418414596969408 -0.486208651481996 -0.394855573445282 0.0565099063921111 0.968069828062038
0 0 0 0 -0.910782310978604 0.17297745006605 -0.375652046332073 0.123105055399387 0.301804094209208 0.850433591888362 0.647713774419169 -0.35816037610209 -0.837080216204023 -0.62472507841498 0.196348290783864 -0.335598191293736 0.807879324585234 0.718669871344492 -0.617264385339117 -0.0856945647478591 0.914417512094767 0.223768273460604 -0.0341232487951303 -0.512445332504561 0.603549735851768 -0.617669591052088 -0.991266693882904 -0.0949223556565267 0.209757629611909 0.913012566108952 0.524605333338338 -0.676418976792362 0.304121085879152 0.481907570420484 0 0 0 0 0.367776700981243 -0.767575428644991 -0.557294256014313 0.422679775524684 0.942054849301374 -0.0876748253458927 -0.0474172973942838 0.0390892714706119 0.833783757762534 0.457160373348618 -0.609082602175114 -0.942351367988635 -0.128385066745682 -0.776988220962106 -0.362580464155136 0.666469721705021 -0.135370464699284 0.602612596926624 -0.946708177211168 0.633831713143901 -0.117595605245939 -0.580786339636417 -0.543791524467298 0.353182952903359 -0.222101131212428 -0.406012881757512 -0.942258921365202 -0.122285105516611 0.782647551124787 0.638307259621198 0.328176645225951 -0.398361199827008 0.614327495459196 0.773355852300619 0.928336219247791 0.678028376596986 -0.0667171548631031 0.298660861775949 0.388804212210273 -0.144296187400003 0.951408566152903 -0.307065777342522 -0.674146052805017 -0.537920416996177 -0.49987043981973 -0.0597071312568101 -0.823505665057209 0.17633665028927 -0.788633812265195 -0.152404810947893 0.999765719062125 0.27262645578868 0.54592640246143 -0.438885800617563 -0.626519262241455 0.827953429686638 0.235410035277851 0.404895223382111 0.294179507777146 -0.861128225000186 0.197446930614585 -0.800116711012941 0.845058482945488 -0.0903778877477914
0 0 0 0 0.412764879562102 0.269216191843979 -0.920858715984131 0.535215890564813 -0.840622560000687 0.349452346827414 -0.117457110004701 0.88057144063514 -0.293312328052364 0.302345158348515 0.907466109455891 0.44451556465761 0.579946113179555 -0.590922660976758 -0.137962922859817 -0.874300633291008 -0.157392630690182 -0.203020688549691 -0.672370414893658 -0.326386635683093 -0.792668275688916 -0.74148411928358 -0.131786642917736 0.995089819647934 0.0104596191931524 -0.121388348847542 0.693420241460135 0.551173982719151 -0.640020779910077 0.563791427389668 0 0 0 0 0.80021598461875 0.503277579609164 -0.218126420284439 -0.869796958640085 0.277868883049465 0.346696709396249 -0.924883269151569 -0.534561388587108 -0.244464528469948 0.0880799159453973 -0.788257520335697 0.298323466261189 0.776103641029163 -0.203212389486853 0.367702318209932 0.447412721201381 0.975835719172409 -0.399693262623964 -0.297622506036751 -0.735039886300005 -0.0943062947992071 -0.587148550482383 0.69348260471958 0.902052285544719 -0.329423944011011 -0.561534581607879 0.266754677557227 -0.932793615450888 0.0686294863882837 0.724241569354822 -0.862485987402956 0.245249899563091 -0.451411674597307 0.57188946134461 0.0335118485567042 -0.725553101895663 -0.596922877958638 0.591303226588612 -0.034375617309569 0.978757004081877 -0.0086290700668384 0.64362919054478 0.0659791177585982 -0.720160768798848 0.666786794270364 -0.768310429421076 -0.564815211953429 -0.00390293038920105 0.517680593929334 -0.988176562274024 -0.00985857111356872 0.344407380513004 0.352064989878782 0.896454750694319 0.157398802985753 -0.218708717833318 0.784001157182858 0.903417847543367 -0.552019643309874 -0.288768774707311 -0.851243711766805 -0.451555450603065 -0.531679218047722 0.233821823842194

dwi_post_eddy.eddy_rotated_bvecs

-nan  -nan  -nan  -nan  0.00988191837  0.947173236  0.1050599533  -0.8358291069  -0.4486960037  0.3930749484  -0.7527820483  -0.3110154314  0.461732563  -0.7199974058  0.370757182  0.8302559712  -0.1049986623  0.3672003946  -0.7744046101  0.4779100866  -0.3725800419  0.9532685422  -0.739194789  0.7941650676  -0.08521129008  -0.2618701939  0.004470591537  0.02716617133  -0.9776734995  0.3897619343  -0.4939585296  0.4880780635  0.7059765141  0.670702835  -nan  -nan  -nan  -nan  0.473931341  -0.391649582  0.8024954839  -0.2590042005  0.1851221111  -0.9319425044  0.3742472386  -0.8464223  -0.5000316946  0.8833128755  0.08676210544  0.1567585155  -0.6141849599  -0.5931843266  0.8592334654  -0.5969839345  0.1750881423  0.6867813293  0.1258978822  0.2354671954  0.9886675228  -0.5630128095  0.4773097458  -0.2460025806  -0.9177270146  0.7199881911  -0.1976384601  -0.3412899144  -0.6216921496  0.2603164457  0.3801002457  -0.8810790173  -0.6521773786  -0.2742045254  0.3665506813  -0.1233878762  0.7971115611  0.7492896333  -0.9226947346  -0.1417049703  -0.3120253466  0.7044953263  -0.7325193239  0.4373076173  -0.54842112  -0.6390012121  -0.05179509942  0.9834680855  0.3373109274  0.01382423361  0.01496691905  -0.8977683448  0.7591340128  -0.05596546003  0.7668715873  0.5121103831  -0.571841858  0.1426822819  0.7760286772  0.4205010326  -0.4903648018  -0.393176634  0.05077062048  0.9696247775  
-nan  -nan  -nan  -nan  -0.912435559  0.1718014722  -0.3714304532  0.1203729086  0.3053474031  0.8486231722  0.6482964819  -0.362057829  -0.8356073103  -0.6262662518  0.1920039305  -0.3376779839  0.8047644578  0.7211373017  -0.6166651525  -0.08156220676  0.9152884703  0.2248878167  -0.03112845448  -0.5111745194  0.6072504035  -0.6138589525  -0.9905753017  -0.09926649986  0.2098193059  0.9134820306  0.5210073502  -0.679091136  0.30697571  0.4790994868  -nan  -nan  -nan  -nan  0.372283743  -0.7670973446  -0.5541865658  0.4170426262  0.9433478855  -0.09083917339  -0.04910407526  0.0333184018  0.830797512  0.4611898999  -0.6100740448  -0.9407328827  -0.1279025145  -0.7798946494  -0.3575559636  0.6648048274  -0.1299265501  0.6038361904  -0.9466811832  0.6309060592  -0.1133905671  -0.5847522509  -0.5383740284  0.3548497441  -0.2273088986  -0.4042820046  -0.9420401579  -0.1275854162  0.7801421523  0.6410926814  0.3257635378  -0.4015432093  0.6096579709  0.7729902811  0.9299204448  0.6739994725  -0.06480366535  0.3036308783  0.3843265998  -0.1404665054  0.9500277368  -0.3013905825  -0.6771019736  -0.5372892485  -0.499137854  -0.0653324119  -0.8246478224  0.1808881372  -0.7849657866  -0.1560240541  0.9998086987  0.2693495392  0.5502783523  -0.4347858656  -0.6227068314  0.8293869185  0.234560745  0.4082444324  0.2957196534  -0.8598268655  0.1920781776  -0.8025732676  0.8431619039  -0.0851782448  
-nan  -nan  -nan  -nan  0.4091010858  0.2708267253  -0.9224976014  0.5356305321  -0.8399016964  0.3540208985  -0.1141527893  0.8787397396  -0.2975961412  0.298988825  0.9086658366  0.443450788  0.5842340699  -0.5874732865  -0.1414976662  -0.8746139466  -0.1530722982  -0.2017537023  -0.67277194  -0.3286372713  -0.7899278343  -0.7447155081  -0.1368962584  0.9946899824  0.01141872318  -0.1167742026  0.6961007916  0.5482837157  -0.6382500098  0.5662343939  -nan  -nan  -nan  -nan  0.7979936708  0.5081065527  -0.2210842569  -0.8712016254  0.275362617  0.3510433209  -0.9260279662  -0.5314688836  -0.2444254456  0.08403713637  -0.7875798353  0.3007464235  0.7787283106  -0.1997415594  0.3658846606  0.449048687  0.9759422288  -0.4046149539  -0.2965543132  -0.7392650028  -0.09838246159  -0.5840217303  0.6944989648  0.9019780427  -0.3257419089  -0.5640683163  0.2711076907  -0.9312589092  0.06983618958  0.7219664272  -0.8656800336  0.2499256216  -0.4505350434  0.5720995575  0.02980879607  -0.7283544076  -0.6003446045  0.5885349056  -0.03045474296  0.9798922707  -0.009353200198  0.6425340863  0.07034456179  -0.7211673254  0.6708917035  -0.7664262045  -0.5632701276  -0.008366997432  0.5196634028  -0.9876565117  -0.01259195248  0.3485151716  0.3477201253  0.8987931455  0.1553839464  -0.2232941893  0.7861158607  0.9016530651  -0.5570721486  -0.2896146457  -0.8500872513  -0.4486516294  -0.5352572726  0.2292868456  

@Lestropie
Copy link
Member

I'll try to replicate the configuration using my own data rather than having to download yours.

First thing that takes my eye is:

dwifslpreproc: [DEBUG] image.__init__() (from image.py:137): {'_name': '/xdisk/adamraikes/p3/derivatives/dmri_prep/sub-AT7894/dwi/tmp/full_data/unringed.mif.gz', ... 'dw_scheme': [[0.0, 0.0, 0.0, 19.50365589], ...
...
dwifslpreproc: [DEBUG] image.__init__() (from dwifslpreproc:1308): {'_name': 'result.mif', ... 'dw_scheme': [[None, None, None, 19.50365589], ```

So perhaps wherever the NaNs are creeping in, getting that data into Python via the JSON import is converting them to None, and that's then precluding them from being loaded back into the header via JSON?

And for completeness:
bvecs:

Is this the bvecs that is generated as the input to eddy? If so, then eddy motion correction of bvecs doesn't like null vectors, and there's therefore probably an argument to be made about whether the bvecs format supports null vectors, at which point we need to modify our save_bvecs_bvals() function.

Between 3.0.3 and 3.0.4 the only potentially relevant change I see is #2329. It would also be important to rule out the prospect of this actually arising due to an FSL update rather than the MRtrix3 update.

@jdtournier
Copy link
Member

I have a suspicion the NaNs might be due to those b=0 images not being recognised as b=0 as they're actually b=19.5 - which is above our default threshold. I wonder if things might actually work out of the box if you add:

BZeroThreshold: 30

to your ~/.mrtrix.conf file...?

@araikes
Copy link
Author

araikes commented Feb 1, 2023

Hi @Lestropie,

So, I can address some of these.

  1. I'm running MRtrix in Singularity images that I have built for myself. I have a container with v 3.0.3 and another with v. 3.0.4. FSL version is identical between the containers (v. 6.0.5.1). Python version differs (3.9.7 vs 3.10.8) and ANTs differs by a minor update (2.4.1 vs 2.4.2).
  2. MRtrix was installed exactly the same way (conda installer).
  3. There are probably some python package version differences. If you can tell me which might be relevant, I can check version differences. The only notable addition is the inclusion of TractSeg in the container with 3.0.4.
  4. There is only one thing in my ~/.mrtrix.conf file and it is BZeroThreshold: 61 (Bruker gradients are weird sometimes).
  5. Yes the bvecs shown are the ones used for eddy.

Notables:

  1. The processing works just fine in 3.0.3. No nan's, no weirdness. All of the [0 0 0] vectors get interpreted as bzeros with the proper number of volumes if I use dwiextract.
  2. I can manually convert the result.mif file (which has the gradient table, albeit with nans) to the output file and have it retain the gradient table.

Questions:

Is this the bvecs that is generated as the input to eddy? If so, then eddy motion correction of bvecs doesn't like null vectors, and there's therefore probably an argument to be made about whether the bvecs format supports null vectors, at which point we need to modify our save_bvecs_bvals() function.

What do you mean by "null vectors" in this case? I'm assuming it's the [0 0 0] vectors you're referring to (since that's where the nans end up), but I guess I don't understand how you'd then represent b= 0 if its not [0 0 0].

@Lestropie
Copy link
Member

The processing works just fine in 3.0.3. No nan's, no weirdness. All of the [0 0 0] vectors get interpreted as bzeros with the proper number of volumes if I use dwiextract.

That's at the point of import. My suspicion is that in 3.0.3 those data may have been internally modified at import time to be [0 0 1], such that they would be [0 0 1] in the bvecs fed to eddy, and it would therefore have no issue with rotation of the gradient directions. But I'll know more when I get the chance to test.

I guess I don't understand how you'd then represent b= 0 if its not [0 0 0].

Well even at our end it's only fairly recently that we've supported [0 0 0] as b=0. Historically there's a unit vector direction but b < BZeroThreshold in the fourth column.

@Lestropie
Copy link
Member

First finding: problem only manifests in the case where it is the case that both the vector direction is null and the b-value is non-zero.

@Lestropie
Copy link
Member

Lestropie commented Feb 2, 2023

  • For above tests, all four cases work OK on 3.0.3.
  • For data with [0 0 0 5]:
    • bvals contains b=5 on master, b=0 on 3.0.3.
    • This occurs not at bvec-bval export, but at initial conversion of the input DWI data into the scratch directory.
    • mrinfo reports [0 0 0 5] on both software versions
    • mrconvert piped to mrinfo reports b=5 on master, b=0 on 3.0.3.
    • Same goes for mrinfo -export_grad_fsl: b=5 on master, b=0 on 3.0.3.

A git bisect selects e105aec from #2450. However that's clearly a bug fix preventing infinity from rearing its ugly head where it doesn't belong.

I think the solution here is to prevent [0 0 0 <BZeroThreshold] from appearing in an exported bvecs.

Edit: An alternative is that if a [0 0 0 <BZeroThreshold] is present, write a b-value of 0. This would prevent the manifestation of the problem, which is eddy attempting to rotate vectors for any volumes with non-zero b-value, without any tolerance on the classification of such (recall that there's no issue with [0 0 0 0]).

@Lestropie
Copy link
Member

PS.

I can manually convert the result.mif file (which has the gradient table, albeit with nans) to the output file and have it retain the gradient table.

This relates to c7c1cc9 in #1603.

The final image export step of Python scripts involves taking template image header contents and importing it into the exported image. This means in particular that command_history has added to it the string used to invoke the script, rather than all of the MRtrix3 commands executed within the script. In the case of dwifslpreproc, this template header information is manually modified by exporting from MRtrix3 to JSON, importing the JSON in Python, manipulating the dict, exporting to JSON from Python, and then providing that JSON to the final mrconvert call.

(There's a separate argument to be had over whether some of those modifications should or should not be done, but let's defer that for now...)

The JSON for Modern C++ library that we use for JSON handling, when it sees the NaNs in the gradient table, instead writes them to the JSON as "null". These get preserved by the library when the modified JSON is loaded back in, but get detected as non-numeric and discarded by MRtrix3 deep in the back-end during header construction here.

@jdtournier
Copy link
Member

OK, thanks for the deep dive, Rob!

Edit: An alternative is that if a [0 0 0 <BZeroThreshold] is present, write a b-value of 0. This would prevent the manifestation of the problem, which is eddy attempting to rotate vectors for any volumes with non-zero b-value, without any tolerance on the classification of such (recall that there's no issue with [0 0 0 0]).

Yes, that's my immediate gut feeling also. We would however need to double-check what happens with trace-weighted data, which some manufacturers have a habit of producing with zero DW direction vectors and non-zero b-value. But I expect as long as we only zero b-values <BZeroThreshold, that should be OK too, right?

The JSON for Modern C++ library that we use for JSON handling, when it sees the NaNs in the gradient table, instead writes them to the JSON as "null".

Should we treat 'null' as equivalent to NaN when parsing these values, then? I think it should just be a matter of adding to the list at this point in the code... (?)

@araikes
Copy link
Author

araikes commented Feb 6, 2023

Thanks for all of this.

As a wrap-up for me and my data need in the short-term, should I just downgrade to 3.0.3, since this produces correctly formatted gradient tables in the dwifslpreproc output?

@Lestropie
Copy link
Member

Lestropie commented Feb 6, 2023

To be clear, the two alternatives are:

  1. Write [0 0 0 <BZeroThreshold] as [0 0 0 0]
  2. Write [0 0 0 <BZeroThreshold] as [0 0 1 <BZeroThreshold]

Neither of these are ideal, but my suspicion is that while either may be a solution for eddy motion correction, 1. may be more likely to cause issues elsewhere in FSL. Content with either though. Also should consider a terminal message (WARNING?) to notify regarding the modification on export.

Should we treat 'null' as equivalent to NaN when parsing these values, then?

Personally I think no. In Python there's a considerable distinction between a floating-point NaN and None; I'd treat JSON null as the same as the latter. This conversion may well be a bug in JSON for Modern C++ that has been patched since we last imported.


@araikes: Easier would be to manually modify your gradient table to explicitly have zeroes in the fourth column for volumes intended to be b=0. Then 3.0.4 and eddy should play nicely with one another.

@jdtournier
Copy link
Member

jdtournier commented Feb 7, 2023

This conversion may well be a bug in JSON for Modern C++ that has been patched since we last imported.

Looking at the docs, this looks very much like the intended behaviour. I don't see that being patched any time soon...

As to how to handle things going forward, personally I think option 2 is the most likely to cause problems, since this gives a direction where there was none, and invites eddy (or MRtrix) to treat these as a b>0 shell - which if anything is likely to glitch if it tries to fit SH to it. I think these need to be zero'd to make it very clear to eddy (and other downstream applications) that these are to be interpreted as b=0 volumes. This is also what the previous version did (I think?).

Also worth linking with this discussion on the forum. Not the same exactly, but it's probably worth expanding the fix to also force any entry with b<BZeroThreshold to zero while we're at it.

@Lestropie
Copy link
Member

option 2 is the most likely to cause problems

The converse I was thinking of was IVIM, where loss of non-zero but small b-values could be a problem. But surely users of such would be manually specifying a smaller BZeroThreshold. So happy to go with 1.

Also worth linking with this discussion on the forum.

Request already exists in #2495.

Not the same exactly, but it's probably worth expanding the fix to also force any entry with b<BZeroThreshold to zero while we're at it.

As in, even if the vector is valid? eddy at least has been processing such data without issue for some time.

@jdtournier
Copy link
Member

OK, ignore that discussion on the forum, I got myself mixed up... You're right, #2495 is probably the right answer there.

The converse I was thinking of was IVIM, where loss of non-zero but small b-values could be a problem.

I would expect IVIM to explicitly ignore BZeroThreshold, it's really not appropriate to this use case... I've not looked into the detail of @dchristiaens' IVIM PR (#2578), but if that doesn't already ignore the b-zero threshold, we should make sure it does - or provide some alternative means of setting that threshold...

@Lestropie
Copy link
Member

I would expect IVIM to explicitly ignore BZeroThreshold, it's really not appropriate to this use case...

In the IVIM implementation itself, of course. But this issue is around bvecs / bvals generation. What you wouldn't want is for a conversion between formats to modify the gradient table in such a way that the requisite information for such a model is lost.

@araikes
Copy link
Author

araikes commented Mar 13, 2023

I assume that you (@Lestropie and @jdtournier) arrived a solution that is going to work for MRtrix and the majority of use cases, however just some additional testing that I finally had opportunity to do with these data:

  1. Rounding the negative bvecs corresponding to bzeros (e.g., [-0 0 0]) to [0 0 0]) does not work.
  2. Rounding the bzero bvals to 0 does not work.
  3. Setting the BZeroThresholdValue manually in dwifslpreproc with the original bvecs does not work.
  4. Setting the BZeroThresholdValue manually with the rounded bvecs ([-0 0 0]) to [0 0 0]) does not work.
  5. Using the rounded bvecs and the rounded bvals works.

Just as an aside, other tools (e.g., dirstat) see the original b-values as the correct shells (0, approx. 1000, and approx. 3000)

@Lestropie
Copy link
Member

I assume that you arrived at a solution

We didn't decide definitively on one. I'm confident that the solution should be explicitly limited to the bvec-bval export step, possibly with a warning to say that there are modifications being made to the gradient table compared to the internal representation of those data. But deciding between the two options is tough because I don't know whether any given FSL command is going to bork in one case or the other. Ie. We know that [0 0 0 >0] is a problem for eddy rotating bvecs, but could [0 0 0 0] be a problem elsewhere?

Rounding the bzero bvals to 0 does not work.

OK, I think that conflicts with my own prior testing.


What I might do is create a branch where on -export_grad_fsl, [0 0 0 0<BZeroThreshold] is modified to [0 0 0 0], and we'll see if dwifslpreproc then works on such data, and test bedpostx also.

Lestropie added a commit that referenced this issue Mar 14, 2023
Where the gradient direction vector is zero, but the b-value is non-zero, when FSL's "eddy" attempts to rotate the directions of b>0 volumes according to subject rotation, this results in corrupted gradient directions.
This change prevents such data from reaching "eddy" within dwifslpreproc, by detecting volumes where the gradient vector is zero and the b-value is non-zero but is classified by MRtrix3 as non-zero based on BZeroThreshold and forcing the value within the bvals file to be zero.
Relates to #2577.
Lestropie added a commit that referenced this issue Mar 14, 2023
Where the gradient direction vector is zero, but the b-value is non-zero, when FSL's "eddy" attempts to rotate the directions of b>0 volumes according to subject rotation, this results in corrupted gradient directions.
This change prevents such data from reaching "eddy" within dwifslpreproc, by detecting volumes where the gradient vector is zero and the b-value is non-zero but is classified by MRtrix3 as non-zero based on BZeroThreshold and forcing the value within the bvals file to be zero.
Relates to #2577.
@lconcha
Copy link

lconcha commented Aug 31, 2024

Hello. Seeing as this issue is still open, I'll just throw something else in.

It seems that eddy sometimes leaves nan values in the bvec files, which then causes dwifslpreproc to fail with an error saying no gradient information found within image. I added the following simple hack in this line of dwifslpreproc and it all works now.

app.console('Making sure there are no nans in bvecs')
run.command('sed -i \'s/nan/0/g\' ' + bvecs_path)

Tested on mrtrix 3.0.4, with fsl 6.0.7.1 and 6.0.7.4.

@Lestropie Lestropie added this to the 3.1.0 updates milestone Sep 2, 2024
@Lestropie
Copy link
Member

@lconcha Presumably you're applying your hack after the code block corresponding to old versions of eddy where rotated bvecs aren't created, rather than within it?

Did you happen to try the code in #2602? That's intended to condition the bvecs to prevent eddy from ever producing a corrupt output; but if it's still possible for that to occur, then yes, dwifslpreproc will need to also check the output produced by eddy and condition it if necessary (though I'd probably do it without sed).

@lconcha
Copy link

lconcha commented Sep 2, 2024

Yes, I placed that sed hack right after the script checks for the existence of the rotated bvecs.
The code in #2602 does not appear to deal with NaN values, and I agree that something more elegant than sed could be used to solve this issue. Cheers.

@Lestropie Lestropie removed this from the 3.1.0 updates milestone Sep 16, 2024
@Lestropie Lestropie added this to the 3.0.5 updates milestone Sep 16, 2024
@Lestropie
Copy link
Member

I've expanded the scope of #2602 via bac6028 to include sanitisation of bvecs / bvals import that may contain NaN values. That should hopefully make the MRtrix3 software robust to whatever FSL generates, regardless of the condition of the data that was provided to FSL (which may not necessarily come from dwifslpreproc). So I'm going to deem this closed; the warning that gets generated when such NaN values appear should over time provide insight into the circumstances in which they arise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants