FSL-MRS trouble loading sagittally acquired MRSI data

Hello everyone,
I am a Post-Doctoral fellow at UC Irvine working in the Stark lab and we just started using FSL-MRS to analyze some of our spectroscopy data. I have been successful in using it to analyze the single voxel data with no problems and loving it! It also worked okay for typical axially acquired data for another lab member but I am running into some trouble with loading up our MRSI data: Our MRSI data was bit atypical in the sense we were trying to collect it in the sagittal plane. Not sure if collecting data that way is itself problematic or it is a loading/conversion issue. The single voxel mrs_segment runs fine on the same subject’s data. I would really appreciate any thoughts/help with this!
The spec2nii conversion itself ran without issue
Here is a screenshot of simply loading up the data in fsleyes - the plane is correct but the span looks much larger than where data was collected from and not sure what the bright voxels are supposed to be that is also not where the data was collected from it was more of a small rectangle in the same sagittal plane inside the one seen.

And here is the exact mrsi_segment error:
mrsi_segment -a Anat/T1.anat MRS_Dicom/pilot01_CSI.nii.gz
sform and qform not identical in image /Pilot01/Anat/T1.anat/T1_fast_pve_0.nii.gz
Traceback (most recent call last):
File “/home/pia/miniconda3/bin/mrsi_segment”, line 10, in
sys.exit(main())
File “/home/pia/miniconda3/lib/python3.9/site-packages/fsl_mrs/scripts/mrsi_segment.py”, line 72, in main
applywarp_func(anat / ‘T1_fast_pve_0.nii.gz’,
File “/home/pia/miniconda3/lib/python3.9/site-packages/fsl_mrs/scripts/mrsi_segment.py”, line 63, in applywarp_func
applywarp(str_resolve_path(i),
File “/home/pia/miniconda3/lib/python3.9/site-packages/fsl/wrappers/wrapperutils.py”, line 1152, in wrapper
result = fot(*args, **kwargs)
File “/home/pia/miniconda3/lib/python3.9/site-packages/fsl/wrappers/wrapperutils.py”, line 796, in call
result = func(*args, **kwargs)
File “/home/pia/miniconda3/lib/python3.9/site-packages/fsl/wrappers/wrapperutils.py”, line 1194, in wrapper
return fot(*args, **kwargs)
File “/home/pia/miniconda3/lib/python3.9/site-packages/fsl/wrappers/wrapperutils.py”, line 796, in call
result = func(*args, **kwargs)
File “/home/pia/miniconda3/lib/python3.9/site-packages/fsl/wrappers/wrapperutils.py”, line 197, in wrapper
return runner(cmd,
File “/home/pia/miniconda3/lib/python3.9/site-packages/fsl/utils/run.py”, line 395, in runfsl
return run(*args, **kwargs)
File “/home/pia/miniconda3/lib/python3.9/site-packages/fsl/utils/run.py”, line 233, in run
raise RuntimeError(’{} returned non-zero exit code: {}’.format(
RuntimeError: /usr/local/fsl/bin/applywarp returned non-zero exit code: 1

Here is the data :
MRSI_Data.zip (3.8 MB)
T1_fast.zip (2.9 MB)

Hi @pia,

Let’s check if the orientation and position is correct first before figuring our what’s happening with the segmentation.Correct me if I’m wrong, but I think you are saying that the orientation (angle of the slab) is correct. Is the left-right position and thickness also correct?

How large do you expect the whole field of view to be? Note that this might be different to any inner volume selected (with a white voi box on the scanner, assuming that this is from a Siemens scanner). What anatomy are you expecting the signal to come from? The bright voxels are simply the magnitude of the first point in the FID, so there is probably a lot of signal in them e.g. from water or lipid. Possibly as a result of the high off resonance in that area, or something that has gone wrong with conversion.

Regarding the actual MRSI segmentation error it looks like an error with the data in the .anat reulsts. sform and qform not identical in image /Pilot01/Anat/T1.anat/T1_fast_pve_0.nii.gz is the error. Has this image been changed at all after fsl_anat has been run? Could you provide the results of fslhd /Pilot01/Anat/T1.anat/T1_fast_pve_0.nii.gz?

BW

Will

Hi @wclarke,
Thanks for getting back. Yes, the orientation, position and thickness look correct. Attached is the screenshot from Siemens.

The images were not modified after fsl_anat and I did not have problems with svs_segment for data from same subject’s single voxel. Attached is fslhd report for both the fast_pve0 and the CSI
fslhd_T1pve0.txt (1.4 KB)
fslhd_CSI.txt (1.4 KB)

So I think the MRSI converted correctly. The extent of the image looks the same as the MRSI grid (green/yellow UI element).

Regarding the bug, it looks like the data does have a tiny mismatch in the sform and qform. Note the first element of the two matrices. Im not sure what has caused this, is it the same in the original T1 data? Could you try the following command on T1_fast_pve_0 to fix make the two matrices match?

fslorient -copysform2qform

The qform and sform of the original data looked equal. I think something is going wrong during fsl_anat.
So I tried a few things:

  1. fslorient -copyqform2sform on T1_fast_pve_0. That led to following error : sform and qform not identical in image /tmp/tmpsxrxelxq/tmp5a6hztk9.nii.gz
    So it is still looking at some temp file that hasn’t updated. To address this I tried
  2. Copying qform2sform for all files in the .anat folder but that did not address it either - still relying on some file in /tmp/ that might be created using transformation matrix (?).
  3. So I used fslorient -copyqform2sform on the original T1 image just in case there was small difference in the q and sform because of precision and Reran fslanat. But, still the sform and qform not identical for T1_fast_pve and same as above simply copying the qform to sform is not enough as it is looks at some other file in tmp.
  4. Simply reran dicom to nifti conversion using SPM instead of MRICro. This also leads to unidentical qform and sform in the fast_pve_0 and some step conversion in fsl_anat
  5. Then tried this on different subject’s axial and sagittal MRSI data but still the exact same issue. The T1 sequence used for this subject was also different.

The tmp file usage is coming from applywarp_func that relied on wrapperutils in run.py. Attached is a screenshot

My fsl_mrs was using the wrapperutils from the 6.05.1 version which is what leads to the creation of tmp files with unequal qform and sform in the first place.

I thus tried using mrsi_segment -t T1spm.nii.gz -o CSI MRS_Dicom/pilot01_CSI.nii.gz
but that leads to an error as well!
Traceback (most recent call last):
File “/opt/fsl-6.0.5.1/fslpython/bin/mrsi_segment”, line 10, in
sys.exit(main())
File “/opt/fsl-6.0.5.1/fslpython/lib/python3.9/site-packages/fsl_mrs/scripts/mrsi_segment.py”, line 46, in main
if (args.anat is None) and (not args.mask_only):
AttributeError: ‘Namespace’ object has no attribute ‘mask_only’

If I simply edit that line out to not look for args.mask_only the fsl_anat runs and then we reach the same qform not equal to sform error from before.

Finally, I figured out that using older version FSL-6.0.1 does not lead to the sform & qform mismatch. So I used older version of FSL and mrsi_segment runs without errors but I think the files it created though correct in size 16*32 are empty.

@wclarke And mrsi_segment did not create a binary mask which is required to run the next step. I don’t see the module in mrsi_segment that does it. Is there a separate function/previous step I missed to create the mask?

Hi @pia,

Sorry for taking a couple of days to respond. From your fairly detailed testing it looks like something is going wrong in fsl_anat rather than FSL-MRS. The mrsi_segment simply uses a few python wrappers which directly call the command line FSL tools. Are you able to ask this question over on the FSL mailing list? That way we can bring in the FSL devs and try to get to the bottom of the issue with fsl_anat.

Regarding using the earlier version of FSL mrsi_segment actually only does a single thing, it uses the applywarp FSL tool to register (without any optimisation) the FAST segmentation results to the MRSI image. There is one small step where an empty file is created, simply because applywarp won’t work on complex data, even though it doesn’t actually need any access to the data, just the headers.

Hi @wclarke ,
I did post on the fsl mailing list but I am yet to get a solution to the problem. My guess is that it has to do with precision but I will keep you posted.

Meanwhile using older version of FSL 6.0.1 including the older applywarp should in principle work. And mrsi_segment does run without any error and creates files. The two issues I had with that were:

  1. Yes, the tmp file is empty because applywarp doesn’t like complex data but the files after mrsi_segment the gm/wm/csf.nii.gz files are also empty (only zeroes)). Although they are now correctly shaped as the csi slab. So, something still seems to be upsetting the applywarp function - the CSI shaped segmentation nifti it created has unequal sform and qform, and has only zeroes instead of ones and zeroes even though the fsl_anat does good segmentation job and created T1_fast_pve with equal sform and qform.
  2. The code for creating mask is also missing from the mrsi_segment function. Though, it should be easy to create once I can get past the applywarp problem

Hi Pia,

I’ve replied on the JISC mailing list. There’s a bug in applywarp which will get fixed, but for the meantime you can do the following:

fslorient -copyqform2sform t1.anat/T1_fast_pve_0.nii.gz
fslorient -copyqform2sform t1.anat/T1_fast_pve_1.nii.gz
fslorient -copyqform2sform t1.anat/T1_fast_pve_2.nii.gz
 
fslcomplex -realabs pilot01_CSI.nii.gz tmpabs_mrsi
fslcpgeom pilot01_CSI.nii tmpabs_mrsi.nii.gz
fslorient -copyqform2sform tmpabs_mrsi.nii.gz
 
mrsi_segment -a t1.anat tmpabs_mrsi.nii.gz

Sorry about that!

Thanks @wclarke that worked!
It still did not create a mask - do I simply create one by applywarp on T1_biascorr_brain_mask or is it through some other step?

Hi Pia,

What mask are you expecting it to create? There’s a mask for the fitting stage, but that just enables you to select a subset of voxels in the MRSI to fit. Currently there isn’t an automated way of creating that mask, though fsl/fsleyes has a number of mechanisms that could help.

Will

Hi Will,
I did not want to restrict it to a subset but rather want quantification separately at every voxel in the slab. But, since a mask is a required input for fsl_mrsi I assumed it would be something that is a default output from the mrsi_segment step similar to the single voxel analysis.

Pia

Have i made it a required input? If so thats a mistake which i should correct. I had thought it was optional.

Yup it is required.
fsl_mrsi: error: the following arguments are required: --data, --basis, --mask, --output

Also mrsi_segment errors if you try to use the -t instead of -a flag at line 41 because it looks for mask_only argument.

mrsi_segment -t ANAT/T1.nii.gz CSI/csi_slaser_40.nii.gz
Traceback (most recent call last):
File “/opt/fsl-6.0.5.1/fslpython/bin/mrsi_segment”, line 76, in
main()
File “/opt/fsl-6.0.5.1/fslpython/bin/mrsi_segment”, line 41, in main
if (args.anat is None) and (not args.mask_only):
AttributeError: ‘Namespace’ object has no attribute ‘mask_only’

Right, that’s not good. I’m fixing a few things today and will try to tackle both of these bugs + the original issue with the q/sform

Hi @pia

These issues should now be fixed in V2.0.1. Run

conda update -c conda-forge -c defaults \
              -c https://fsl.fmrib.ox.ac.uk/fsldownloads/fslconda/public/ \
              fsl_mrs

to update.