Distortion correction using T1

Is there any reason to use the warp field to modulate the DWI after it’s been normalized to the T1 image?

Hi
If you refer to the fact that one should modulate the DWI with the jacobian of the warp field I would say no :
The modulation is used when normalizing gray matter segmentation so that the deformation shrinking (or dilation) is reflected to the intensity of gray matter (used after for vbm).
but for diffusion the deformation is used to correct for the EPI distortion so we want to correct the deformation and keep the original intensity

1 Like

Thanks. Just making sure my reasoning was correct on this.

Is there any reason to use the warp field to modulate the DWI after it’s been normalized to the T1 image?

Ideally, one would modulate the FODs based on any non-linear transfomation. Hopefully the figures in the original AFD manuscript should demonstrate why this is the case. However this modulation can’t be applied to the diffusion MRI intensities directly.

Any chance you have been able to repeat this process or document it in some way so that we could try and replicate it? I unfortunately have several old data sets with no opposite phase encoding directions that I have run through 3 tissue CSD.

Hey Daniel,

Yep, I’ve vaguely documented some ideas here a while ago: T1-like contrast from DWI data .

But I wouldn’t actually recommend to use this without a lot of experience in what’s going on here, as well as very careful QC. Generating the T1-like contrast itself is in some ways relatively straightforward actually, but it’s the registration for this particular purpose and sometimes in presence of certain particular pathologies, that is much harder to get right without a lot of experience in this area.

So while we did manage to get this right for a few particular studies at some point, I wouldn’t generally recommend to adopt this strategy broadly.

There’s a nice piece of work here though, and the software seems to be available: https://www.biorxiv.org/content/10.1101/2020.01.19.911784v1.full . It looks like quite an elegant approach with promising results. If you give it a go, I would actually love to hear if it works well for your data!

Cheers,
Thijs

There’s a nice piece of work here though, and the software seems to be available: https://www.biorxiv.org/content/10.1101/2020.01.19.911784v1.full . It looks like quite an elegant approach with promising results. If you give it a go, I would actually love to hear if it works well for your data!

Can confirm, Synb0-DISCO is fantastic and very comparable to topup.

1 Like

Thanks for the feedback @lbinding. Is there any chance you have any documentation on running the docker scripts that are available for Synb0-DISCO.

I have docker installed however I find the documentation on running a bit confusing.

Specifically, if I have an input folder with the requested documents.

How do I set up this command?

sudo docker run --rm \
-v $(pwd)/INPUTS/:/INPUTS/ \
-v $(pwd)/OUTPUTS:/OUTPUTS/ \
-v <path to license.txt>:/extra/freesurfer/license.txt \
--user $(id -u):$(id -g) \
justinblaber/synb0_25iso

I have

@CallowBrainProject No worries, I’ve been thinking about writing up my pipeline on here as I’ve spent the last 2 months trying to get optimal tractography for older and newer data… I’m sure I’ll get round to it at some point…

So I have a folder in each participant called synb0 where I have my T1, the b0 and acqparams. The acqparams need to be changed so it has another line i.e. if the original acqparams.txt file is:

0 1 0 0.035225

you need to add another line with all zeros on the 4th entry i.e:

0 1 0 0.035225
0 1 0 0.000000

After that I would call synb0-disco like:

sudo docker run --rm
-v /Users/lbinding/Desktop/subjects/161/synb0/:/INPUTS/
-v /Users/lbinding/Desktop/subjects/161/synb0/OUTPUTS:/OUTPUTS/
-v /Applications/freesurfer/license.txt:/extra/freesurfer/license.txt
–user $(id -u):$(id -g)
justinblaber/synb0_25iso

Hope that helps, if you have issues I’m more than happy to help where I can.

1 Like

Hi all - I’m glad this tool has been useful for several groups!

@CallowBrainProject, just to clarify here, when you run this command you are running the docker image (named synb0_25iso) that is essentially a system-agnostic black box that is only good (in our case) for running this one specific process. You can think of this as each line in the above command is binding a directory on your system to a directory within this black-box. So anything before the “:” should point to the inputs on your file system and everything after the “:” remains unchanged. For example we choose to literally create a folder named INPUTS but you can use any folder on your system as an inputs folder and bind it to the /INPUTS/ directory within the docker image.

The issue that we’ve run into most is the that should point to a free surfer license.txt file (you get this when you download free surfer). For example, my license file sits in /Applications/freesurfer/ so my line would look like:

-v /Applications/freesurfer/:/extra/freesurfer/license.txt

We use a freesurfer command during a preprocessing step and are looking to eliminate this in a future iteration to make this more simple for users.

Also - this docker/singularity image will create a synthesized image and run TOPUP for you. You will then want to use the output (movement parameters and field coefficients) with EDDY in exactly the same way you would if you had started with a full set of blip-up blip-down acquisitions. We are trying to update the GitHub to make this very intuitive to use (I apologize this is my first tool I’ve released and I can only imagine how hard it would be to maintain an entire software framework like MRtrix3!).

One last note, we would recommend after running this pipeline to do a visual inspection of the b0_all.nii.gz and flip back-and-forth between the first and second volumes. The first one is your distortion-corrected b0 which should now match the second volume (the synthesized b0 that is undistorted) exactly!

Would love any feedback on the output or running the image itself!

2 Likes

Hello, thank you so much for all the input and advice. I am really excited to try and run this.

I am currently running the following!

sudo docker run --rm \

-v /Volumes/DANIEL/EPC/analysis/EPC001.post/input:/INPUTS/ \

-v /Volumes/DANIEL/EPC/analysis/EPC001.post/output:/OUTPUTS/ \

-v /Applications/freesurfer_dev/license.txt:/extra/freesurfer/license.txt \

-user $(id -u):$(id -g) \

justinblaber/synbo_25iso

However, I get the following error when trying to run…

Unable to find image ‘501:20’ locally

docker: Error response from daemon: pull access denied for 501, repository does not exist or may require ‘docker login’: denied: requested access to the resource is denied.

See ‘docker run --help’.

For reference I already downloaded the

Synb0-DISCO-master file in my applications folder.

I also have docker but am not super familiar with using it.

does it have something to do with me not sourcing to or correctly sourcing the docker image in general? Is that what the error means? should something point to the “docker”, justinblaber/synbo_25iso ?

By default the user id and group id is 501 and 20. If you used this command exactly then it looks like you might be missing a dash for the argument --user. Could you change “-user” to “–user”? For some reason it doesn’t know where to look for the image.

1 Like

Thank you!

I changed the command to …

sudo docker run --rm \

-v /Volumes/DANIEL/EPC/analysis/EPC001.post/input:/INPUTS/ \

-v /Volumes/DANIEL/EPC/analysis/EPC001.post/output:/OUTPUTS/ \

-v /Applications/freesurfer_dev/license.txt:/extra/freesurfer/license.txt \

–user $(id -u):$(id -g) \

justinblaber/synbo_25iso

This resulted in the error…

Unable to find image ‘justinblaber/synbo_25iso:latest’ locally

docker: Error response from daemon: pull access denied for justinblaber/synbo_25iso, repository does not exist or may require ‘docker login’: denied: requested access to the resource is denied.

See ‘docker run --help’.

I changed the code to justinblaber/synb0_25iso:latest …

sudo docker run --rm \

-v /Volumes/DANIEL/EPC/analysis/EPC001.post/input:/INPUTS/ \

-v /Volumes/DANIEL/EPC/analysis/EPC001.post/output:/OUTPUTS/ \

-v /Applications/freesurfer/license.txt:/extra/freesurfer/license.txt \

--user $(id -u):$(id -g) \

justinblaber/synb0_25iso:latest

It seems to work however there does seem to be an issue with the freesurfer license.txt…

The path /Applications/freesurfer/license.txt

is not shared from OS X and is not known to Docker.

You can configure shared paths from Docker -> Preferences… -> File Sharing.

See https://docs.docker.com/docker-for-mac/osxfs/#namespaces for more info.

.

ERRO[0000] error waiting for container: context canceled

But for people who find this thread in the future. …

You just need to mount /Applications/ in the file sharing section of docker.

thanks for all your help! I look forward to trying it out.

1 Like

Very keen to see a result! I’ve got a few use cases where this would be very welcome, and of high impact.

Thanks for chipping in and providing some documentation / help @schilkg1; this will be very useful to many!

Cheers,
Thijs

I will be sure to share some results as I get them.

Unfortunately @schilkg1; eventhough it seems like I have everything up and running fine, there appears to be some type of docker error when running on every one of the three subjects I have tried so far. I appear to be getting the error around the bbregister and FAST segmentation portion.

See here the first error. That then propagates throughout the rest of the script.

Removing job directory...
-------
Skull stripping T1
bet /INPUTS/T1.nii.gz /tmp/tmp.9D4x42aZhk/T1_mask.nii.gz -R
-------
epi_reg distorted b0 to T1
epi_reg --epi=/INPUTS/b0.nii.gz --t1=/INPUTS/T1.nii.gz --t1brain=/tmp/tmp.9D4x42aZhk/T1_mask.nii.gz --out=/tmp/tmp.9D4x42aZhk/epi_reg_d
Running FAST segmentation
/extra/fsl/bin/epi_reg: line 320:  1243 Killed                  $FSLDIR/bin/fast -o ${vout}_fast ${vrefbrain}
Image Exception : #63 :: No image files match: /tmp/tmp.9D4x42aZhk/epi_reg_d_fast_pve_2
terminate called after throwing an instance of 'std::runtime_error'
  what():  No image files match: /tmp/tmp.9D4x42aZhk/epi_reg_d_fast_pve_2
/extra/fsl/bin/epi_reg: line 320:  1244 Aborted                 $FSLDIR/bin/fslmaths ${vout}_fast_pve_2 -thr 0.5 -bin ${vout}_fast_wmseg
Image Exception : #63 :: No image files match: /tmp/tmp.9D4x42aZhk/epi_reg_d_fast_wmseg
terminate called after throwing an instance of 'std::runtime_error'
  what():  No image files match: /tmp/tmp.9D4x42aZhk/epi_reg_d_fast_wmseg
/extra/fsl/bin/epi_reg: line 329:  1269 Aborted                 $FSLDIR/bin/fslmaths ${vout}_fast_wmseg -edge -bin -mas ${vout}_fast_wmseg ${vout}_fast_wmedge
FLIRT pre-alignment
Running BBR
Image Exception : #63 :: No image files match: /tmp/tmp.9D4x42aZhk/epi_reg_d_fast_wmseg
Image Exception : #22 :: Failed to read volume /tmp/tmp.9D4x42aZhk/epi_reg_d_fast_wmseg
Error : No image files match: /tmp/tmp.9D4x42aZhk/epi_reg_d_fast_wmseg
Failed to read volume /tmp/tmp.9D4x42aZhk/epi_reg_d_fast_wmseg
Error : No image files match: /tmp/tmp.9D4x42aZhk/epi_reg_d_fast_wmseg
Could not open matrix file /tmp/tmp.9D4x42aZhk/epi_reg_d.mat

Hi @CallowBrainProject. Once the image is running, it is surprising that there are failures!

This could possibly be three things:

First, it could be a RAM limitation. What system are you running on? If it is a Mac we’ve found that Docker by default limits to very little memory and we recommend >8Gb at a minimum. You can change these Docker settings to allow more memory.

Second, as you’ve brought up, the most common issue we’ve had (again with Docker on Mac systems) is binding the license.txt path to the image. It sounds like you’ve found one solution (manually mounting the path in the docker). Two other solutions are [1] to literally just copy the txt file to the current directory and used “$(pwd)/license.txt:/extra/freesurfer/license.txt”, or [2] use another OS! We realize this isn’t always possible, but we’ve found running Docker on a Mac to be more of a headache than its simplicity on other systems. We again apologize for even including the one freesurfer command and will hope to eliminate needing this license file in the future!

Finally, it could have literally just failed! Our first few steps are skull strip (bet), registration (flirt) and segmentation (FAST) which are pretty robust, but it is possible that one failed. If these are pipeline and analysis issues (rather than Docker issues and syntax) then we can try debugging on our end (if you are allowed to share an example dataset) - although I suspect these are Docker memory issues.

Thanks for the suggestions. You were correct that my memory was very low. I changed the following parameters.
CPUs = 6
Memory = 9 GB
Swap = 1 GB
Disk image size = 59 GB

However, I am still get the issue later in the script if I have 2 dockers running at 1 time. I assume this may be due to memory limits or something.

I wonder, is there a way for me to put a for loop inside the docker command so that I can run this on all my subjects without having to go in after each subject finishes since I can’t seem to run multiple instances without running into errors?

Maybe change

sudo docker run --rm \

-v /Volumes/DANIEL/EPC/analysis/EPC001.pre/input:/INPUTS/ \

-v /Volumes/DANIEL/EPC/analysis/ECP001.pre_correct:/OUTPUTS/ \

-v /Applications/freesurfer/license.txt:/extra/freesurfer/license.txt \

–user $(id -u):$(id -g) \

justinblaber/synb0_25iso:latest

to something like …?

sudo docker run --rm
foreach subj (EPC001 EPC002 EPC003)
foreach cond (pre post)
-v /Volumes/DANIEL/EPC/analysis/${subj}.${cond}/input:/INPUTS/ \

-v /Volumes/DANIEL/EPC/analysis/${subj}.${cond}_correct:/OUTPUTS/ \

-v /Applications/freesurfer/license.txt:/extra/freesurfer/license.txt \

–user $(id -u):$(id -g) \

justinblaber/synb0_25iso:latest

Any suggestions. I will also update if the script running on it’s own doesn’t work.

Thanks,
Daniel