Snr computation

Hi,
I would like to know how to compute SNR on a diffusion image in SCT. I have inspected sct_compute_snr but I could not understand what to put instead of -vol option.
best regards,
Rosella

Hi @Rosella_Tro,

Thank you for reaching out. So, let’s start with an example dMRI dataset:

# Download example data
sct_download_data -d sct_example_data
# Go to DWI data
cd sct_example_data/dmri

So, at this point there are different ways to compute SNR on a dMRI dataset. One way to do it, is to compute it on the b=0 images only, to remove bias from the diffusion-related signal attenuation, ie: you want to quantify thermal noise only.

To identify where the b=0 images are, you can run this:

sct_dmri_separate_b0_and_dwi -i dmri.nii.gz -bvec bvecs.txt

The output is:

[...]
Identify b=0 and DWI images...
  WARNING: bvecs file is 3xn instead of nx3. Consider using sct_dmri_transpose_bvecs.
  Transpose bvecs...
  Number of b=0: 5 [0, 31, 32, 33, 34]
  Number of DWI: 30 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
[...]

Now that you know where the b=0 images are, you can use them to compute SNR using the “mult” method, as described in [Dietrich et al. J Magn Reson Imaging 2007]. In brief, with this method, noise standard deviation (SD) is computed across time. So you need enough samples (ie: volumes) to compute a reliable SD. Here, we have 5, which is “borderline”.

sct_compute_snr -i dmri.nii.gz -method mult -vol 0,31:34

This outputs the file dmri_SNR-mult.nii.gz, which shows the voxel-wise SNR:

If you have a mask of the spinal cord, you could input it to extract SNR inside the cord. That’s what we are going to do here:

sct_deepseg_sc -i dmri_dwi_mean.nii.gz -c dwi -qc qc

Which gives us this spinal cord mask:

Which we can then use to extract average SNR in the spinal cord at each slice:

sct_extract_metric -i dmri_SNR-mult.nii.gz -f dmri_dwi_mean_seg.nii.gz -o snr_mult.csv

Output:

Slice (I->S) Size [vox] WA() STD()
0 80 8.379061 5.376076701355050
1 81 7.6254206 2.9527455242505100
2 85 8.024328 7.179199467822250
3 91 8.088527 3.894383220097640
4 92 8.511543 4.6690126153706500
5 86 8.035383 3.9745487892725800
6 88 7.688621 3.20418832388819
7 87 7.3579865 3.135453706609150
8 82 7.112298 3.190911953956170
9 77 7.7654552 3.780912526101250
10 78 7.026523 3.4383660352603000
11 71 6.530175 2.9450315953682500
12 70 6.7164145 3.3545565803044500
13 75 7.267548 4.877266381484310
14 71 6.702518 2.739299068038260

Now, let’s look at another approach to compute SNR, which is based on the difference between two images and the computation of the noise SD within a spatial mask (as opposed to across time, as done with the “mult” method). With this method, you need to input a mask that specifies the region where noise SD is computed. In general, the mask is defined in a region of interest, and one assumption is that noise SD is invariant across voxels in the mask (this property is called homoscedasticity). Here, we will use the spinal cord mask:

sct_compute_snr -i dmri.nii.gz -m dmri_dwi_mean_seg.nii.gz -method diff -vol 31,32

Output:

SNR_diff = 5.891875075931879

:information_source: When using the “diff” or “mult” methods, it is important that images are co-registered before computing SNR. Also, the interpolation used for motion correction should not be linear or sinc, because it will alter noise property. Interpolation should only be nearest-neighbour.

thank you as always for your clarity :slight_smile:
best,
Rosella

1 Like