Obtaining N slice indices in native space, equidistant along centerline

I would like to be able to obtain a list of N slice indices that are equidistant along the centerline in an image of interest (e.g. t2.nii.gz), between lower and upper bounds of my choosing. The bounds would be delimited by the file labels.nii.gz, where a binary mask labels two points: one at the lower bound of interest (e.g. mid vertebra C2) and one at the upper bound of interest (e.g. mid vertebra C5). More specifically:

INPUT

  • t2_centerline.nii.gz (obtained by running: sct_get_centerline -i t2.nii.gz -c t2)
  • labels.nii.gz (obtained by running: sct_deepseg_sc -i t2.nii.gz -c t2; sct_label_vertebrae -i t2.nii.gz -s t2_seg.nii.gz -c t2; sct_label_utils -i t2_seg_labeled.nii.gz -vert-body 2,5)
  • N (integer value corresponding to the number of slices of interest)

OUTPUT

  • Integer list of length N (each entry corresponding to a slice index)

Is there an SCT tool that already does this or should I create a new script for this? Thank you!

Find N slices that are approximately equidistant along the centerline (NOT along S-I axis!)

Solution uses the Centerline.length and Centerline.progressive_length attributes. For instance, for the following inputs:

  • N_slices: integer value predetermined by the user
  • labels.nii.gz: a file containing a label of the upper and lower boundary
  • t2_seg.nii.gz: a file containing a spinal cord mask

One could run the following code:

# Read data into Image objects
im_seg = Image('t2_seg.nii.gz').change_orientation('RPI')
im_boundary = Image('labels.nii.gz').change_orientation('RPI') 

# Get z-index in pixel space of lower and upper bound within which we want to obtain our N slices
X, Y, Z = (im_boundary.data > NEAR_ZERO_THRESHOLD).nonzero()
min_z_index, max_z_index = min(Z), max(Z)
z_ref = np.array(range(min_z_index,max_z_index+1))

# Get centerline
param_centerline = ParamCenterline(algo_fitting='optic',contrast=image_contrast) 
im_centerline, arr_ctl, arr_ctl_der,fit_results = get_centerline(im,param=param_centerline, verbose=1) 
    
# Create Centerline object within min_z_index and max_z_index
ctl = Centerline(points_x=arr_ctl[0,z_ref],points_y=arr_ctl[1,z_ref],points_z=arr_ctl[2,z_ref], deriv_x=arr_ctl_der[0,z_ref],deriv_y=arr_ctl_der[1,z_ref],deriv_z=arr_ctl_der[2,z_ref])

# Find N slices that are approximately equidistant along the centerline
dist_between_slices = float(ctl.length/(N_slices)-1)
slices_z=[0]
i = 0
for slices_i in range(1,N_slices):
        dist_upper=0
        dist_lower=0
        while (dist_upper < dist_between_slices) and (i < len(ctl.progressive_length)):
            dist_upper+= ctl.progressive_length[i]
            i+=1
        dist_lower = dist_upper - ctl.progressive_length[i-1]
        interslice_dist.append(dist_upper) if (abs(dist_upper-dist_between_slices) < abs(dist_lower-dist_between_slices)) else slices_z.append(i-1)
slices_z = np.array(slices_z)
slices_z += min_z_index
1 Like