def lung_fill_hole(data_folder, data, type_im, cn, ext='.mha', mha_folder_name='mha'): lung_initial_folder_name = 'Lung_Initial' lung_filled_folder_name = 'Lung_Filled' if data == 'DIR-Lab_4D': type_im_list = ['T00', 'T10', 'T20', 'T30', 'T40', 'T50', 'T60', 'T70', 'T80', 'T90'] data_folder_sub = data_folder + 'DIR-Lab/4DCT/' lung_initial_folder = data_folder_sub+mha_folder_name+'/case'+str(cn)+'/'+lung_initial_folder_name+'/' lung_filled_folder = data_folder_sub+mha_folder_name+'/case'+str(cn)+'/'+lung_filled_folder_name+'/' lung_initial_address = lung_initial_folder+'case'+str(cn)+'_'+type_im_list[type_im]+'_'+lung_initial_folder_name+ext lung_filled_address = lung_filled_folder+'case'+str(cn)+'_'+type_im_list[type_im]+'_'+lung_filled_folder_name+ext elif data == 'DIR-Lab_COPD': type_im_list = ['i', 'e'] data_folder_sub = data_folder + 'DIR-Lab/COPDgene/' lung_initial_folder = data_folder_sub+mha_folder_name+'/'+lung_initial_folder_name+'/' lung_filled_folder = data_folder_sub+mha_folder_name+'/'+lung_filled_folder_name+'/' lung_initial_address = lung_initial_folder+'copd'+str(cn)+'_'+type_im_list[type_im]+'BHCT'+ext lung_filled_address = lung_filled_folder+'copd'+str(cn)+'_'+type_im_list[type_im]+'BHCT'+ext else: raise ValueError('Data='+data+", it should be in ['DIR-Lab_4D', 'DIR-Lab_COPD']") if not os.path.isdir(lung_filled_folder): os.makedirs(lung_filled_folder) lung_initial_sitk = sitk.ReadImage(lung_initial_address) lung_initial = sitk.GetArrayFromImage(lung_initial_sitk) lung_initial = lung_initial > 0 structure = np.ones([3, 3, 3], dtype=np.bool) lung_filled = (ndimage.morphology.binary_closing(lung_initial, structure=structure)).astype(np.int8) sitk.WriteImage(ip.array_to_sitk(lung_filled, im_ref=lung_initial_sitk), lung_filled_address)
def cylinder_mask(setting, cn=None, overwrite=False): cylinder_folder = su.address_generator(setting, 'Cylinder', cn=cn, type_im=0).rsplit('/', maxsplit=1)[0] if not os.path.isdir(cylinder_folder): os.makedirs(cylinder_folder) for type_im in range(len(setting['types'])): cylinder_mask_address = su.address_generator(setting, 'Cylinder', cn=cn, type_im=type_im) if (not os.path.isfile(cylinder_mask_address)) or overwrite: image_sitk = sitk.ReadImage( su.address_generator(setting, 'Im', cn=cn, type_im=type_im)) cylinder_mask_sitk = sitk.BinaryThreshold( image_sitk, lowerThreshold=setting['defaultPixelValue'] - 1, upperThreshold=setting['defaultPixelValue'] + 0.01, insideValue=0, outsideValue=1) structure = np.ones((1, 3, 3)) # erosion with ndimage is 5 times faster than SimpleITK cylinder_mask_eroded = (ndimage.binary_erosion( sitk.GetArrayFromImage(cylinder_mask_sitk), structure=structure, iterations=2)).astype(np.int8) cylinder_mask_eroded_sitk = ip.array_to_sitk(cylinder_mask_eroded, im_ref=image_sitk) sitk.WriteImage(cylinder_mask_eroded_sitk, cylinder_mask_address) logging.debug(cylinder_mask_address + ' is done')
def lung_fill_hole_erode(setting, cn=None): folder = su.address_generator(setting, 'Lung_Filled_Erode', cn=cn, type_im=0).rsplit('/', maxsplit=1)[0] if not os.path.isdir(folder): os.makedirs(folder) for type_im in range(len(setting['types'])): lung_raw_filled_sitk = sitk.ReadImage(su.address_generator(setting, 'Lung_Filled', cn=cn, type_im=type_im)) lung_raw_filled = sitk.GetArrayFromImage(lung_raw_filled_sitk) lung_raw_filled = lung_raw_filled > 0 structure = np.ones([3, 3, 3], dtype=np.bool) lung_filled_erode = (ndimage.morphology.binary_dilation(lung_raw_filled, structure=structure)).astype(np.int8) sitk.WriteImage(ip.array_to_sitk(lung_filled_erode, im_ref=lung_raw_filled_sitk), su.address_generator(setting, 'Lung_Filled_Erode', cn=cn, type_im=type_im))
def jac(setting, cn=None): time_before = time.time() dvf_sitk = sitk.ReadImage( su.address_generator(setting, 'DVF_nonRigid_composed', cn=cn, out=0)) jac = ip.calculate_jac(sitk.GetArrayFromImage(dvf_sitk), dvf_sitk.GetSpacing()) sitk.WriteImage( sitk.Cast(ip.array_to_sitk(jac, im_ref=dvf_sitk), sitk.sitkVectorFloat32), su.address_generator(setting, 'Jac', cn=cn)) time_after = time.time() logging.debug( 'multi_registration: calculating Jac cn={} is done in {:.2f}'.format( cn, time_after - time_before))
def image_normalization(setting, cn=None, mask_name='Lung_Filled_Erode'): normalized_folder = su.address_generator( setting, 'originalImageFolder') + 'Normalized/' if not os.path.isdir(normalized_folder): os.makedirs(normalized_folder) normalized_erode_folder = su.address_generator( setting, 'originalImageFolder') + 'Masked_Normalized/' if not os.path.isdir(normalized_erode_folder): os.makedirs(normalized_erode_folder) for type_im in range(len(setting['types'])): im_sitk = sitk.ReadImage( su.address_generator(setting, 'Im', type_im=type_im, cn=cn)) im = sitk.GetArrayFromImage(im_sitk) mask = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, mask_name, type_im=type_im, cn=cn))) im_masked = im * mask min_im = np.min(im_masked) max_im = np.max(im_masked) slop = 1.0 / (max_im - min_im) intercept = -min_im / (max_im - min_im) im_masked_normalized = 1 - (im_masked - min_im) / (max_im - min_im) im_masked_normalized = im_masked_normalized * mask im_masked_normalized_sitk = ip.array_to_sitk(im_masked_normalized, im_ref=im_sitk) sitk.WriteImage( im_masked_normalized_sitk, su.address_generator(setting, 'Im_Masked_Normalized', type_im=type_im, cn=cn)) print('writing ' + su.address_generator(setting, 'Im_Masked_Normalized', type_im=type_im, cn=cn, print_mode=True)) print('slop: {:.6f}, intercept: {:.6f}'.format(slop, intercept))
def std_t(setting, cn=None, max_number_of_registration=None, mode='initial'): """ This function writes stdT, E_T or stdT_final, E_T_final. mode can be chosen between 'initial' and 'final' mode = 'initial' ---->> write stdT, E_T mode = 'final' ---->> write stdT_final, E_T_final :param setting: setting dictionary :param cn: number of the case :param max_number_of_registration: maximum number of registration. By default it is supposed to be written in the setting dict. :param mode: 'initial' or 'final' :return: write stdT, E_T or stdT_final, E_T_final """ time_before = time.time() all_dvf_available = True if mode == 'initial': name_ext = '' # no extentension in the naming of initial mode, for eg: DVF_nonRigid_composed, stdT if max_number_of_registration is None: max_number_of_registration = setting['out_max'] if os.path.isfile( su.address_generator(setting, 'stdT' + name_ext, cn=cn)): logging.debug( 'multi_registration.std_t: already exists: ' + su.address_generator( setting, 'stdT' + name_ext, cn=cn, print_mode=True)) return 1 else: for out in range(1, max_number_of_registration + 1): all_dvf_available = all_dvf_available & os.path.isfile( su.address_generator(setting, 'DVF_nonRigid_composed' + name_ext, cn=cn, out=out)) elif mode == 'final': name_ext = '_final' # _final extentension in the naming of final mode, , for eg: DVF_nonRigid_composed_final, stdT_final if max_number_of_registration is None: max_number_of_registration = setting['out_max_final'] if os.path.isfile( su.address_generator(setting, 'stdT' + name_ext, cn=cn)): logging.debug( 'multi_registration.std_t: already exists: ' + su.address_generator( setting, 'stdT' + name_ext, cn=cn, print_mode=True)) return 1 else: for outfinal in range(1, max_number_of_registration + 1): all_dvf_available = all_dvf_available & os.path.isfile( su.address_generator(setting, 'DVF_nonRigid_composed' + name_ext, cn=cn, outfinal=outfinal)) else: raise ValueError('mode is set to ' + mode + ' but is should be either "initial" or "final"') if all_dvf_available: logging.debug('multi_registration.stdT: start calculating stdT' + name_ext + ' IN={}'.format(cn)) dimension = setting['dimension'] dvf0 = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, 'DVF_nonRigid_composed', cn=cn, out=0))) dvf_all = [None] * dimension dvf_var = [None] * dimension dvf_mean = [None] * dimension for dim in range(3): dvf_all[dim] = np.empty(np.r_[np.shape(dvf0)[:-1], max_number_of_registration], dtype=np.float32) for out in range(1, max_number_of_registration + 1): if mode == 'initial': dvf_ = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, 'DVF_nonRigid_composed' + name_ext, cn=cn, out=out))) logging.debug('multi_registration.stdT: reading: ' + su.address_generator(setting, 'DVF_nonRigid_composed' + name_ext, cn=cn, out=out, print_mode=True)) elif mode == 'final': dvf_ = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, 'DVF_nonRigid_composed' + name_ext, cn=cn, outfinal=out))) logging.debug('multi_registration.stdT: reading: ' + su.address_generator(setting, 'DVF_nonRigid_composed' + name_ext, cn=cn, outfinal=out, print_mode=True)) for dim in range(dimension): dvf_all[dim][:, :, :, out - 1] = dvf_[:, :, :, dim] for dim in range(dimension): dvf_var[dim] = (np.var(dvf_all[dim], axis=dimension)).astype(np.float32) dvf_mean[dim] = (np.mean(dvf_all[dim], axis=dimension)).astype(np.float32) std_t = np.sqrt(sum(dvf_var)) E_T = (np.sqrt( np.sum(np.square([ dvf_mean[dim] - dvf0[:, :, :, dim] for dim in range(dimension) ]), axis=0))).astype(np.float32) fixed_image_sitk = sitk.ReadImage( su.address_generator(setting, 'Im', cn=cn, type_im=0)) sitk.WriteImage( ip.array_to_sitk(std_t, im_ref=fixed_image_sitk), su.address_generator(setting, 'stdT' + name_ext, cn=cn)) sitk.WriteImage(ip.array_to_sitk(E_T, im_ref=fixed_image_sitk), su.address_generator(setting, 'E_T' + name_ext, cn=cn)) time_after = time.time() logging.debug( 'multi_registration.stdT: calculating stdT' + name_ext + ' IN={} is done in {:.2f}'.format(cn, time_after - time_before)) else: logging.debug('multi_registration.std_t: all dvf are not available: ' + su.address_generator( setting, 'stdT' + name_ext, cn=cn, print_mode=True))
def compute_error(setting, cn=None, write_error_image=True): if (os.path.isfile(su.address_generator(setting, 'errorImage', cn=cn)) & os.path.isfile( su.address_generator(setting, 'errorImageAffine', cn=cn)) & os.path.isfile( su.address_generator(setting, 'errorImageMask', cn=cn))): logging.debug(setting['current_experiment'] + ' cn:' + str(cn) + ' all error images exist') return 1 if not (os.path.isfile( su.address_generator( setting, 'DVF_nonRigid_composed', cn=cn, out=0))): logging.debug(setting['current_experiment'] + ' cn:' + str(cn) + ' deformation field not found') return 2 fixed_indices = np.loadtxt(su.address_generator(setting, 'landmarkIndex_tr', cn=cn, type_im=0), dtype=np.int) fixed_points = np.loadtxt( su.address_generator(setting, 'landmarkPoint_tr', cn=cn, type_im=0)) moving_points = np.loadtxt( su.address_generator(setting, 'landmarkPoint_tr', cn=cn, type_im=1)) if setting['registration_output'] == 'DVF': if 'affine_experiment_step' in setting.keys(): affine_step = setting['affine_experiment_step'] elif 'AffineParameter' in setting.keys(): affine_step = len(setting['AffineParameter']) - 1 else: affine_step = 0 dvf_nonrigid = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, 'DVF_nonRigid_composed', cn=cn, out=0))) dvf_affine = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator( setting, 'affineDVF', cn=cn, current_experiment=setting['affine_experiment'], reg_step=affine_step))) fixed_nonrigid_transformed_points = np.empty(np.shape(fixed_points)) fixed_affine_transformed_points = np.empty(np.shape(fixed_points)) for p in range(len(fixed_nonrigid_transformed_points)): fixed_nonrigid_transformed_points[p, :] = fixed_points[p, :] + [ dvf_nonrigid[fixed_indices[p, 2], fixed_indices[p, 1], fixed_indices[p, 0], 0], dvf_nonrigid[fixed_indices[p, 2], fixed_indices[p, 1], fixed_indices[p, 0], 1], dvf_nonrigid[fixed_indices[p, 2], fixed_indices[p, 1], fixed_indices[p, 0], 2] ] fixed_affine_transformed_points[p, :] = fixed_points[p, :] + [ dvf_affine[fixed_indices[p, 2], fixed_indices[p, 1], fixed_indices[p, 0], 0], dvf_affine[fixed_indices[p, 2], fixed_indices[p, 1], fixed_indices[p, 0], 1], dvf_affine[fixed_indices[p, 2], fixed_indices[p, 1], fixed_indices[p, 0], 2] ] elif setting['registration_output'] == 'elastix_transform_parameters': fixed_points_elx_address = su.address_generator(setting, 'landmarkIndex_elx', cn=cn, type_im=0) elxpy.transformix( parameter_file=su.address_generator(setting, 'DVF_nonRigid_composed', cn=cn, out=0), output_directory=su.address_generator(setting, 'nonRigidFolder', cn=cn, out=0), points=fixed_points_elx_address, transformixPath='transformix') raise ValueError('not implemented yet') TRE_before_registration = (np.sum( (fixed_affine_transformed_points - moving_points)**2, axis=1))**0.5 TRE = (np.sum((fixed_nonrigid_transformed_points - moving_points)**2, axis=1))**0.5 if write_error_image: logging.debug('compute_error: writing: ' + su.address_generator( setting, 'errorImage', cn=cn, print_mode=True)) fixed_image_sitk = sitk.ReadImage( su.address_generator(setting, 'Im', cn=cn, type_im=0)) error_image_nonrigid = np.zeros(fixed_image_sitk.GetSize()[::-1]) error_image_affine = np.zeros(fixed_image_sitk.GetSize()[::-1]) error_mask = np.zeros(fixed_image_sitk.GetSize()[::-1], dtype=np.int8) r = setting['neighborhood_radius'] for p in range(len(fixed_indices)): error_image_affine[fixed_indices[p, 2] - r:fixed_indices[p, 2] + r + 1, fixed_indices[p, 1] - r:fixed_indices[p, 1] + r + 1, fixed_indices[p, 0] - r:fixed_indices[p, 0] + r + 1] = TRE_before_registration[p] error_image_nonrigid[fixed_indices[p, 2] - r:fixed_indices[p, 2] + r + 1, fixed_indices[p, 1] - r:fixed_indices[p, 1] + r + 1, fixed_indices[p, 0] - r:fixed_indices[p, 0] + r + 1] = TRE[p] error_mask[fixed_indices[p, 2] - r:fixed_indices[p, 2] + r + 1, fixed_indices[p, 1] - r:fixed_indices[p, 1] + r + 1, fixed_indices[p, 0] - r:fixed_indices[p, 0] + r + 1] = 1 sitk.WriteImage( sitk.Cast( ip.array_to_sitk(error_image_nonrigid, im_ref=fixed_image_sitk), sitk.sitkFloat32), su.address_generator(setting, 'errorImage', cn=cn)) sitk.WriteImage( sitk.Cast( ip.array_to_sitk(error_image_affine, im_ref=fixed_image_sitk), sitk.sitkFloat32), su.address_generator(setting, 'errorImageAffine', cn=cn)) sitk.WriteImage( sitk.Cast(ip.array_to_sitk(error_mask, im_ref=fixed_image_sitk), sitk.sitkInt8), su.address_generator(setting, 'errorImageMask', cn=cn)) return 0
def img_converter(data_folder, data, type_im, cn, ext='.mha', mha_folder_name='mha', point_folder_name='points'): """ convert img images to mha. reading image: 1) Size and voxel spacing of the images are available at https://www.dir-lab.com/ReferenceData.html 2) The superior-inferior axis needs to be flipped 3) Empty slices will be removed copd1_eBHCT.mha slice 0:1 copd2_eBHCT.mha slice 0:6 copd3_eBHCT.mha slice 0:9 copd4_eBHCT.mha slice 0:9 copd5_eBHCT.mha slice NA copd6_eBHCT.mha slice 0:2 copd7_eBHCT.mha slice 0:9 copd8_eBHCT.mha slice 0:7 copd9_eBHCT.mha slice 0:19 copd10_iBHCT.mah slice 0 4) Index modification: 4a) The superior-inferior axis needs to be flipped 4b) The indices start at 1. We like them to start at 0. 4c) change indices of landmarks based on the removed slices 5) Normalize the intensity by subtracting by -1024 6) Set the outside value to -2048 :param ext :param cn: :param type_im :param data_folder :param data :param mha_folder_name :param point_folder_name :return: """ if data == 'DIR-Lab_4D': type_im_list = [ 'T00', 'T10', 'T20', 'T30', 'T40', 'T50', 'T60', 'T70', 'T80', 'T90' ] data_folder_sub = data_folder + 'DIR-Lab/4DCT/' if cn < 6: im_img_name = 'Images/case' + str( cn) + '_' + type_im_list[type_im] + '_s.img' else: im_img_name = 'Images/case' + str( cn) + '_' + type_im_list[type_im] + '.img' im_img_folder = data_folder_sub + 'Case' + str(cn) + 'Pack/' if cn == 8: im_img_folder = data_folder_sub + 'Case' + str(cn) + 'Deploy/' im_mha_name = 'case' + str(cn) + '_' + type_im_list[type_im] + ext im_mha_folder = data_folder_sub + mha_folder_name + '/case' + str( cn) + '/' point_folder = data_folder_sub + point_folder_name + '/case' + str( cn) + '/' index_tr_old_address_list = [ im_img_folder + '/Sampled4D/case' + str(cn) + '_4D-75_' + type_im_list[type_im] + '.txt', im_img_folder + '/ExtremePhases/case' + str(cn) + '_300_' + type_im_list[type_im] + '_xyz.txt' ] index_tr_new_address_list = [ point_folder + '/case' + str(cn) + '_4D-75_' + type_im_list[type_im] + '_xyz_tr.txt', point_folder + '/case' + str(cn) + '_300_' + type_im_list[type_im] + '_xyz_tr.txt' ] index_elx_new_address_list = [ point_folder + '/case' + str(cn) + '_4D-75_' + type_im_list[type_im] + '_xyz_elx.txt', point_folder + '/case' + str(cn) + '_300_' + type_im_list[type_im] + '_xyz_elx.txt' ] point_tr_new_address_list = [ point_folder + '/case' + str(cn) + '_4D-75_' + type_im_list[type_im] + '_world_tr.txt', point_folder + '/case' + str(cn) + '_300_' + type_im_list[type_im] + '_world_tr.txt' ] point_elx_new_address_list = [ point_folder + '/case' + str(cn) + '_4D-75_' + type_im_list[type_im] + '_world_elx.txt', point_folder + '/case' + str(cn) + '_300_' + type_im_list[type_im] + '_world_elx.txt' ] dirlab_header = dirlab_4dct_header() elif data == 'DIR-Lab_COPD': type_im_list = ['i', 'e'] data_folder_sub = data_folder + 'DIR-Lab/COPDgene/' im_img_name = 'copd' + str( cn) + '_' + type_im_list[type_im] + 'BHCT.img' im_img_folder = data_folder_sub + 'copd' + str(cn) + '/' im_mha_name = 'copd' + str( cn) + '_' + type_im_list[type_im] + 'BHCT' + ext im_mha_folder = data_folder_sub + mha_folder_name + '/' point_folder = data_folder_sub + point_folder_name index_tr_old_address_list = [ im_img_folder + 'copd' + str(cn) + '_300_' + type_im_list[type_im] + 'BH_xyz_r1.txt' ] index_tr_new_address_list = [ point_folder + '/copd' + str(cn) + '_300_' + type_im_list[type_im] + 'BH_xyz_r1_tr.txt' ] index_elx_new_address_list = [ point_folder + '/copd' + str(cn) + '_300_' + type_im_list[type_im] + 'BH_xyz_r1_elx.txt' ] point_tr_new_address_list = [ point_folder + '/copd' + str(cn) + '_300_' + type_im_list[type_im] + 'BH_world_r1_tr.txt' ] point_elx_new_address_list = [ point_folder + '/copd' + str(cn) + '_300_' + type_im_list[type_im] + 'BH_world_r1_elx.txt' ] dirlab_header = dirlab_copd_header() else: raise ValueError('Data=' + data + ", it should be in ['DIR-Lab_4D', 'DIR-Lab_COPD']") if not os.path.isdir(im_mha_folder): os.makedirs(im_mha_folder) if not os.path.isdir(point_folder): os.makedirs(point_folder) im_img_address = im_img_folder + im_img_name im_mha_address = im_mha_folder + im_mha_name if not os.path.isfile(im_mha_address): # 1,2) reading image:---------------------------------------------------------------- fid = open(im_img_address, 'rb') im_data = np.fromfile(fid, np.int16) image_old = im_data.reshape(dirlab_header['case' + str(cn)]['Size'][::-1]) image_old = np.flip( image_old, axis=0) # The superior-inferior axis needs to be flipped origin = [0, 0, 0] image = copy.deepcopy(image_old) # reading landmarks: for ii, index_tr_old_address in enumerate(index_tr_old_address_list): index_tr_new_address = index_tr_new_address_list[ii] index_elx_new_address = index_elx_new_address_list[ii] point_tr_new_address = point_tr_new_address_list[ii] point_elx_new_address = point_elx_new_address_list[ii] if os.path.isfile(index_tr_old_address): index_tr_old_raw = np.loadtxt(index_tr_old_address) # 4a&b) The superior-inferior axis is flipped. be careful about that indices start at 1. after converting to zero-start, # there is no -1 in the SI direction. index_tr_old = np.array([[ index_tr_old_raw[i, 0] - 1, index_tr_old_raw[i, 1] - 1, image_old.shape[0] - index_tr_old_raw[i, 2] ] for i in range(index_tr_old_raw.shape[0])]) # 3) remove empty slices only in DIR-Lab_COPD----------------------------------------- if data == 'DIR-Lab_COPD': image, slices_to_remove = remove_empty_slices(image_old) print(im_img_name + ' slices are removed: ' + str(slices_to_remove)) shift_indices = len(slices_to_remove) shift_world = shift_indices * dirlab_header[ 'case' + str(cn)]['Spacing'][2] origin[2] = shift_world # 4c) change indices of landmarks based on the removed slices index_tr_new = [[ index_tr_old[i, 0], index_tr_old[i, 1], index_tr_old[i, 2] - shift_indices ] for i in range(index_tr_old.shape[0])] else: index_tr_new = index_tr_old.copy() np.savetxt(index_tr_new_address, index_tr_new, fmt='%d') point_tr_new = ip.index_to_world( index_tr_new, spacing=dirlab_header['case' + str(cn)]['Spacing'], origin=origin) np.savetxt(point_tr_new_address, point_tr_new, fmt='%-9.3f') open_text = open(index_tr_new_address, "r") number_of_landmarks = index_tr_new.shape[0] with open(index_elx_new_address, "w") as open_elx: open_elx.write('index \n') open_elx.write(str(number_of_landmarks) + ' \n') open_elx.write(open_text.read()) open_text.close() open_text = open(point_tr_new_address, "r") with open(point_elx_new_address, "w") as open_elx: open_elx.write('point \n') open_elx.write(str(number_of_landmarks) + ' \n') open_elx.write(open_text.read()) open_text.close() # 5) normalize the intensity image = image - 1024 # we are not sure about the slope and intercept. # 6) set the outside value to -2048 image[image == -3024] = -2048 image_sitk = ip.array_to_sitk( image, spacing=dirlab_header['case' + str(cn)]['Spacing'], origin=origin) sitk.WriteImage(image_sitk, im_mha_address) print('case' + str(cn) + ' type' + str(type_im) + ' is done..')
def perturbation(setting, cn=None, out=None, outfinal=None): affine_experiment = setting['affine_experiment'] if out is None and outfinal is not None: mode = 'final_perturbation' out = 0 folder_address = su.address_generator(setting, 'nonRigidFolder_final', cn=cn, outfinal=outfinal) ref_dvf_address = su.address_generator(setting, 'DVF_nonRigid_composed', cn=cn, out=0) DVF_perturb_address = su.address_generator(setting, 'DVF_perturb_final', cn=cn, outfinal=outfinal) DVF_perturb_pure_address = su.address_generator( setting, 'DVF_perturb_pure_final', cn=cn, outfinal=outfinal) elif outfinal is None and out is not None: mode = 'initial_perturbation' outfinal = 0 folder_address = su.address_generator(setting, 'nonRigidFolder', cn=cn, out=out) ref_dvf_address = su.address_generator( setting, 'affineDVF', cn=cn, current_experiment=affine_experiment) # if affine_experiment is given, it loads the DVF from that experiment. DVF_perturb_address = su.address_generator(setting, 'DVF_perturb', cn=cn, out=out) DVF_perturb_pure_address = su.address_generator( setting, 'DVF_perturb_without_affine', cn=cn, out=out) else: raise ValueError('out and outfinal cannot be None at the same time') seedNumber = 10000 + 1000 * cn + out * 101 + outfinal * 4 np.random.seed(seedNumber) if not os.path.exists(folder_address): os.makedirs(folder_address) ref_dvf_sitk = sitk.ReadImage(ref_dvf_address) if mode == 'initial_perturbation' and out == 0: # when out=0, there is no perturbation, so the initial DVF is equal to the affine dvf. sitk.WriteImage( sitk.Cast(ref_dvf_sitk, sitk.sitkVectorFloat32), su.address_generator(setting, 'DVF_perturb', cn=cn, out=out)) else: GridSpacing = setting['GridSpacing'] gridBorderToZero = setting['GridBorderToZero'] maxDeform = setting['perturbationOffset'] numberOfGrids = list( np.round( np.array(ref_dvf_sitk.GetSize()) * np.array(ref_dvf_sitk.GetSpacing()) / GridSpacing)) numberOfGrids = [ int(i) for i in numberOfGrids ] # This is a bit funny, it has to be int (and not even np.int) BCoeff = sitk.BSplineTransformInitializer(ref_dvf_sitk, numberOfGrids, order=3) grid_side = BCoeff.GetTransformDomainMeshSize() BCoeff_parameters = np.random.uniform(-maxDeform, maxDeform, len(BCoeff.GetParameters())) BCoeff_processed_dim = [None] * 3 for dim in range(3): BCoeff_dim = np.reshape( np.split(BCoeff_parameters, 3)[dim], [grid_side[2] + 3, grid_side[1] + 3, grid_side[0] + 3]) # number of coefficients in grid is increased by 3 in simpleITK. if np.any(gridBorderToZero): nonZeroMask = np.zeros(np.shape(BCoeff_dim)) nonZeroMask[gridBorderToZero[0]:-gridBorderToZero[0], gridBorderToZero[1]:-gridBorderToZero[1], gridBorderToZero[2]:-gridBorderToZero[2]] = 1 BCoeff_dim = BCoeff_dim * nonZeroMask BCoeff_processed_dim[dim] = np.copy(BCoeff_dim) sitk.WriteImage( sitk.GetImageFromArray(np.stack( (BCoeff_processed_dim[0], BCoeff_processed_dim[1], BCoeff_processed_dim[2]), axis=3), isVector=True), su.address_generator(setting, 'BSplineGrid', cn=cn, out=out)) BCoeff_processed = np.hstack((BCoeff_processed_dim[0].flatten(), BCoeff_processed_dim[1].flatten(), BCoeff_processed_dim[2].flatten())) BCoeff.SetParameters(BCoeff_processed) DVF_filter = sitk.TransformToDisplacementFieldFilter() DVF_filter.SetReferenceImage(ref_dvf_sitk) DVF_perturb_pure_SITK = DVF_filter.Execute(BCoeff) if setting['verboseImage']: sitk.WriteImage( sitk.Cast(DVF_perturb_pure_SITK, sitk.sitkVectorFloat32), DVF_perturb_pure_address) DVF_perturb_pure = sitk.GetArrayFromImage(DVF_perturb_pure_SITK) origDVF = sitk.GetArrayFromImage(ref_dvf_sitk) DVF_perturb = origDVF + DVF_perturb_pure DVF_perturb_SITK = IP.array_to_sitk(DVF_perturb, im_ref=ref_dvf_sitk, is_vector=True) sitk.WriteImage(sitk.Cast(DVF_perturb_SITK, sitk.sitkVectorFloat32), DVF_perturb_address)