Source code for spinalcordtoolbox.template

#!/usr/bin/env python
# -*- coding: utf-8
# Functions that utilize the template (e.g., PAM50)

import logging
import numpy as np

logger = logging.getLogger(__name__)


[docs]def get_slices_from_vertebral_levels(im_vertlevel, level): """ Find the slices of the corresponding vertebral level. Important: This function assumes that the 3rd dimension is Z. :param im_vertlevel: image object of vertebral labeling (e.g., label/template/PAM50_levels.nii.gz) :param level: int: vertebral level :return: list of int: slices """ data_vertlevel = im_vertlevel.data slices = [] # loop across z for iz in range(data_vertlevel.shape[-1]): # fetch non-null and finite values data_vertlevel_nonzero = data_vertlevel[..., iz].flatten()[np.nonzero(data_vertlevel[..., iz].flatten())] data_vertlevel_nonzero_finite = [i for i in data_vertlevel_nonzero if np.isfinite(i)] # avoid empty slice if not data_vertlevel_nonzero_finite == []: # average non-null values and round to closest average_value = int(np.round(np.mean(data_vertlevel_nonzero_finite))) # if that matches the desired level, append it to slice list if average_value == level: slices.append(iz) return slices
[docs]def get_vertebral_level_from_slice(im_vertlevel, idx_slice): """ Find the vertebral level of the corresponding slice. Important: This function assumes that the 3rd dimension is Z. :param im_vertlevel: image object of vertebral labeling (e.g., label/template/PAM50_levels.nii.gz) :param idx_slice: int: slice (z) :return: int: vertebral level. If no level is found (only zeros on this slice), return None. """ data_vertlevel = im_vertlevel.data # average non-null values and round to closest try: # find indices of non-null values indx, indy = np.where(data_vertlevel[:, :, idx_slice]) vert_level = int(np.round(np.mean(data_vertlevel[indx, indy, idx_slice]))) except ValueError as e: # slice is empty (no indx found). Do nothing. logger.debug('Empty slice: z=%s (%s)', idx_slice, e) vert_level = None return vert_level