Dwigradcheck

Hi @rsmith or @jdtournier

Simple question: How do I read the dwigradcheck table? Is this suggesting a x-axis flip?

Mean length     Axis flipped    Axis permutations    Axis basis
60.26            0                (0, 1, 2)           image
59.74            0                (0, 1, 2)           scanner
37.79            2                (0, 1, 2)           image
37.24         none                (0, 2, 1)           scanner
37.21            0                (0, 2, 1)           image
37.07            2                (0, 1, 2)           scanner
36.54         none                (0, 2, 1)           image
36.39            0                (0, 2, 1)           scanner
35.52            2                (2, 1, 0)           scanner
35.38            1                (1, 0, 2)           scanner
34.92            0                (2, 1, 0)           image
34.91            2                (2, 1, 0)           image
34.89            0                (2, 1, 0)           scanner
34.88            1                (0, 1, 2)           image
34.83         none                (0, 1, 2)           image
34.79         none                (0, 1, 2)           scanner
34.75            0                (1, 0, 2)           image
34.54            1                (0, 1, 2)           scanner
34.51            1                (1, 0, 2)           image
34.36            0                (1, 0, 2)           scanner
29.04            2                (0, 2, 1)           scanner
29.02            1                (0, 2, 1)           image
28.18            2                (2, 0, 1)           scanner
27.78         none                (2, 0, 1)           image
27.53            1                (1, 2, 0)           scanner
27.36            1                (2, 0, 1)           image
27.27            1                (0, 2, 1)           scanner
27.16         none                (1, 0, 2)           image
27.14            2                (1, 0, 2)           scanner
27.11            0                (2, 0, 1)           scanner
27.10            2                (1, 2, 0)           image
27.03         none                (1, 2, 0)           image
27.00            2                (0, 2, 1)           image
26.80            0                (1, 2, 0)           scanner
26.80            2                (1, 2, 0)           scanner
26.39            0                (1, 2, 0)           image
26.39         none                (1, 0, 2)           scanner
26.36            1                (2, 0, 1)           scanner
26.34         none                (2, 0, 1)           scanner
26.28         none                (2, 1, 0)           scanner
26.25         none                (1, 2, 0)           scanner
26.25            1                (1, 2, 0)           image
26.22            2                (2, 0, 1)           image
26.18            0                (2, 0, 1)           image
25.99         none                (2, 1, 0)           image
25.99            2                (1, 0, 2)           image
25.79            1                (2, 1, 0)           image
25.60            1                (2, 1, 0)           scanner

Hey Adam,

Yep: if you flip the x-axis, the mean streamline length is almost double that compared to if you perform no such flip, and it’s a pretty clear standout winner.

The ambiguity is whether this flip should be applied in image space (equivalent to negating values in the first row of the bvec file) or scanner space (equivalent to negating values in the first column of the gradient table in MRtrix format). If your image axes are very close to the scanner principal axes, then it’s just about impossible to figure out which of the two should be applied based on this heuristic. But your prior processing might provide a clue. E.g. If you’ve just imported DICOM data, and the nature of the data coming from your scanner vendor means that the gradient orientations are stored within the DICOM headers in scanner space, then you probably want to do the flip in scanner space. If your data have been somehow processed by some other software package, which has involved conversion to/from NIfTI / bvecs at some point, and especially if that software isn’t guaranteed to deal with the bvecs coordinate system handedness issue, more likely the error has been applied in image space and so should be corrected there. But the closer your images axes are to the scanner axes, the less important the distinction becomes.

Cheers
Rob

1 Like

Hi I have a follow up question on this as I have a similar issue. The output of my dwigradcheck looks like this:

Mean length Axis flipped Axis permutations Axis basis
95.03 0 (1, 0, 2) scanner
91.44 1 (1, 0, 2) image
54.66 none (1, 0, 2) scanner
54.52 2 (1, 2, 0) image
53.68 none (2, 0, 1) scanner
53.53 2 (2, 0, 1) image
53.41 2 (1, 0, 2) image
53.16 none (1, 2, 0) image
53.05 0 (1, 2, 0) scanner
52.83 2 (1, 2, 0) scanner
52.59 1 (1, 2, 0) image
52.46 1 (1, 0, 2) scanner
52.38 0 (1, 0, 2) image
52.22 none (1, 2, 0) scanner
51.53 1 (1, 2, 0) scanner
51.32 0 (1, 2, 0) image
50.38 0 (0, 1, 2) image
50.37 1 (2, 0, 1) image
50.25 0 (0, 1, 2) scanner
49.79 0 (2, 0, 1) scanner
49.58 none (1, 0, 2) image
49.31 2 (1, 0, 2) scanner
49.25 1 (0, 1, 2) scanner
48.77 1 (0, 1, 2) image
47.99 none (0, 1, 2) scanner
47.83 none (0, 1, 2) image
47.65 0 (2, 1, 0) scanner
47.10 2 (0, 1, 2) image
46.66 2 (0, 1, 2) scanner
46.51 0 (2, 1, 0) image
45.65 0 (2, 0, 1) image
45.48 1 (2, 0, 1) scanner
45.45 2 (0, 2, 1) image
45.37 none (2, 1, 0) scanner
45.23 none (2, 1, 0) image
44.83 1 (2, 1, 0) scanner
44.71 none (0, 2, 1) scanner
44.70 2 (2, 1, 0) image
44.67 1 (0, 2, 1) scanner
44.65 2 (2, 1, 0) scanner
44.43 none (2, 0, 1) image
44.41 2 (2, 0, 1) scanner
44.33 none (0, 2, 1) image
44.30 1 (2, 1, 0) image
44.05 0 (0, 2, 1) image
43.31 0 (0, 2, 1) scanner
42.60 1 (0, 2, 1) image
42.56 2 (0, 2, 1) scanner

The dicoms that I pull off my scanner don’t have any diffusion gradient tables (it is a Siemens XA Vida but I currently have to anonymise all the data and I understand that sometimes removes some important dicom header info) so I have to always give it one using -grad.
Am I understanding your advice correctly above that the best action for me would be to edit this gradient vector file and change the values in the first column? So if the first few look like this:
0, 0, 0 ,0
0.887457431839749, -0.363247150950841, -0.283673780950044 ,400
0.568088287950483, -0.822003244736793, -0.0398291694072874,400
-0.133723725688416, 0.948874806417039, -0.285927555396532,400

I should edit to be:
0, 0, 0 ,0
-0.887457431839749, -0.363247150950841, -0.283673780950044 ,400
-0.568088287950483, -0.822003244736793, -0.0398291694072874,400
0.133723725688416, 0.948874806417039, -0.285927555396532,400

??

Thanks

Caitlin

Just a quick update, I am guessing it’s something more complicated as I tried what I thought you were recommending above and it didn’t help. My FA maps look like this:

Hi Caitlin,

Indeed, inverting the x axis won’t be sufficient in this case: it looks like it’ll need at least a swap of the x & y axes (so that the red & green channels swap around). But it’s still difficult to know whether that’s actually correct, you might still need to also invert the x or y components.

On top of which, it’s hard to know whether the swap/inversion needs to happen in scanner or image space (probably scanner space on a Siemens, but it depends where your gradient table actually came from and how confident you are that this is what the scanner actually played out). That starts to matter when you have any slice angulation, since then the two coordinate systems no longer coincide.

All this to say, it’s worth being paranoid about getting this right.

I’m a bit puzzled by your dwigradcheck output, it seems a lot longer than I’d expect. And did the script not produce an updated version of the table…? @bjeurissen might be able to shed some light here.

On a final note: I’d strongly recommend against using the on-scanner anonymisation on this generation of scanners. It strips out so much information that the images are often unusable – and not just the gradient table. @Chris_Rorden has spent quite a bit of time looking into this and came to the conclusion that the data is often beyond rescue when anonymised that way. I’ve also had a look and came to the same conclusion. I strongly recommend exporting the data normally (maybe as enhanced DICOM) and anonymising afterwards if necessary.

Happy to discuss further face to face next week if you wish!

Cheers,
Donald

@caitlinob my center has not upgraded to XA, and I am not sure if things have changed with the recent versions of XA (e.g. XA30). However, with prior versions of XA saving data on the scanner as anonymized had catastrophic consequences, which I documented here. I strongly advise you to heed the specific warning from Siemens engineers to use an offline/in-house anonymization software instead if you intend to use these data for research purposes. If your MR center has a Siemens Research Master Agreement in place, there will be a Siemens Research Collaboration Manager assigned to your center. I encourage you to work with them to lobby for anonymization which does not strip crucial sequence details. Since Siemens gradients are described in scanner space, you need to transform them for slice angulation, which typically varies for each session.

Thanks for confirming, Chris!

Just to clarify one aspect though. When you say:

This applies to gradients stored as bvecs, which are specified relative to the image axes. If the gradient table is stored in MRtrix ‘grad’ format, no transformation for slice angulation would be necessary in that case, since in that format the gradients are specified relative to scanner coordinates.

And as a final disclaimer: Siemens will generally assume gradients in scanner space, but if you passed a custom gradient table (by supplying your own .dvs file) and you happened to specify CoordinateSystem as prs rather than xyz, then the gradients played out will follow the image axes, and you’ll still have to worry about slice angulation… Of course, if you hadn’t used anonymisation and the gradient table had been preserved, you would actually have the correct directions in scanner space (they’d be rotated relative to what you specified in your gradient table, but nonetheless correct in terms of what was played out relative to scanner space).

Just in case things weren’t confusing enough…

Thanks both for your quick replies.
Yes I am aware of the struggles of anonymising the data but currently I have no option, I can explain more in a less public discussion perhaps. We do not have a Research Master Agreement with Siemens for this site.

If it did output an updated version of the table, I could not find it in an obvious place. I’ll try again.

Ok so essentially if I cannot get the gradient diffusion directions from the dicom header (because of anonymisation) I have to make sure there is zero angulation in the acquisition? I have a volunteer booked on Monday so I will give this a go.

Just to be clear: this won’t fix the issue, it just sidesteps one potential headache. You will still have the problems you show, but the list of possible fixes will be shorter and less ambiguous.

If you have a volunteer booked, I really strongly recommend you heed @neurolabusc’s advice and avoid the on-scanner anonymisation. There’s no need for a research agreement to do this, and you can provide anonymous IDs & an approximate DOBs instead of the actual patient name if you absolutely need the anonymisation – though that obviously depends on what policies you need to abide by.

Happy to chat about this in private if you prefer. You can reach me on Teams via my KCL account.

Hi @rsmith,

Question on this as I’m dealing with a different dataset and I finally much better understand your point far above about whether the flip needs to occur in image vs. scanner basis. Is there a way to compel dwigradcheck to choose the axis basis when outputting the corrected table. For instance, I’m certain that the flip needs to occur in the image axes but would like to automate this across the subjects and it isn’t always consistent which choice (scanner, image) is the “best”.

1 Like

@rsmith… looking at some output logs, it is as simple as export_grad_mrtrix is scanner basis and export_grad_fsl is image basis?

I think this one should be directed at @bjeurissen:stuck_out_tongue_winking_eye:

Then I tag @bjeurissen for good measure. Thanks @jdtournier.