def detect_c2c3(nii_im, nii_seg, contrast, nb_sag_avg=7.0, verbose=1): """ Detect the posterior edge of C2-C3 disc. :param nii_im: :param nii_seg: :param contrast: :param verbose: :return: """ # path to the pmj detector path_model = os.path.join(sct.__data_dir__, 'c2c3_disc_models', '{}_model'.format(contrast)) orientation_init = nii_im.orientation z_seg_max = np.max(np.where(nii_seg.change_orientation('PIR').data)[1]) # Flatten sagittal nii_im = flatten_sagittal(nii_im, nii_seg, verbose=verbose) nii_seg_flat = flatten_sagittal(nii_seg, nii_seg, verbose=verbose) # create temporary folder with intermediate results sct.log.info("Creating temporary folder...") tmp_folder = sct.TempFolder() tmp_folder.chdir() # Extract mid-slice nii_im.change_orientation('PIR') nii_seg_flat.change_orientation('PIR') mid_RL = int(np.rint(nii_im.dim[2] * 1.0 / 2)) nb_sag_avg_half = int(nb_sag_avg / 2 / nii_im.dim[6]) midSlice = np.mean(nii_im.data[:, :, mid_RL - nb_sag_avg_half:mid_RL + nb_sag_avg_half + 1], 2) # average 7 slices midSlice_seg = nii_seg_flat.data[:, :, mid_RL] nii_midSlice = msct_image.zeros_like(nii_im) nii_midSlice.data = midSlice nii_midSlice.save('data_midSlice.nii') # Run detection sct.printv('Run C2-C3 detector...', verbose) os.environ["FSLOUTPUTTYPE"] = "NIFTI_PAIR" cmd_detection = 'isct_spine_detect -ctype=dpdt "%s" "%s" "%s"' % \ (path_model, 'data_midSlice', 'data_midSlice_pred') sct.run(cmd_detection, verbose=0, raise_exception=False) pred = nib.load('data_midSlice_pred_svm.hdr').get_data() if verbose >= 2: # copy the "prediction data before post-processing" in an Image object nii_pred_before_postPro = nii_midSlice.copy() nii_pred_before_postPro.data = pred # 2D data with orientation, mid sag slice of the original data nii_pred_before_postPro.save( "pred_midSlice_before_postPro.nii.gz") # save it) # Create mask along centerline midSlice_mask = np.zeros(midSlice_seg.shape) mask_halfSize = int(np.rint(25.0 / nii_midSlice.dim[4])) for z in range(midSlice_mask.shape[1]): row = midSlice_seg[:, z] # 2D data with PI orientation, mid sag slice of the original data if np.any(row > 0): med_y = int(np.rint(np.median(np.where(row > 0)))) midSlice_mask[ med_y - mask_halfSize:med_y + mask_halfSize, z] = 1 # 2D data with PI orientation, mid sag slice of the original data if verbose >= 2: # copy the created mask in an Image object nii_postPro_mask = nii_midSlice.copy() nii_postPro_mask.data = midSlice_mask # 2D data with PI orientation, mid sag slice of the original data nii_postPro_mask.save("mask_midSlice.nii.gz") # save it # mask prediction pred[midSlice_mask == 0] = 0 pred[:, z_seg_max:] = 0 # Mask above SC segmentation if verbose >= 2: # copy the "prediction data after post-processing" in an Image object nii_pred_after_postPro = nii_midSlice.copy() nii_pred_after_postPro.data = pred nii_pred_after_postPro.save( "pred_midSlice_after_postPro.nii.gz") # save it # assign label to voxel nii_c2c3 = zeros_like(nii_seg_flat) # 3D data with PIR orientaion if np.any(pred > 0): sct.printv('C2-C3 detected...', verbose) pred_bin = (pred > 0).astype(np.int_) coord_max = np.where(pred == np.max(pred)) pa_c2c3, is_c2c3 = coord_max[0][0], coord_max[1][0] nii_seg.change_orientation('PIR') rl_c2c3 = int( np.rint(center_of_mass(np.array(nii_seg.data[:, is_c2c3, :]))[1])) nii_c2c3.data[pa_c2c3, is_c2c3, rl_c2c3] = 3 else: sct.printv('C2-C3 not detected...', verbose) # remove temporary files tmp_folder.chdir_undo() if verbose < 2: sct.log.info("Remove temporary files...") tmp_folder.cleanup() nii_c2c3.change_orientation(orientation_init) return nii_c2c3
def detect_c2c3(nii_im, nii_seg, contrast, nb_sag_avg=7.0, verbose=1): """ Detect the posterior edge of C2-C3 disc. :param nii_im: :param nii_seg: :param contrast: :param verbose: :return: """ # path to the pmj detector path_model = os.path.join(sct.__data_dir__, 'c2c3_disc_models', '{}_model'.format(contrast)) # check if model exists if not os.path.isfile(path_model + '.yml'): raise FileNotFoundError( "The model file {} does not exist. Please download it using sct_download_data" .format(path_model + '.yml')) orientation_init = nii_im.orientation z_seg_max = np.max(np.where(nii_seg.change_orientation('PIR').data)[1]) # Flatten sagittal nii_im = flatten_sagittal(nii_im, nii_seg, verbose=verbose) nii_seg_flat = flatten_sagittal(nii_seg, nii_seg, verbose=verbose) # create temporary folder with intermediate results logger.info("Creating temporary folder...") tmp_folder = sct.TempFolder() tmp_folder.chdir() # Extract mid-slice nii_im.change_orientation('PIR') nii_seg_flat.change_orientation('PIR') mid_RL = int(np.rint(nii_im.dim[2] * 1.0 / 2)) nb_sag_avg_half = int(nb_sag_avg / 2 / nii_im.dim[6]) midSlice = np.mean(nii_im.data[:, :, mid_RL - nb_sag_avg_half:mid_RL + nb_sag_avg_half + 1], 2) # average 7 slices midSlice_seg = nii_seg_flat.data[:, :, mid_RL] nii_midSlice = zeros_like(nii_im) nii_midSlice.data = midSlice nii_midSlice.save('data_midSlice.nii') # Run detection logger.info('Run C2-C3 detector...') os.environ["FSLOUTPUTTYPE"] = "NIFTI_PAIR" cmd_detection = 'isct_spine_detect -ctype=dpdt "%s" "%s" "%s"' % \ (path_model, 'data_midSlice', 'data_midSlice_pred') # The command below will fail, but we don't care because it will output an image (prediction), which we # will use later on. s, o = run_proc(cmd_detection, verbose=0, is_sct_binary=True, raise_exception=False) pred = nib.load('data_midSlice_pred_svm.hdr').get_data() if verbose >= 2: # copy the "prediction data before post-processing" in an Image object nii_pred_before_postPro = nii_midSlice.copy() nii_pred_before_postPro.data = pred # 2D data with orientation, mid sag slice of the original data nii_pred_before_postPro.save( "pred_midSlice_before_postPro.nii.gz") # save it) # DEBUG trick: check if the detection succeed by running: fsleyes data_midSlice data_midSlice_pred_svm -cm red -dr 0 100 # If a "red cluster" is observed in the neighbourhood of C2C3, then the model detected it. # Create mask along centerline midSlice_mask = np.zeros(midSlice_seg.shape) mask_halfSize = int(np.rint(25.0 / nii_midSlice.dim[4])) for z in range(midSlice_mask.shape[1]): row = midSlice_seg[:, z] # 2D data with PI orientation, mid sag slice of the original data if np.any(row > 0): med_y = int(np.rint(np.median(np.where(row > 0)))) midSlice_mask[ med_y - mask_halfSize:med_y + mask_halfSize, z] = 1 # 2D data with PI orientation, mid sag slice of the original data if verbose >= 2: # copy the created mask in an Image object nii_postPro_mask = nii_midSlice.copy() nii_postPro_mask.data = midSlice_mask # 2D data with PI orientation, mid sag slice of the original data nii_postPro_mask.save("mask_midSlice.nii.gz") # save it # mask prediction pred[midSlice_mask == 0] = 0 pred[:, z_seg_max:] = 0 # Mask above SC segmentation if verbose >= 2: # copy the "prediction data after post-processing" in an Image object nii_pred_after_postPro = nii_midSlice.copy() nii_pred_after_postPro.data = pred nii_pred_after_postPro.save( "pred_midSlice_after_postPro.nii.gz") # save it # assign label to voxel nii_c2c3 = zeros_like(nii_seg_flat) # 3D data with PIR orientaion if np.any(pred > 0): logger.info('C2-C3 detected...') pred_bin = (pred > 0).astype(np.int_) coord_max = np.where(pred == np.max(pred)) pa_c2c3, is_c2c3 = coord_max[0][0], coord_max[1][0] nii_seg.change_orientation('PIR') rl_c2c3 = int( np.rint(center_of_mass(np.array(nii_seg.data[:, is_c2c3, :]))[1])) nii_c2c3.data[pa_c2c3, is_c2c3, rl_c2c3] = 3 else: logger.warning('C2-C3 not detected...') # remove temporary files tmp_folder.chdir_undo() if verbose < 2: logger.info("Remove temporary files...") tmp_folder.cleanup() else: logger.info("Temporary files saved to " + tmp_folder.get_path()) nii_c2c3.change_orientation(orientation_init) return nii_c2c3
def detect_c2c3(nii_im, nii_seg, contrast, verbose=1): """ Detect the posterior edge of C2-C3 disc. :param nii_im: :param nii_seg: :param contrast: :param verbose: :return: """ # path to the pmj detector path_sct = os.environ.get("SCT_DIR", os.path.dirname(os.path.dirname(__file__))) path_model = os.path.join(path_sct, 'data', 'c2c3_disc_models', '{}_model'.format(contrast)) orientation_init = nii_im.orientation # Flatten sagittal nii_im = flatten_sagittal(nii_im, nii_seg, centerline_fitting='hanning', verbose=verbose) nii_seg_flat = flatten_sagittal(nii_seg, nii_seg, centerline_fitting='hanning', verbose=verbose) # create temporary folder with intermediate results sct.log.info("Creating temporary folder...") tmp_folder = sct.TempFolder() tmp_folder.chdir() # Extract mid-slice nii_im.change_orientation('PIR') nii_seg_flat.change_orientation('PIR') mid_RL = int(np.rint(nii_im.dim[2] * 1.0 / 2)) midSlice = nii_im.data[:, :, mid_RL] midSlice_seg = nii_seg_flat.data[:, :, mid_RL] nii_midSlice = msct_image.zeros_like(nii_im) nii_midSlice.data = midSlice nii_midSlice.save('data_midSlice.nii') # Run detection sct.printv('Run C2-C3 detector...', verbose) os.environ["FSLOUTPUTTYPE"] = "NIFTI_PAIR" cmd_detection = 'isct_spine_detect -ctype=dpdt "%s" "%s" "%s"' % \ (path_model, 'data_midSlice', 'data_midSlice_pred') sct.run(cmd_detection, verbose=0, raise_exception=False) # sct.run(cmd_detection, verbose=0) pred = nib.load('data_midSlice_pred_svm.hdr').get_data() # Create mask along centerline midSlice_mask = np.zeros(midSlice_seg.shape) mask_halfSize = 25 for z in range(midSlice_mask.shape[1]): row = midSlice_seg[:, z] if np.any(row): med_y = int(np.rint(np.median(np.where(row)))) midSlice_mask[med_y - mask_halfSize:med_y + mask_halfSize] = 1 # mask prediction pred[midSlice_mask == 0] = 0 # assign label to voxel nii_c2c3 = zeros_like(nii_seg_flat) if np.any(pred > 0): sct.printv('C2-C3 detected...', verbose) coord_max = np.where(pred == np.max(pred)) pa_c2c3, is_c2c3 = coord_max[0][0], coord_max[1][0] nii_seg.change_orientation('PIR') rl_c2c3 = int(np.rint(center_of_mass(nii_seg.data[:, is_c2c3, :])[1])) nii_c2c3.data[pa_c2c3, is_c2c3, rl_c2c3] = 3 else: sct.printv('C2-C3 not detected...', verbose) # remove temporary files tmp_folder.chdir_undo() sct.log.info("Remove temporary files...") tmp_folder.cleanup() nii_c2c3.change_orientation(orientation_init) return nii_c2c3
def detect_c2c3(nii_im, nii_seg, contrast, nb_sag_avg=7.0, verbose=1): """ Detect the posterior edge of C2-C3 disc. :param nii_im: :param nii_seg: :param contrast: :param verbose: :return: """ # path to the pmj detector path_sct = os.environ.get("SCT_DIR", os.path.dirname(os.path.dirname(__file__))) path_model = os.path.join(path_sct, 'data', 'c2c3_disc_models', '{}_model'.format(contrast)) orientation_init = nii_im.orientation z_seg_max = np.max(np.where(nii_seg.change_orientation('PIR').data)[1]) # Flatten sagittal nii_im = flatten_sagittal(nii_im, nii_seg, centerline_fitting='hanning', verbose=verbose) nii_seg_flat = flatten_sagittal(nii_seg, nii_seg, centerline_fitting='hanning', verbose=verbose) # create temporary folder with intermediate results sct.log.info("Creating temporary folder...") tmp_folder = sct.TempFolder() # print tmp_folder.path_tmp tmp_folder.chdir() # Extract mid-slice nii_im.change_orientation('PIR') nii_seg_flat.change_orientation('PIR') mid_RL = int(np.rint(nii_im.dim[2] * 1.0 / 2)) nb_sag_avg_half = int(nb_sag_avg / 2 / nii_im.dim[6]) midSlice = np.mean(nii_im.data[:, :, mid_RL - nb_sag_avg_half:mid_RL + nb_sag_avg_half + 1], 2) # average 7 slices midSlice_seg = nii_seg_flat.data[:, :, mid_RL] nii_midSlice = msct_image.zeros_like(nii_im) nii_midSlice.data = midSlice nii_midSlice.save('data_midSlice.nii') # Run detection sct.printv('Run C2-C3 detector...', verbose) os.environ["FSLOUTPUTTYPE"] = "NIFTI_PAIR" cmd_detection = 'isct_spine_detect -ctype=dpdt "%s" "%s" "%s"' % \ (path_model, 'data_midSlice', 'data_midSlice_pred') sct.run(cmd_detection, verbose=0, raise_exception=False) pred = nib.load('data_midSlice_pred_svm.hdr').get_data() # Create mask along centerline midSlice_mask = np.zeros(midSlice_seg.shape) mask_halfSize = int(np.rint(25.0 / nii_midSlice.dim[4])) for z in range(midSlice_mask.shape[1]): row = midSlice_seg[:, z] if np.any(row): med_y = int(np.rint(np.median(np.where(row)))) midSlice_mask[med_y - mask_halfSize:med_y + mask_halfSize] = 1 # mask prediction pred[midSlice_mask == 0] = 0 # dist_medulla = 30.0 if contrast == 't1' else 40.0 # Observation: segmentation ends higher on t2 images than t1 # z_seg_max -= int(np.rint(dist_medulla / nii_midSlice.dim[5])) # TODO: take into account the curvature pred[:, z_seg_max:] = 0 # Mask above SC segmentation # assign label to voxel nii_c2c3 = zeros_like(nii_seg_flat) if np.any(pred > 0): sct.printv('C2-C3 detected...', verbose) pred_bin = (pred > 0).astype(np.int_) # labeled_pred, nb_regions = label_regions(pred_bin, return_num=True) # if nb_regions > 1: # if there are several clusters of voxels detected # region_idx_top, region_z_top = 0, 0 # for region_idx in range(1, nb_regions+1): # pred_idx = (labeled_pred == region_idx).astype(np.int_) # pa_com, is_com = center_of_mass(pred_idx) # if is_com >= region_z_top: # region_idx_top = region_idx # region_z_top = is_com # pred[labeled_pred != region_idx_top] = 0 # then keep the one located at the top (IS direction) coord_max = np.where(pred == np.max(pred)) pa_c2c3, is_c2c3 = coord_max[0][0], coord_max[1][0] nii_seg.change_orientation('PIR') rl_c2c3 = int(np.rint(center_of_mass(nii_seg.data[:, is_c2c3, :])[1])) nii_c2c3.data[pa_c2c3, is_c2c3, rl_c2c3] = 3 else: sct.printv('C2-C3 not detected...', verbose) # remove temporary files tmp_folder.chdir_undo() sct.log.info("Remove temporary files...") tmp_folder.cleanup() nii_c2c3.change_orientation(orientation_init) return nii_c2c3
def detect_c2c3(nii_im, nii_seg, contrast, nb_sag_avg=7.0, verbose=1): """ Detect the posterior edge of C2-C3 disc. :param nii_im: :param nii_seg: :param contrast: :param verbose: :return: """ # path to the pmj detector path_model = os.path.join(sct.__data_dir__, 'c2c3_disc_models', '{}_model'.format(contrast)) orientation_init = nii_im.orientation z_seg_max = np.max(np.where(nii_seg.change_orientation('PIR').data)[1]) # Flatten sagittal nii_im = flatten_sagittal(nii_im, nii_seg,verbose=verbose) nii_seg_flat = flatten_sagittal(nii_seg, nii_seg, verbose=verbose) # create temporary folder with intermediate results logger.info("Creating temporary folder...") tmp_folder = sct.TempFolder() tmp_folder.chdir() # Extract mid-slice nii_im.change_orientation('PIR') nii_seg_flat.change_orientation('PIR') mid_RL = int(np.rint(nii_im.dim[2] * 1.0 / 2)) nb_sag_avg_half = int(nb_sag_avg / 2 / nii_im.dim[6]) midSlice = np.mean(nii_im.data[:, :, mid_RL-nb_sag_avg_half:mid_RL+nb_sag_avg_half+1], 2) # average 7 slices midSlice_seg = nii_seg_flat.data[:, :, mid_RL] nii_midSlice = msct_image.zeros_like(nii_im) nii_midSlice.data = midSlice nii_midSlice.save('data_midSlice.nii') # Run detection logger.info('Run C2-C3 detector...') os.environ["FSLOUTPUTTYPE"] = "NIFTI_PAIR" cmd_detection = 'isct_spine_detect -ctype=dpdt "%s" "%s" "%s"' % \ (path_model, 'data_midSlice', 'data_midSlice_pred') # The command below will fail, but we don't care because it will output an image (prediction), which we # will use later on. s, o = sct.run(cmd_detection, verbose=0, is_sct_binary=True, raise_exception=False) pred = nib.load('data_midSlice_pred_svm.hdr').get_data() if verbose >= 2: # copy the "prediction data before post-processing" in an Image object nii_pred_before_postPro = nii_midSlice.copy() nii_pred_before_postPro.data = pred # 2D data with orientation, mid sag slice of the original data nii_pred_before_postPro.save("pred_midSlice_before_postPro.nii.gz") # save it) # Create mask along centerline midSlice_mask = np.zeros(midSlice_seg.shape) mask_halfSize = int(np.rint(25.0 / nii_midSlice.dim[4])) for z in range(midSlice_mask.shape[1]): row = midSlice_seg[:, z] # 2D data with PI orientation, mid sag slice of the original data if np.any(row > 0): med_y = int(np.rint(np.median(np.where(row > 0)))) midSlice_mask[med_y-mask_halfSize:med_y+mask_halfSize, z] = 1 # 2D data with PI orientation, mid sag slice of the original data if verbose >= 2: # copy the created mask in an Image object nii_postPro_mask = nii_midSlice.copy() nii_postPro_mask.data = midSlice_mask # 2D data with PI orientation, mid sag slice of the original data nii_postPro_mask.save("mask_midSlice.nii.gz") # save it # mask prediction pred[midSlice_mask == 0] = 0 pred[:, z_seg_max:] = 0 # Mask above SC segmentation if verbose >= 2: # copy the "prediction data after post-processing" in an Image object nii_pred_after_postPro = nii_midSlice.copy() nii_pred_after_postPro.data = pred nii_pred_after_postPro.save("pred_midSlice_after_postPro.nii.gz") # save it # assign label to voxel nii_c2c3 = zeros_like(nii_seg_flat) # 3D data with PIR orientaion if np.any(pred > 0): logger.info('C2-C3 detected...') pred_bin = (pred > 0).astype(np.int_) coord_max = np.where(pred == np.max(pred)) pa_c2c3, is_c2c3 = coord_max[0][0], coord_max[1][0] nii_seg.change_orientation('PIR') rl_c2c3 = int(np.rint(center_of_mass(np.array(nii_seg.data[:, is_c2c3, :]))[1])) nii_c2c3.data[pa_c2c3, is_c2c3, rl_c2c3] = 3 else: logger.warning('C2-C3 not detected...') # remove temporary files tmp_folder.chdir_undo() if verbose < 2: logger.info("Remove temporary files...") tmp_folder.cleanup() nii_c2c3.change_orientation(orientation_init) return nii_c2c3