pyushkevich / ashs

Automatic Segmentation of Hippocampal Subfields
http://www.nitrc.org/projects/ashs
GNU General Public License v3.0
16 stars 4 forks source link

Issue casting Philips NIfTI images to short (16-bit) type #6

Open jhuguetn opened 2 years ago

jhuguetn commented 2 years ago

One of the early ASHS steps (ashs_template_qsub.sh) casts both MPRAGE and TSE images to 'short' data type, see ashs_template_qsub.sh#L62 and ashs_template_qsub.sh#L112.

Our MRI data was acquired in a Philips scanner, vendor known for the complexity to deal with its scaling transformations (see here). Thus, my dcm2niix-converted NIfTIs include a high scaling slope value (multiplicative factor applied to the image stored values) which leads to large ranges of intensities once applied to image data. This Philips eventuality combined with the aforementioned casting transformation applied by ASHS, leads in some cases to bad registration and segmentation results.
Example of c3d $IN_IMG -type short -o $OUT_IMG casting results, image

I found someone here posting a similar issue and the solution proposed was using ANTS to transform the image intensities to a given range (0-1000) before running ASHS.
In addition, the ashs_template_qsub.sh script has a commented line suggesting to apply a linear transformation of the intensities with c3d itself to 0-4096 but that was somehow discarded do to some further troubles with old atlases. See,

### TODO: I took this out because it was messing up CL with old atlases!
### c3d $ASHS_MPRAGE -stretch 1% 99% 0 4096 -clip 0 4096 -type short -o $SUBJ_MPRAGE

What approach would you primarily recommend to mitigate/fix that issue and be able to run ASHS normally on those images?

Thanks in advance, Jordi

ajschadler12 commented 1 year ago

Not sure if relevant, but I had a similar issue. Though the original issue was using another pipeline, I found similar fixes worked for ASHS.

Steps to fix:

  1. Replace ext/Linux/fsl/{bet2,flirt} binaries with symbolic links to binaries from fsl 6.0.2 or above
  2. In bin/ashs_template_qsub.sh, replace the c3d call with freesurfer's mri_convert (DO NOT INCLUDE -odt short!)

ASHS will run like normal. I did not notice any peculiarities with the ASHS output on non-short data.

jhuguetn commented 1 year ago

Thanks @ajschadler12, that's enlightening! In general, I prefer not to manually modify embedded dependencies of packages/tools unless it's being labeled under a new version tag. Just for the sake of reproducibility and comparability of results.
Perhaps, that raises a good case for releasing a new ASHS version upgrading its inner dependencies (ie. ANTS and FSL)?

FYI, the workaround I used for mitigating the issue was to 'revert' the application of the Philips scaling slope (which is unnecessary for running ASHS). That is, divide the image scaled values by its final slope value before feeding it to the ASHS pipeline.

ajschadler12 commented 1 year ago

Ah, thank you for mentioning that. I will be presenting data processed using the modifications I mentioned at a conference soon. I will need to keep that in mind when we move forward with publishing!

FYI, the workaround I used for mitigating the issue was to 'revert' the application of the Philips scaling slope (which is unnecessary for running ASHS). That is, divide the image scaled values by its final slope value before feeding it to the ASHS pipeline.

I had two questions:

  1. I was wondering if you could provide a quick code snippet for how you re-scaled your images? It sounds like you scrape the slope value using a tool like fslhd then divide the image by it, but I just wanted to make sure.
    • I found a discussion you had with effigies on neurostars about messing with the slope. Looks like I can query slope values nibabel.nifti1.Nifti1Image.dataobj.slope and can just get the unscaled image using get_unscaled()
  2. I will be including an ASHS analysis for a larger pipeline we use. Some of the data we will be using have similar scaling issues. Would you happen to know of a simple heuristic I could use to detect if an image needs to be re-scaled before being fed to ASHS (perhaps detecting if the scaling slope exceeds a certain cutoff)?
jhuguetn commented 1 year ago

1) Sure, here you go. What I do in a nutshell is quite close to what you suggested, pick the slope (via fslval) and divide the image intensity values for the slope value using fslmaths. For images not affected, their slope is usually 1 so it's harmless. In addition, having an scaling slope applied to MRI image data is not required for running a segmentation procedure.

# FIX: undo Philips scaling factor applied by dcm2niix to the input images
#      before they go into the pipeline to avoid further inconsistencies when
#      having data casted to 'short' type by ASHS.
SLOPE=$(fslval ${T1_NII_IMG} scl_slope)
CMD="fslmaths ${T1_NII_IMG} -div ${SLOPE} ${T1_NII_IMG}"
echo "[info] CMD: "$CMD; $CMD

2) For our data, troubled images included a (2005,100E) PhilipsScaleSlope DICOM tag with Philips-only rescaling details. The formula used by dcm2niix to convert the images to NIfTI uses this private Philips field and generates a large final Slope value. You could control that field in your case perhaps. Otherwise and as I said, I don't see a problem in disabling the scaling slope in all the cases as is not going to add anything useful for the segmentation pipeline IMO.