Using Bruker 2dseq file: beware RECO_slope

Just wanted to thank the MRtrix developers for helping users use Bruker data through the convert_bruker python script, which generates a header file for use with the data. The default binary data file that is specified for use is 2dseq, which is the Bruker raw data in binary format. I just wanted to point out that using this binary data will give you wrong results (like FA>1), since each set of diffusion images may have a different reconstruction scaling factor (instead of one scaling factor that is used for all images). You can find the different scaling factors in the RECO_map_slope parameter in the reco file. You can get around this by converting the 2dseq file to another format, using a software tool that understands that the slope parameters are different.

Thanks for pointing that out, I’ll see if we can fix this. Incidentally, do you have any hard information on how Bruker store their data? The current script really was a quick & dirty hack to try to read in the data, given that the Bruker DICOM export was somewhat lacking. I’ve basically gone through the text headers to see if I could identify anything relevant. But I’ve found no reference information about this online…

One question though: I’m hoping the RECO_map_slope parameter is constant for a given 2dseq file? Otherwise that would require quite a bit of extra work… And is there a corresponding RECO_map_offset or equivalent to worry about too?

The bruker 2dseq is a simple binary file with no header. The word size is described by RECO_word_type, byte order is in RECO_byte_order. The pixel values are written sequentially, line by line, frame by frame, starting from the top left pixel of the first frame. In the DWI experiment, it stores the slices of the first diffusion direction (usually Ao), then the slices of the second diffusion direction, and so forth.

Unfortunately yes, the RECO_map_slope parameter is different for each diffusion scan. The reco file lists out all the slope values for each slice, and it looks like at least the slices from one diffusion experiment all have the same slope value. You have to divide the binary data by the RECO_map_slope. Fortunately, the offset seems to be all zero (at least for my version of Bruker scanning software, Paravision 5.1). Thanks for your work on this!

Thanks for all this information. It sounds like supporting this properly is going to require a fair bit of effort… The other outstanding issue is importing the slice orientation information, and ensuring the DW scheme is also correctly imported. I’m not sure I’ll have the time to look into this any time soon. Happy to assist if anyone wants to tackle this, though… :wink:

Hmmm… I might be able to help, if I can stay in python or matlab. :grin: What would you have in mind?

I also wouldn’t mind seeing what I could do to help with modifying the code so that I can input the b gradients as a b matrix, instead of just a b-value/gradient vector pair. The gradient cross terms are not insignificant in a small-bore preclinical scanner.

Is the slice orientation information really critical to import correctly? In my data processing, I just let MRtrix reset to “sane” defaults (zero angles and corner at origin?), because I know that the DW gradient vectors are in the read/phase/slice frame (as opposed to the physical x/y/z gradient directions). Shouldn’t this be enough for the accuracy of the FOD/TWI results? Of course, getting the slice orientations wrong would prevent you from aligning with other scans with proper orientation, but I am not so concerned with this.

In the initial stage, maybe. The problem is that if we have to scale all the data by the RECO_map_slope, it requires a different approach than the current one. At the moment, all the script does is produce an MRtrix3 compatible header that then references the original raw data (so no copy involved). If we need to scale things differently per volume, then we’d need to convert the data to floating-point format and scale accordingly into a separate file. All do-able with Python, but suddenly a lot messier…

In the long run, I think this is something that would be better managed with MRtrix3’s own image handling backend, but that would require some coding effort. I don’t mind doing this, but what I can’t commit to is testing this to death to make sure all edge cases are appropriately handled. That means getting the transform information right, verifying that the DW orientations are correct across a range of different acquisition scenarios, etc. I’d need a lot of test data, and more importantly, someone to figure out how to extract the relevant information from the headers and interpret it correctly.

So if we can fix up the python script to a level where we’re confident that it handles things well, I’d be happy to write the direct import code at that point. But what I’d like to have is some guarantees that the Python import is solid before I do this…

So you could do this, but bear in mind there is no support within MRtrix3 for the full b-matrix. While we do provide a tensor-fitting routine, it’s very much a low priority for us. There is no real way to handle full b-matrices within a HARDI / multi-shell HARDI framework. There is some recent research from other labs that might be able to handle this in future, but it’s certainly not implemented within MRtrix3, and we have no plans at the moment to do anything about it…

In general, you would be much better off making sure the sequence does not generate large cross-terms. That used to be a problem when the read-dephase gradient was played out at the same time as the 90° slice refocus gradient, before the DW gradients - most other gradients don’t have anywhere near the same effect. If your sequence is still doing this, it’s about 20 years out of date… Also, it’s now recommended to disable the 180° crushers for b>0 images, since the DW gradients are essentially enormous crushers anyway. If you do all of this, there’s essentially nothing but the very short 180° slice-select gradient to worry about, and that self-refocuses very quickly, so should only produce tiny cross-terms.

I guess it’s OK if we know the DW gradients are always relative to the read/phase/slice - I’m just paranoid about getting these things wrong - although it’s admittedly not as big an issue on a preclinical scanner as it might be in a pre-surgical environment… Would be good to get right though.

OK, I can work on this. I already have some python code that correctly scales the binary data per volume, but will have to work on getting the slice orientations correct. This would be useful in my other projects, so this work will serve multiple purposes.

As for the gradient vectors being in the read/phase/slice frame, I guess we will have to trust that Bruker software is reporting this correctly. There is an option to define the gradient vectors in the magnet x/y/z frame before acquisition, but the manual does state that the vectors are transformed into the r/p/s frame before storing them in the header file.

Good to hear! Thanks for helping out, I’m sure others will appreciate this too.

By the way, this discussion is relevant here, worth taking a quick look.