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 BSpline_SyN_ANTs_transform_image(setting, IN=None, out=None): fixedIm_address = su.address_generator(setting, 'Im', cn=IN, type_im=0) movingIm_address = su.address_generator(setting, 'Im', cn=IN, type_im=1) transform0 = su.address_generator(setting, 'DVF_nonRigid_composed', cn=IN, out=out) nonRigid_MovedImage_address = su.address_generator(setting, 'nonRigid_MovedImage', cn=IN, out=out) number_of_threads = setting['numberOfThreads'] script = su.address_generator(setting, 'nonRigidTransformMovedImageScript', cn=IN, out=out) log = script + '_log' setLogFile(log) with open(script, "w") as textScr: # please note that the last registration that you did, should be the first transform parameters textScr.write(ANTsP.header_transform()) textScr.write(ANTsP.write_number_of_threads(number_of_threads)) textScr.write(ANTsP.write_input_image(movingIm_address)) textScr.write(ANTsP.write_reference_image(fixedIm_address)) textScr.write(ANTsP.write_transform_parameters(transform0)) textScr.write(ANTsP.write_dimension(setting['dimension'])) textScr.write(ANTsP.write_output(nonRigid_MovedImage_address)) textScr.write( ANTsP.write_default_pixel_value(setting['defaultPixelValue'])) textScr.write(ANTsP.transform_image(number_of_transforms=1)) textScr.write(ANTsP.footer()) textScr.close() os.chmod(script, 0o774) os.system(script)
def affine_ANTs_transform_image(setting, cn=None): fixedIm_address = su.address_generator(setting, 'Im', cn=cn, type_im=0) movingIm_address = su.address_generator(setting, 'Im', cn=cn, type_im=1) affineOutMat = su.address_generator(setting, 'affineOutMat', cn=cn) affine_MovedImage_address = su.address_generator(setting, 'affine_MovedImage', cn=cn) number_of_threads = setting['numberOfThreads'] script = su.address_generator(setting, 'affineTransformMovedImageScript', cn=cn) with open(script, "w") as textScr: # please note that the last registration that you did, should be the first transform parameters textScr.write(ANTsP.header_transform()) textScr.write(ANTsP.write_number_of_threads(number_of_threads)) textScr.write(ANTsP.write_input_image(movingIm_address)) textScr.write(ANTsP.write_reference_image(fixedIm_address)) textScr.write(ANTsP.write_transform_parameters(affineOutMat)) textScr.write(ANTsP.write_dimension(setting['dimension'])) textScr.write(ANTsP.write_output(affine_MovedImage_address)) textScr.write( ANTsP.write_default_pixel_value(setting['defaultPixelValue'])) textScr.write(ANTsP.transform_image(number_of_transforms=1)) textScr.write(ANTsP.footer()) textScr.close() os.chmod(script, 0o774) os.system(script)
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 read_binary_feature(setting, cn=None, feature=None): if feature in ['NCMI', 'NC', 'MI']: number_of_elements = 56 feature_binary = 'NCMI' # 16:48 MI # 48:56 NC # Number of features in NCMI, # outMI[0]: NMI # outMI[1]: NMIS # outMI[2]: PMI # outMI[3]: PMIS # outMI[4]: NMI->ITK # outMI[5]: NMIS->ITK # outMI[6]: NCR else: number_of_elements = 18 feature_binary = feature fid = open( su.address_generator(setting, 'PooledFeature', feature=feature_binary, cn=cn), 'rb') data = np.fromfile(fid, np.float32) binary_feature = data.reshape(-1, number_of_elements, order='F') # order 'F' is double checked! if feature == 'MI': binary_feature = binary_feature[:, 16:48] if feature == 'NC': binary_feature = binary_feature[:, 48:56] return binary_feature
def BSpline_SyN_ANTs_cleanup(setting, IN=None, out=None): if os.path.isfile( su.address_generator(setting, 'DVF_nonRigid_composed', cn=IN, out=out)): os.remove( su.address_generator(setting, 'DVF_nonRigid0', cn=IN, out=out)) os.remove( su.address_generator(setting, 'DVF_nonRigid1', cn=IN, out=out)) if out > 0: os.remove( su.address_generator(setting, 'DVF_perturb_without_affine', cn=IN, out=out))
def read_landmarks_pkl(setting, cn_list=None, exp_tre_list=None, exp_list=None): all_landmarks = dict() all_landmarks_merged = dict() legend_list = [] extra_exp_info = su.exp_info() if exp_tre_list is not None: exp_list = exp_tre_list for exp_full_name in exp_list: if exp_tre_list is None: exp = exp_full_name legend_text = exp_full_name else: exp = exp_full_name.rsplit('-', maxsplit=1)[0] legend_text = exp_full_name.rsplit('-', maxsplit=1)[1].rsplit('_')[1] legend_text = exp_full_name with open( su.address_generator(setting, 'landmark_file', current_experiment=exp), 'rb') as f: landmark_exp = pickle.load(f) all_landmarks[exp_full_name] = copy.deepcopy(landmark_exp) all_landmarks_merged[exp_full_name] = copy.deepcopy( merge_landmarks(landmark_exp, cn_list=cn_list)) if exp_full_name in extra_exp_info.keys(): legend_text = legend_text + ': ' + extra_exp_info[exp_full_name] # legend_text = '$' + legend_text + '_{' + exp.replace('_', '\_') + '}$' legend_text = legend_text legend_list.append(legend_text) return all_landmarks, all_landmarks_merged, legend_list
def ncmi(setting, cn=None, ncmi_executable=None, neighborhood_radius=None, config_file=None, pool_dir=None, pooled_name=None): # ToDO the call to executable might not work time_before = time.time() if ncmi_executable is None: ncmi_executable = setting['NCMIExeAddress'] if pool_dir is None: if not os.path.isdir(su.address_generator(setting, 'PoolFolder', cn=cn)): os.makedirs(su.address_generator(setting, 'PoolFolder', cn=cn)) feature = 'NCMI' if config_file is None: config_file = su.address_generator( setting, 'PoolingConfig', cn=cn, feature=feature, neighborhood_radius=neighborhood_radius) generate_config_file( config_path=Path(config_file), image_paths=[ Path(su.address_generator(setting, 'Im', cn=cn, type_im=0)), Path( su.address_generator(setting, 'nonRigid_MovedImage', cn=cn, out=0)) ], mask_path=Path( su.address_generator(setting, 'errorImageMask', cn=cn, neighborhood_radius=neighborhood_radius)), output_dir=Path(su.address_generator(setting, 'PoolFolder', cn=cn)), max_boxsize=setting['NCMI_MaxBoxSize'], min_boxsize=setting['NCMI_MinBoxSize']) if pooled_name is None: pooled_feature_address = su.address_generator( setting, 'PooledFeature', feature=feature, cn=cn, neighborhood_radius=neighborhood_radius) pooled_name = pooled_feature_address.rsplit('/', maxsplit=1)[1] pooling_cmd = ncmi_executable + ' --config ' + config_file print(pooling_cmd) os.system(pooling_cmd) time_after = time.time() logging.debug('multi_registration: NCMMI cn={} is done in {:.2f}'.format( cn, time_after - time_before))
def affine_ANTs(setting, cn=None): fixedIm_address = su.address_generator(setting, 'Im', cn=cn, type_im=0) movingIm_address = su.address_generator(setting, 'Im', cn=cn, type_im=1) affineFolder = su.address_generator(setting, 'affineFolder', cn=cn) if not os.path.exists(affineFolder): os.makedirs(affineFolder) output_name = su.address_generator(setting, 'affineOut', cn=cn) number_of_threads = setting['numberOfThreads'] affine_script = su.address_generator(setting, 'affineScript', cn=cn) with open(affine_script, "w") as textScr: textScr.write(ANTsP.header_registration()) textScr.write(ANTsP.write_number_of_threads(number_of_threads)) textScr.write(ANTsP.write_fixed_image(fixedIm_address)) textScr.write(ANTsP.write_moving_image(movingIm_address)) textScr.write(ANTsP.write_dimension(setting['dimension'])) textScr.write(ANTsP.write_output(output_name)) if setting['useMask']: textScr.write( ANTsP.write_fixed_mask( su.address_generator(setting, setting['MaskName_Affine'][0], cn=cn, type_im=0))) textScr.write( ANTsP.write_moving_mask( su.address_generator(setting, setting['MaskName_Affine'][0], cn=cn, type_im=1))) textScr.write(ANTsP.affine_EMPIRE10(use_mask=setting['useMask'])) textScr.write(ANTsP.footer()) textScr.close() os.chmod(affine_script, 0o774) os.system(affine_script)
def BSpline_SyN_ANTs_cleanup_final(setting, cn=None, outfinal=None): if os.path.isfile( su.address_generator(setting, 'DVF_nonRigid_composed_final', cn=cn, outfinal=outfinal)): os.remove( su.address_generator(setting, 'DVF_nonRigid0_final', cn=cn, outfinal=outfinal)) os.remove( su.address_generator(setting, 'DVF_nonRigid1_final', cn=cn, outfinal=outfinal)) os.remove( su.address_generator(setting, 'DVF_perturb_pure_final', cn=cn, outfinal=outfinal))
def BSpline_SyN_ANTs_transform(setting, cn=None, out=None, number_of_transforms=2): if 'nonrigid_number_of_transform' in setting.keys(): number_of_transforms = setting[ 'nonrigid_number_of_transform'] # remove later fixedIm_address = su.address_generator(setting, 'Im', cn=cn, type_im=0) movingIm_address = su.address_generator(setting, 'Im', cn=cn, type_im=1) if number_of_transforms == 1: transform0 = su.address_generator(setting, 'DVF_nonRigid0', cn=cn, out=out) if number_of_transforms == 2: transform0 = su.address_generator(setting, 'DVF_nonRigid1', cn=cn, out=out) transform1 = su.address_generator(setting, 'DVF_nonRigid0', cn=cn, out=out) DVF_nonRigid_composed = su.address_generator(setting, 'DVF_nonRigid_composed', cn=cn, out=out) number_of_threads = setting['numberOfThreads'] nonrigid_transform_script = su.address_generator(setting, 'nonRigidTransformScript', cn=cn, out=out) with open(nonrigid_transform_script, "w") as textScr: # please note that the last registration that you did, should be the first transform parameters textScr.write(ANTsP.header_transform()) textScr.write(ANTsP.write_number_of_threads(number_of_threads)) textScr.write(ANTsP.write_input_image(movingIm_address)) textScr.write(ANTsP.write_reference_image(fixedIm_address)) textScr.write( ANTsP.write_transform_parameters(transform0, transform_number=0)) if number_of_transforms > 1: textScr.write( ANTsP.write_transform_parameters(transform1, transform_number=1)) textScr.write(ANTsP.write_dimension(setting['dimension'])) textScr.write(ANTsP.write_output(DVF_nonRigid_composed)) textScr.write( ANTsP.write_default_pixel_value(setting['defaultPixelValue'])) textScr.write( ANTsP.transform(number_of_transforms=number_of_transforms)) textScr.write(ANTsP.footer()) textScr.close() os.chmod(nonrigid_transform_script, 0o774) os.system(nonrigid_transform_script)
def convert_nii2mha(setting, cn=None, out_list=None): if out_list is None: out_list = np.arange(0, 21) if setting['registration_method'] == 'ANTs': for out in out_list: moved_nii_address = su.address_generator(setting, 'nonRigid_MovedImage', cn=cn, out=out) moved_mha_address = su.address_generator(setting, 'nonRigid_MovedImage_mha', cn=cn, out=out) if os.path.isfile(moved_nii_address): if not os.path.isfile(moved_mha_address): moved_nii_sitk = sitk.ReadImage(moved_nii_address) sitk.WriteImage(moved_nii_sitk, moved_mha_address) logging.debug( 'convert_nii2mha is done cn={}, out={}'.format( cn, out)) else: logging.debug( 'convert_nii2mha, nii exists: cn={}, out={}'.format( cn, out))
def affine_ANTs_transform(setting, cn=None): fixedIm_address = su.address_generator(setting, 'Im', cn=cn, type_im=0) movingIm_address = su.address_generator(setting, 'Im', cn=cn, type_im=1) affineOutMat = su.address_generator(setting, 'affineOutMat', cn=cn) affineDVF_address = su.address_generator(setting, 'affineDVF', cn=cn) number_of_threads = setting['numberOfThreads'] affine_transform_script = su.address_generator(setting, 'affineTransformScript', cn=cn) with open(affine_transform_script, "w") as textScr: textScr.write(ANTsP.header_transform()) textScr.write(ANTsP.write_number_of_threads(number_of_threads)) textScr.write(ANTsP.write_input_image(movingIm_address)) textScr.write(ANTsP.write_reference_image(fixedIm_address)) textScr.write(ANTsP.write_transform_parameters(affineOutMat)) textScr.write(ANTsP.write_dimension(setting['dimension'])) textScr.write(ANTsP.write_output(affineDVF_address)) textScr.write( ANTsP.write_default_pixel_value(setting['defaultPixelValue'])) textScr.write(ANTsP.transform(number_of_transforms=1)) textScr.write(ANTsP.footer()) textScr.close() os.chmod(affine_transform_script, 0o774) os.system(affine_transform_script)
def feature_pooling(setting, cn=None, feature_list=None, pooling_executable=None, neighborhood_radius=None): time_before = time.time() if pooling_executable is None: pooling_executable = setting['PoolingExeAddress'] if not os.path.isdir(su.address_generator(setting, 'PoolFolder', cn=cn)): os.makedirs(su.address_generator(setting, 'PoolFolder', cn=cn)) for feature in feature_list: config_file = su.address_generator( setting, 'PoolingConfig', cn=cn, feature=feature, neighborhood_radius=neighborhood_radius) config_str = 'image=' + su.address_generator(setting, feature, cn=cn) + '\n' config_str = config_str + 'mask=' + su.address_generator( setting, 'errorImageMask', cn=cn, neighborhood_radius=neighborhood_radius) + '\n' config_str = config_str + 'output=' + su.address_generator( setting, 'PoolFolder', cn=cn) + '\n' config_str = config_str + 'max_boxsize=' + str( setting['Pooling_MaxBoxSize']) + '\n' config_str = config_str + 'min_boxsize=' + str( setting['Pooling_MinBoxSize']) + '\n' config_str = config_str + 'abs_intensity_features=1' + '\n' with open(config_file, "w") as text_str: text_str.write(config_str) pooled_feature_address = su.address_generator( setting, 'PooledFeature', feature=feature, cn=cn, neighborhood_radius=neighborhood_radius) pooled_feature_pure_address = pooled_feature_address.rsplit( '/', maxsplit=1)[1] pooling_cmd = pooling_executable + ' --config ' + config_file + ' ' + pooled_feature_pure_address os.system(pooling_cmd) time_after = time.time() logging.debug('multi_registration: Pooling cn={} is done in {:.2f}'.format( cn, time_after - time_before))
def backup_script(setting, script_address): """ backup the current script :param script_address: current script address :return: backup_script_address: backup script address """ script_address = script_address.replace('\\', '/') # windows path correction script_name = script_address.rsplit('/', maxsplit=1)[1] script_folder = script_address.rsplit('/', maxsplit=1)[0] + '/' backup_number = 1 backup_root_folder = su.address_generator(setting, 'experimentRootFolder') + 'code_backup/' backup_folder = backup_root_folder + 'backup-' + str(backup_number) + '/' while os.path.isdir(backup_folder): backup_number = backup_number + 1 backup_folder = backup_root_folder + 'backup-' + str(backup_number) + '/' os.makedirs(backup_folder) shutil.copy(script_address, backup_folder) shutil.copytree(script_folder + '/Functions/Python/', backup_folder + '/Functions/Python/') backup_script_address = backup_folder + script_name return backup_script_address
def BSpline_SyN_ANTs_final_transform(setting, cn=None, outfinal=None): fixedIm_address = su.address_generator(setting, 'Im', cn=cn, type_im=0) movingIm_address = su.address_generator(setting, 'Im', cn=cn, type_im=1) transform1 = su.address_generator(setting, 'DVF_nonRigid0_final', cn=cn, outfinal=outfinal) transform0 = su.address_generator(setting, 'DVF_nonRigid1_final', cn=cn, outfinal=outfinal) DVF_nonRigid_composed = su.address_generator(setting, 'DVF_nonRigid_composed_final', cn=cn, outfinal=outfinal) number_of_threads = setting['numberOfThreads'] script = su.address_generator(setting, 'nonRigidTransformScript_final', cn=cn, outfinal=outfinal) with open(script, "w") as textScr: # please note that the last registration that you did, should be the first transform parameters textScr.write(ANTsP.header_transform()) textScr.write(ANTsP.write_number_of_threads(number_of_threads)) textScr.write(ANTsP.write_input_image(movingIm_address)) textScr.write(ANTsP.write_reference_image(fixedIm_address)) textScr.write( ANTsP.write_transform_parameters(transform0, transform_number=0)) textScr.write( ANTsP.write_transform_parameters(transform1, transform_number=1)) textScr.write(ANTsP.write_dimension(setting['dimension'])) textScr.write(ANTsP.write_output(DVF_nonRigid_composed)) textScr.write( ANTsP.write_default_pixel_value(setting['defaultPixelValue'])) textScr.write(ANTsP.transform(number_of_transforms=2)) textScr.write(ANTsP.footer()) textScr.close() os.chmod(script, 0o774) os.system(script)
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 write_and_submit_job(setting, job_name=None, phase=None, cn=None, out=None, outfinal=None, script_address=None): if phase == 0: job_script_folder = su.address_generator(setting, 'affineFolder', cn=cn) job_output = su.address_generator(setting, 'affineJobOut', cn=cn) elif phase == 1: job_script_folder = su.address_generator(setting, 'nonRigidFolder', cn=cn, out=out) job_output = su.address_generator(setting, 'nonRigidJobOut', cn=cn, out=out) elif phase == 2: job_script_folder = su.address_generator(setting, 'nonRigidFolder_final', cn=cn, outfinal=outfinal) job_output = su.address_generator(setting, 'nonRigidJobOut_final', cn=cn, outfinal=outfinal) else: raise ValueError('phase is {}'.format(phase)) if not os.path.exists(job_script_folder): os.makedirs(job_script_folder) job_script = job_script_folder + 'jobscript.sh' with open(job_script, "w") as textScr: textScr.write( sungrid.job_script(setting, job_name=job_name, phase=phase, cn=cn, out=out, outfinal=outfinal, script_address=script_address, job_output=job_output)) textScr.close() qsub_cmd = 'qsub ' if setting['cluster_task_dependency']: queue_info, job_info = sungrid.qstat() all_jobs = queue_info + job_info found = False if phase == 1: for job in all_jobs: if not found: if setting['affine_experiment'] is None: affine_experiment = setting['current_experiment'] else: affine_experiment = setting['affine_experiment'] if affine_experiment + '_' + 'affine_cn_' + str( cn) == job['JB_name']: found = True print(job_name + ' will wait for ' + affine_experiment + '_' + 'affine_cn_' + str(cn)) qsub_cmd = qsub_cmd + '-hold_jid ' + job[ 'JB_name'] + ' ' if not found: if setting['affine_experiment'] is not None: affine_step = setting['affine_experiment_step'] else: affine_step = 0 if not os.path.isfile( su.address_generator( setting, 'affineDVF', cn=cn, current_experiment=setting['affine_experiment'])): raise ValueError( 'The job ' + job_name + ' cannot be submitted, because neither ' + ' affine output is availalbe nor affine job = ' + 'affine_cn_' + str(cn) + 'is in the job list') if phase == 2: for job in all_jobs: if not found: if setting[ 'current_experiment'] + '_' + 'nonRigid_cn_' + str( cn) + '_out_0' == job['JB_name']: found = True print(job_name + ' will wait for ' + 'nonRigid_cn_' + str(cn) + '_out_0') qsub_cmd = qsub_cmd + '-hold_jid ' + job[ 'JB_name'] + ' ' if not found: if not os.path.isfile( su.address_generator( setting, 'DVF_nonRigid_composed', cn=cn, out=0)): raise ValueError( 'The job ' + job_name + ' cannot be submitted, because neither ' + ' nonrigid output is availalbe nor nonrigidjob = ' + 'nonRigid_cn_' + str(cn) + '_out_0' + 'is in the job list') qsub_cmd = qsub_cmd + job_script os.system(qsub_cmd)
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)
def BSpline_SyN_ANTs(setting, cn=None, out=None): if 'ImageType_Registration' in setting.keys(): image_type_registration = setting['ImageType_Registration'] else: image_type_registration = 'Im' fixed_im_address = su.address_generator(setting, image_type_registration, cn=cn, type_im=0) moving_im_address = su.address_generator(setting, image_type_registration, cn=cn, type_im=1) output_name = su.address_generator(setting, 'DVF_nonRigid', cn=cn, out=out) initial_transform = su.address_generator(setting, 'DVF_perturb', cn=cn, out=out) number_of_threads = setting['numberOfThreads'] nonrigid_script = su.address_generator(setting, 'nonRigidScript', cn=cn, out=out) folder_address = su.address_generator(setting, 'nonRigidFolder', cn=cn, out=out) if not os.path.exists(folder_address): os.makedirs(folder_address) with open(nonrigid_script, "w") as textScr: textScr.write(ANTsP.header_registration()) textScr.write(ANTsP.write_number_of_threads(number_of_threads)) textScr.write(ANTsP.write_fixed_image(fixed_im_address)) textScr.write(ANTsP.write_moving_image(moving_im_address)) textScr.write(ANTsP.write_initial_transform(initial_transform)) textScr.write(ANTsP.write_dimension(setting['dimension'])) textScr.write(ANTsP.write_output(output_name)) if setting['useMask']: textScr.write( ANTsP.write_fixed_mask( su.address_generator(setting, setting['MaskName_BSpline'], cn=cn, type_im=0))) textScr.write( ANTsP.write_moving_mask( su.address_generator(setting, setting['MaskName_BSpline'], cn=cn, type_im=1))) if os.path.isfile( su.address_generator(setting, 'ParameterFolder') + setting['NonRigidParameter']): with open( su.address_generator(setting, 'ParameterFolder') + setting['NonRigidParameter'], 'r') as f_parameter: parameter_str = f_parameter.read() textScr.write('command="antsRegistration ' + parameter_str + '"') else: textScr.write(ANTsP.BSpline_SyN_EMPIRE10(setting)) textScr.write(ANTsP.footer()) textScr.close() os.chmod(nonrigid_script, 0o774) os.system(nonrigid_script)
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 do_elastix_registration(): cn_range = np.arange(1, 11) where_to_run = 'sharkCluster' # 'local' , 'sharkCluster' , 'shark' database = 'DIR-Lab_COPD' current_experiment = 'elastix1' if not su.load_setting(current_experiment, data=database, where_to_run=where_to_run): registration_method = 'elastix' setting = su.initialize_setting(current_experiment, data=database, where_to_run=where_to_run, registration_method=registration_method) setting['affine_experiment'] = 'elastix1' # you can choose to use the affine result of the current experiment or from another experiment. # This is useful when you want to tune the nonrigid registration. if it is None, then the affine folder in the current experiment is used setting['affine_experiment_step'] = 0 setting['BSplineGridExperiment'] = 'elastix1' setting['AffineParameter'] = ['par0049.affine.txt'] setting['MaskName_Affine'] = ['Torso'] setting['MaskName_BSpline'] = 'Lung_Atlas' setting['MaskName_BSpline_Final'] = 'Lung_Atlas' setting['BSplineGridParameter'] = 'par0049.bspline.grid.txt' setting['BSplineParameter'] = 'par0049_stdT-advanced.txt' setting['BSplineParameter_final'] = 'par0049_stdTL-advanced.txt' setting['numberOfThreads'] = 7 su.write_setting(setting) else: setting = su.load_setting(current_experiment, data=database, where_to_run=where_to_run) setting['cluster_phase'] = 1 # 0: affine, 1: initial perturb + BSpline, 2:final perturb + BSpline setting = check_input_arguments(setting) # if script have some arguments, it goes to 'sharkCluster' mode. Now you can modify the code after submitting the jobs. if setting['whereToRun'] == 'local' or setting['whereToRun'] == 'shark': backup_script_address = backup_script(setting, os.path.realpath(__file__)) for cn in range(1, 11): # reg_elx.affine(setting, cn=cn) # reg_elx.affine_transform(setting, cn=cn) hi = 1 for out in range(0, 1): # reg_elx.perturbation(setting, cn=cn, out=out) # reg_elx.bspline(setting, cn=cn, out=out) # reg_elx.correct_initial_transform(setting, cn=cn, out=out) # reg_elx.bspline_transform(setting, cn=cn, out=out, dvf=True) hi = 1 for outfinal in range(1, 21): # reg_elx.perturbation(setting, cn=cn, outfinal=outfinal) # reg_elx.bspline_final(setting, cn=cn, outfinal=outfinal) # reg_elx.correct_initial_transform(setting, cn=cn, outfinal=outfinal) # reg_elx.bspline_final_transform(setting, cn=cn, outfinal=outfinal) hi = 1 elif setting['whereToRun'] == 'sharkCluster': parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument('--cn', metavar='N', type=int, nargs='+', help='an integer for the accumulator') parser.add_argument('--out', metavar='N', type=int, nargs='+', help='an integer for the accumulator') parser.add_argument('--outfinal', metavar='N', type=int, nargs='+', help='an integer for the accumulator') parser.add_argument('--phase', metavar='N', type=int, nargs='+', help='an integer for the accumulator') args = parser.parse_args() if args.phase is not None: # clusterMode is in the run mode phase = args.phase[0] if args.cn is not None: cn = args.cn[0] if args.out is not None: out = args.out[0] if args.outfinal is not None: outfinal = args.outfinal[0] if phase == 0: logging.debug('phase={}, cn={} '.format(phase, cn)) reg_elx.affine(setting, cn=cn) if phase == 1: logging.debug('phase={}, cn={}, out={} '.format(phase, cn, out)) reg_elx.perturbation(setting, cn=cn, out=out) reg_elx.bspline(setting, cn=cn, out=out) reg_elx.bspline_transform(setting, cn=cn, out=out, dvf=True) if phase == 2: logging.debug('phase={}, cn={}, outfinal={} '.format(phase, cn, outfinal)) reg_elx.perturbation(setting, cn=cn, outfinal=outfinal) reg_elx.bspline_final(setting, cn=cn, outfinal=outfinal) else: # clusterMode is in the preparing_jobs mode backup_script_address = backup_script(setting, os.path.realpath(__file__)) phase = setting['cluster_phase'] if phase == 0: for cn in cn_range: if not os.path.isfile(su.address_generator(setting, 'affineTransformParameter', cn=cn)): job_name = setting['current_experiment'] + '_' + 'affine_cn_' + str(cn) reg_elx.write_and_submit_job(setting, job_name=job_name, phase=phase, cn=cn, script_address=backup_script_address) if phase == 1: for cn in cn_range: for out in range(0, 1): job_name = setting['current_experiment'] + '_' + 'nonRigid_cn_' + str(cn) + '_out_' + str(out) reg_elx.write_and_submit_job(setting, job_name=job_name, phase=phase, cn=cn, out=out, script_address=backup_script_address) if phase == 2: for cn in cn_range: for outfinal in range(1, 21): # if not os.path.isfile(su.address_generator(setting, 'DVF_nonRigid_composed_final', IN=cn, outfinal=outfinal)): job_name = setting['current_experiment'] + '_' + 'nonRigid_cn_' + str(cn) + '_outfinal_' + str(outfinal) reg_elx.write_and_submit_job(setting, job_name=job_name, phase=phase, cn=cn, outfinal=outfinal, script_address=backup_script_address)
def plot_loss(setting, cn_list=None, out=None, exp_list=None): loss = loss_function(setting, cn_list=cn_list, out=out, exp_list=exp_list) stage_len = 20 inter_stage_len = 1 horizontal_number = [] horizontal_limit = dict() xtick_locs = [] xtick_labels = [] xtick_labels_dict = dict() color_dict = color_constants.color_dict() color_keys = [ 'red1', 'blue', 'green', 'purple', 'orange', 'cyan2', 'brick', 'cobaltgreen', 'deeppink4', 'gold1', 'midnightblue', 'chartreuse4', 'darkolivegreen', 'indigo', 'seagreen4', 'blue4' ] color_list = [color_dict[color_key] for color_key in color_keys] # x = np.linspace(0.0, 1.0, 50) # color_list = cm.get_cmap('prism')(x)[:, :3] number_of_stages = loss['max_stage'] for i_stage, stage in enumerate(range(number_of_stages - 1, -1, -1)): horizontal_limit['stage' + str(stage)] = {} horizontal_limit[ 'stage' + str(stage)]['start'] = i_stage * stage_len + inter_stage_len - 1 horizontal_limit[ 'stage' + str(stage)]['end'] = i_stage * stage_len + stage_len - 1 xtick_locs.append((horizontal_limit['stage' + str(stage)]['start'] + horizontal_limit['stage' + str(stage)]['end']) / 2) xtick_labels.append('stage' + str(stage)) for cn in cn_list: xtick_labels_dict['cn' + str(cn)] = [] for stage in range(number_of_stages - 1, -1, -1): xtick_labels_dict['cn' + str(cn)].append( 'stage' + str(stage) + '-' + str(loss['max_itr_stage' + str(stage) + '_cn' + str(cn)])) exp_dict = su.exp_info() for cn in cn_list: fig1, axe1 = plt.subplots(num=1, figsize=(18, 6)) for exp_i, exp in enumerate(exp_list): printed_label = False for stage in range(number_of_stages - 1, -1, -1): if 'stage' + str(stage) in loss[exp]['cn' + str(cn)].keys(): loss_exp_stage = loss[exp]['cn' + str(cn)][ 'stage' + str(stage)]['loss'].copy() horizontal_number_fixed = np.linspace( horizontal_limit['stage' + str(stage)]['start'], horizontal_limit['stage' + str(stage)]['end'], loss['max_itr_stage' + str(stage) + '_cn' + str(cn)]) horizontal_number_stage = horizontal_number_fixed[ 0:len(loss_exp_stage)] if not printed_label: loss_label = exp + '_' + exp_dict[exp + '-TRE_nonrigid'] printed_label = True else: loss_label = None axe1.plot(horizontal_number_stage, loss_exp_stage, color=color_list[exp_i], label=loss_label) axe1.legend() plt.xticks(xtick_locs, xtick_labels_dict['cn' + str(cn)], fontsize=16) plt.title('copd' + str(cn)) plt.draw() plt.savefig(su.address_generator(setting, 'LossPlotItr', cn=cn)) plt.close() for cn in cn_list: fig1, axe1 = plt.subplots(num=1, figsize=(18, 6)) for exp_i, exp in enumerate(exp_list): horizontal_number = [] loss_exp = [] for stage in range(number_of_stages - 1, -1, -1): if 'stage' + str(stage) in loss[exp]['cn' + str(cn)].keys(): y = loss[exp]['cn' + str(cn)]['stage' + str(stage)]['loss'].copy() horizontal_number.extend( np.linspace( horizontal_limit['stage' + str(stage)]['start'], horizontal_limit['stage' + str(stage)]['end'], len(y))) loss_exp.extend(y) axe1.plot(horizontal_number, loss_exp, label=exp + '_' + exp_dict[exp + '-TRE_nonrigid'], color=color_list[exp_i]) axe1.legend() plt.xticks(xtick_locs, xtick_labels, fontsize=16) plt.title('copd' + str(cn)) plt.draw() plt.savefig(su.address_generator(setting, 'LossPlot', cn=cn)) plt.close()
def loss_function(setting, cn_list=None, out=None, exp_list=None): loss = dict() number_of_stages_dic = {'ANTs1': 4} loss['max_stage'] = 0 for exp in exp_list: loss['max_stage'] = max(loss['max_stage'], number_of_stages_dic[exp]) for stage in range(loss['max_stage']): for cn in cn_list: loss['max_itr_stage' + str(stage) + '_cn' + str(cn)] = 0 for exp in exp_list: loss[exp] = {} if not su.load_setting( exp, data=setting['data'], where_to_run=setting['whereToRun']): setting_exp = copy.deepcopy(setting) setting_exp['current_experiment'] = exp else: setting_exp = su.load_setting(exp, data=setting['data'], where_to_run=setting['whereToRun']) number_of_stages = number_of_stages_dic[exp] for cn in cn_list: nonrigid_folder = su.address_generator(setting_exp, 'nonRigidFolder', cn=cn, out=out) jobout_list = [] for file in os.listdir(nonrigid_folder): if 'jobOut' in file: jobout_list.append(file) jobout_address = nonrigid_folder + jobout_list[-1] with open(jobout_address, 'r') as f: jobout_str = f.read() loss[exp]['cn' + str(cn)] = {} loss[exp]['cn' + str(cn)]['loss_points'] = [] stage = copy.copy(number_of_stages) for line in jobout_str.splitlines(): if 'XDIAGNOSTIC' in line: stage = stage - 1 loss[exp]['cn' + str(cn)]['stage' + str(stage)] = {} loss[exp]['cn' + str(cn)]['stage' + str(stage)]['loss'] = [] if 'WDIAGNOSTIC' in line: loss[exp]['cn' + str(cn)]['stage' + str(stage)]['loss'].append( float(line.split(',')[2])) for stage in range(number_of_stages - 1, -1, -1): if 'stage' + str(stage) in loss[exp]['cn' + str(cn)].keys(): loss[exp]['cn' + str(cn)]['stage' + str(stage)]['first_itr'] = loss[exp][ 'cn' + str(cn)]['stage' + str(stage)]['loss'][0] loss[exp]['cn' + str(cn)]['stage' + str(stage)]['last_itr'] = loss[exp][ 'cn' + str(cn)]['stage' + str(stage)]['loss'][-1] loss[exp]['cn' + str(cn)]['loss_points'].append( loss[exp]['cn' + str(cn)]['stage' + str(stage)]['first_itr']) loss[exp]['cn' + str(cn)]['loss_points'].append( loss[exp]['cn' + str(cn)]['stage' + str(stage)]['last_itr']) y = loss[exp]['cn' + str(cn)]['stage' + str(stage)]['loss'] if len(y) > loss['max_itr_stage' + str(stage) + '_cn' + str(cn)]: loss['max_itr_stage' + str(stage) + '_cn' + str(cn)] = len(y) # print('max_len_itr_stage{} is {}. exp='.format(stage, loss['max_itr_stage'+str(stage)+'_cn'+str(cn)]) + exp + ', cn={}, stage={}'.format(cn, stage)) return loss
def load_features(setting, landmarks=None, feature_list=None, cn_list=None, pooled_feature_list_ref=None, image_feature_list_ref=None): """ This function load all the features available in feature_list: First, it loads the landmarks file if available. By default, it does not overwrite features in this dictionary. Some feature are in image-based format: 'stdT', 'E_T', 'stdT_final', 'E_T_final', 'Jac', 'MIND', 'CV'. These features can be used directly for no-pool experiment. Some other features are only available within the landmark regions: 'NCMI', 'MI', 'NC'. In no-pool experiment, PMIS with the box size of 15mm is used. This is the 10th element in MI vector Finally, it writes the landmark dictionary to the disk :param setting: :param landmarks: :param feature_list: :param cn_list: :param pooled_feature_list_ref: :param image_feature_list_ref: :return: """ if pooled_feature_list_ref is None: pooled_feature_list_ref = [ 'stdT', 'E_T', 'stdT_final', 'E_T_final', 'Jac', 'MIND', 'CV', 'NCMI', 'MI', 'NC' ] if image_feature_list_ref is None: image_feature_list_ref = [ 'stdT', 'E_T', 'stdT_final', 'E_T_final', 'Jac', 'MIND', 'CV' ] landmark_address = su.address_generator(setting, 'landmark_file') if landmarks is None: if os.path.isfile(landmark_address): with open(landmark_address, 'rb') as f: landmarks = pickle.load(f) else: landmarks = dict() for cn in cn_list: if 'cn' + str(cn) not in landmarks.keys(): landmarks['cn' + str(cn)] = {} if len( list( set(['landmarkIndices', 'TRE_nonrigid', 'TRE_affine']) & set(landmarks['cn' + str(cn)].keys()))) < 3: error_mask = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, 'errorImageMask', cn=cn))) error_image_nonrigid = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, 'errorImage', cn=cn))) error_image_affine = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, 'errorImageAffine', cn=cn))) landmarks_indices = np.where(error_mask > 0) landmarks['cn' + str(cn)]['landmarkIndices'] = landmarks_indices landmarks['cn' + str( cn)]['TRE_nonrigid'] = error_image_nonrigid[landmarks_indices] landmarks[ 'cn' + str(cn)]['TRE_affine'] = error_image_affine[landmarks_indices] for feature in feature_list: if feature in image_feature_list_ref: if feature not in landmarks['cn' + str(cn)].keys(): feature_image = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, feature, cn=cn))) landmarks['cn' + str(cn)][feature] = feature_image[ landmarks['cn' + str(cn)]['landmarkIndices']] logging.debug('cn={}'.format(cn) + ', feature= ' + feature + ' is loaded') else: logging.debug( 'cn' + str(cn) + ', feature ' + feature + ' is already existed in the landmarks dictionary') if feature in pooled_feature_list_ref: feature_pooled = feature + '_pooled' if feature_pooled not in landmarks['cn' + str(cn)].keys(): landmarks['cn' + str(cn)][feature_pooled] = read_binary_feature( setting, cn=cn, feature=feature) if feature in ['MI', 'NC']: if feature not in landmarks['cn' + str(cn)].keys(): if feature == 'MI': landmarks['cn' + str(cn)][feature] = landmarks[ 'cn' + str(cn)][feature_pooled][:, 10] # In no-pool experiment, PMIS with the box size of 15mm is used. This is the 10th element in MI vector if feature == 'NC': landmarks['cn' + str(cn)][feature] = landmarks[ 'cn' + str(cn)][feature_pooled][:, 0] logging.debug('cn={}'.format(cn) + ', feature= ' + feature_pooled + ' is loaded') else: logging.debug( 'cn' + str(cn) + ', feature ' + feature_pooled + ' is already existed in the landmarks dictionary') if not os.path.exists(su.address_generator(setting, 'reportFolder')): os.makedirs(su.address_generator(setting, 'reportFolder')) with open(landmark_address, 'wb') as f: pickle.dump(landmarks, f) return landmarks
def do_ANTs_registration(): cn_range = np.arange(1, 11) out_range = np.arange(0, 21) outfinal_range = np.arange(1, 21) where_to_run = 'sharkCluster' # 'local' , 'sharkCluster' , 'shark' database = 'DIR-Lab_COPD' current_experiment = 'ANTs1' if not su.load_setting( current_experiment, data=database, where_to_run=where_to_run): registration_method = 'ANTs' setting = su.initialize_setting( current_experiment, data=database, where_to_run=where_to_run, registration_method=registration_method) # setting['initial_nonrigid_iterations'] = [150, 120, 100, 30] setting['NonRigidParameter'] = 'nonrigid.txt' setting['NonRigidParameter_final'] = 'nonrigid_final.txt' setting['ImageType_Registration'] = 'Im_Masked_Normalized' setting['MaskName_Affine'] = ['Torso'] setting['useMask'] = False setting['MaskName_BSpline'] = 'Lung_Filled' # Lung_Filled setting['MaskName_BSpline_Final'] = 'Lung_Filled' setting[ 'affine_experiment'] = 'elastix1' # you can choose to use the affine result of the current experiment or from another experiment. # This is useful when you want to tune the nonrigid registration. if it is None, then the affine folder in the current experiment is used setting['affine_experiment_step'] = 0 su.write_setting(setting) else: setting = su.load_setting(current_experiment, data=database, where_to_run=where_to_run) setting[ 'cluster_phase'] = 1 # 0: affine, 1: initial perturb + BSpline_SyN, 2:final perturb + BSpline_Syn setting['cluster_task_despendency'] = True setting = check_input_arguments( setting ) # if script have some arguments, it goes to 'sharkCluster' mode. Now you can modify the code after submitting the jobs. if setting['whereToRun'] == 'local' or setting['whereToRun'] == 'shark': backup_script_address = backup_script(setting, os.path.realpath(__file__)) for cn in [2]: # regANTs.affine_ANTs(setting, cn=cn) # regANTs.affine_ANTs_transform(setting, cn=cn) # regANTs.affine_ANTs_transform_image(setting, cn=cn) hi = 1 for out in range(0, 1): # regANTs.perturbation(setting, cn=cn, out=out) # regANTs.BSpline_SyN_ANTs(setting, cn=cn, out=out) # regANTs.BSpline_SyN_ANTs_transform(setting, cn=cn, out=out) # regANTs.BSpline_SyN_ANTs_cleanup(setting, IN=cn, out=out) # regANTs.BSpline_SyN_ANTs_transform_image(setting, IN=cn, out=out) # regANTs.convert_nii2mha(setting, cn=cn, out=out) hi = 1 for outfinal in range(1, 21): # regANTs.perturbation(setting, cn=cn, outfinal=outfinal) # regANTs.bspline_syn_ants_final(setting, cn=cn, outfinal=outfinal) # regANTs.BSpline_SyN_ANTs_final_transform(setting, cn=cn, outfinal=outfinal) # regANTs.BSpline_SyN_ANTs_cleanup_final(setting, cn=cn, outfinal=outfinal) hi = 1 elif setting['whereToRun'] == 'sharkCluster': parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument('--cn', metavar='N', type=int, nargs='+', help='an integer for the accumulator') parser.add_argument('--out', metavar='N', type=int, nargs='+', help='an integer for the accumulator') parser.add_argument('--outfinal', metavar='N', type=int, nargs='+', help='an integer for the accumulator') parser.add_argument('--phase', metavar='N', type=int, nargs='+', help='an integer for the accumulator') args = parser.parse_args() if args.phase is not None: # clusterMode is in the run mode phase = args.phase[0] if args.cn is not None: cn = args.cn[0] if args.out is not None: out = args.out[0] if args.outfinal is not None: outfinal = args.outfinal[0] if phase == 0: logging.debug('phase={}, cn={} '.format(phase, cn)) regANTs.affine_ANTs(setting, cn=cn) regANTs.affine_ANTs_transform(setting, cn=cn) regANTs.affine_ANTs_transform_image(setting, cn=cn) if phase == 1: logging.debug('phase={}, cn={}, out={} '.format( phase, cn, out)) regANTs.perturbation(setting, cn=cn, out=out) regANTs.BSpline_SyN_ANTs(setting, cn=cn, out=out) regANTs.BSpline_SyN_ANTs_transform(setting, cn=cn, out=out) regANTs.BSpline_SyN_ANTs_cleanup(setting, IN=cn, out=out) regANTs.BSpline_SyN_ANTs_transform_image(setting, IN=cn, out=out) if phase == 2: logging.debug('phase={}, cn={}, outfinal={} '.format( phase, cn, outfinal)) regANTs.perturbation(setting, cn=cn, outfinal=outfinal) regANTs.bspline_syn_ants_final(setting, cn=cn, outfinal=outfinal) regANTs.BSpline_SyN_ANTs_final_transform(setting, cn=cn, outfinal=outfinal) regANTs.BSpline_SyN_ANTs_cleanup_final(setting, cn=cn, outfinal=outfinal) else: # clusterMode is in the preparing_jobs mode backup_script_address = backup_script(setting, os.path.realpath(__file__)) phase = setting['cluster_phase'] if phase == 0: for cn in cn_range: if not os.path.isfile( su.address_generator(setting, 'affineDVF', cn=cn)): job_name = setting[ 'current_experiment'] + '_' + 'affine_cn_' + str( cn) regANTs.write_and_submit_job( setting, job_name=job_name, phase=phase, cn=cn, script_address=backup_script_address) if phase == 1: for cn in range(9, 11): for out in range(1, 21): job_name = setting[ 'current_experiment'] + '_' + 'nonRigid_cn_' + str( cn) + '_out_' + str(out) regANTs.write_and_submit_job( setting, job_name=job_name, phase=phase, cn=cn, out=out, script_address=backup_script_address) if phase == 2: for cn in range(9, 11): for outfinal in range(1, 21): if not os.path.isfile( su.address_generator( setting, 'DVF_nonRigid_composed_final', cn=cn, outfinal=outfinal)): job_name = setting[ 'current_experiment'] + '_' + 'nonRigid_cn_' + str( cn) + '_outfinal_' + str(outfinal) regANTs.write_and_submit_job( setting, job_name=job_name, phase=phase, cn=cn, outfinal=outfinal, script_address=backup_script_address)
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 bspline_syn_ants_final(setting, cn=None, outfinal=None): if 'ImageType_Registration' in setting.keys(): image_type_registration = setting['ImageType_Registration'] else: image_type_registration = 'Im' fixed_im_address = su.address_generator(setting, image_type_registration, cn=cn, type_im=0) moving_im_address = su.address_generator(setting, image_type_registration, cn=cn, type_im=1) output_name = su.address_generator(setting, 'DVF_nonRigid_final', cn=cn, outfinal=outfinal) initial_transform = su.address_generator(setting, 'DVF_perturb_final', cn=cn, outfinal=outfinal) number_of_threads = setting['numberOfThreads'] nonrigid_script_final = su.address_generator(setting, 'nonRigidScript_final', cn=cn, outfinal=outfinal) with open(nonrigid_script_final, "w") as textScr: textScr.write(ANTsP.header_registration()) textScr.write(ANTsP.write_number_of_threads(number_of_threads)) textScr.write(ANTsP.write_fixed_image(fixed_im_address)) textScr.write(ANTsP.write_moving_image(moving_im_address)) textScr.write(ANTsP.write_initial_transform(initial_transform)) textScr.write(ANTsP.write_dimension(setting['dimension'])) textScr.write(ANTsP.write_output(output_name)) if setting['useMask']: textScr.write( ANTsP.write_fixed_mask( su.address_generator(setting, setting['MaskName_BSpline_Final'], cn=cn, type_im=0))) textScr.write( ANTsP.write_moving_mask( su.address_generator(setting, setting['MaskName_BSpline_Final'], cn=cn, type_im=1))) if os.path.isfile( su.address_generator(setting, 'ParameterFolder') + setting['NonRigidParameter_final']): with open( su.address_generator(setting, 'ParameterFolder') + setting['NonRigidParameter_final'], 'r') as f_parameter: parameter_str = f_parameter.read() textScr.write('command="antsRegistration ' + parameter_str + '"') else: textScr.write(ANTsP.bspline_syn_empire10_final(setting)) textScr.write(ANTsP.footer()) textScr.close() os.chmod(nonrigid_script_final, 0o774) os.system(nonrigid_script_final)