def create_semi_synthetic(params): r""" Create semi-synthetic image using real_mod1 as anatomy and tmp_mod2 template as intensity model Template tmp_mod1 is registered towards real_mod1 (which are assumed of the same modality) using SyN-CC. The transformation is applied to template tmp_mod2 (which is assumed to be perfectly aligned with tmp_mod1). The transfer function is computed from real_mod1 to warped tmp_mod2 and applied to real_mod1. """ real_mod1 = params.real base_fixed = getBaseFileName(real_mod1) tmp_mod1 = params.template prealign_name = params.prealign tmp_mod2_list = [os.path.join(params.warp_dir, name) for name in os.listdir(params.warp_dir)] tmp_mod2_list = [tmp_mod1] + tmp_mod2_list # Check if all warpings are already done warp_done = os.path.isfile("mask_" + base_fixed + ".nii.gz") if warp_done: for tmp_mod2 in tmp_mod2_list: base_moving = getBaseFileName(tmp_mod2) wname = "warpedDiff_" + base_moving + "_" + base_fixed if real_mod1[-3:] == "img": # Analyze wname += ".img" else: wname += ".nii.gz" if not os.path.isfile(wname): warp_done = False break # Load input images real_nib = nib.load(real_mod1) real_aff = real_nib.get_affine() real = real_nib.get_data().squeeze() if real_mod1[-3:] == "img": # Analyze: move reference from center to corner offset = real_aff[:3, :3].dot(np.array(real.shape) // 2) real_aff[:3, 3] += offset t_mod1_nib = nib.load(tmp_mod1) t_mod1_aff = t_mod1_nib.get_affine() t_mod1 = t_mod1_nib.get_data().squeeze() if tmp_mod1[-3:] == "img": # Analyze: move reference from center to corner offset = t_mod1_aff[:3, :3].dot(np.array(t_mod1.shape) // 2) t_mod1_aff[:3, 3] += offset # Load pre-align matrix print("Pre-align:", prealign_name) if not prealign_name: prealign = np.eye(4) else: if real_mod1[-3:] == "img": # Analyze ref_coordinate_system = "LAS" else: # DICOM ref_coordinate_system = "LPS" if tmp_mod1[-3:] == "img": # Analyze tgt_coordinate_system = "LAS" else: # DICOM tgt_coordinate_system = "LPS" prealign = readAntsAffine(prealign_name, ref_coordinate_system, tgt_coordinate_system) # Configure CC metric sigma_diff = 1.7 radius = 4 similarity_metric = metrics.CCMetric(3, sigma_diff, radius) # Configure optimizer opt_iter = [100, 100, 50] step_length = 0.25 opt_tol = 1e-5 inv_iter = 20 inv_tol = 1e-3 ss_sigma_factor = 0.2 if not warp_done: syn = imwarp.SymmetricDiffeomorphicRegistration( similarity_metric, opt_iter, step_length, ss_sigma_factor, opt_tol, inv_iter, inv_tol, callback=None ) # Run registration syn.verbosity = VerbosityLevels.DEBUG mapping = syn.optimize(real, t_mod1, real_aff, t_mod1_aff, prealign) # Save the warped template (so we can visually check the registration result) warped = mapping.transform(t_mod1) base_moving = getBaseFileName(tmp_mod1) oname = "warpedDiff_" + base_moving + "_" + base_fixed if real_mod1[-3:] == "img": # Analyze oname += ".img" else: oname += ".nii.gz" real[...] = warped[...] real_nib.to_filename(oname) mask = (t_mod1 > 0).astype(np.int32) wmask = mapping.transform(mask, "nearest") wmask_nib = nib.Nifti1Image(wmask, t_mod1_aff) wmask_nib.to_filename("mask_" + base_fixed + ".nii.gz") else: wmask_nib = nib.load("mask_" + base_fixed + ".nii.gz") wmask = wmask_nib.get_data().squeeze() # Compute and save the semi-synthetic images in different modalities for tmp_mod2 in tmp_mod2_list: print("Warping: " + tmp_mod2) t_mod2_nib = nib.load(tmp_mod2) t_mod2_aff = t_mod2_nib.get_affine() t_mod2 = t_mod2_nib.get_data().squeeze() base_moving = getBaseFileName(tmp_mod2) oname = base_moving + "_" + base_fixed if real_mod1[-3:] == "img": # Analyze oname += ".img" else: oname += ".nii.gz" if not warp_done: # Save warped image warped = mapping.transform(t_mod2) wnib = nib.Nifti1Image(warped, t_mod2_aff) wnib.to_filename("warpedDiff_" + oname) else: wnib = nib.load("warpedDiff_" + oname) warped = wnib.get_data().squeeze() real_nib = nib.load(real_mod1) real = real_nib.get_data().squeeze() use_density_estimation = True nbins = 100 if use_density_estimation: print("Using density sampling.") oname = "ssds_" + oname # Compute marginal distributions densities = np.array(compute_densities(real.astype(np.int32), warped.astype(np.float64), nbins, wmask)) # Sample the marginal distributions real[...] = create_ss_de(real.astype(np.int32), densities) else: print("Using mean transfer.") oname = "ssmt_" + oname # Compute transfer function means, vars = get_mean_transfer(real, warped) # Apply transfer to real real[...] = means[real] # Save semi_synthetic real_nib.to_filename(oname)
def register_3d(params): r''' Runs the non-linear registration with the parsed parameters ''' print('Registering %s to %s'%(params.target, params.reference)) sys.stdout.flush() metric_name=params.metric[0:params.metric.find('[')] metric_params_list=params.metric[params.metric.find('[')+1:params.metric.find(']')].split(',') moving_mask = None static_mask = None #Initialize the appropriate metric if metric_name == 'SSD': smooth=float(metric_params_list[0]) inner_iter=int(metric_params_list[1]) iter_type = metric_params_list[2] similarity_metric = metrics.SSDMetric( 3, smooth, inner_iter, iter_type) elif metric_name=='EM': smooth=float(metric_params_list[0]) q_levels=int(metric_params_list[1]) inner_iter=int(metric_params_list[2]) iter_type = metric_params_list[3] double_gradient=False if params.single_gradient else True similarity_metric = metrics.EMMetric( 3, smooth, inner_iter, q_levels, double_gradient, iter_type) similarity_metric.mask0 = params.mask0 elif metric_name=='POLY': print('>>>>>>>>>>>>>>>>OK<<<<<<<<<<<<<') from dipy.align.polynomial import PolynomialTransfer degree=int(metric_params_list[0]) smooth=float(metric_params_list[1]) q_levels=int(metric_params_list[2]) cprop=float(metric_params_list[3]) drop_zeros=int(metric_params_list[4])!=0 similarity_metric = PolynomialTransfer(3, degree, smooth, q_levels, cprop, drop_zeros) similarity_metric.mask0 = params.mask0 elif metric_name=='CC': sigma_diff = float(metric_params_list[0]) radius = int(metric_params_list[1]) similarity_metric = metrics.CCMetric(3, sigma_diff, radius) elif metric_name=='ECC': from dipy.align.ECCMetric import ECCMetric sigma_diff = float(metric_params_list[0]) radius = int(metric_params_list[1]) q_levels = int(metric_params_list[2]) similarity_metric = ECCMetric(3, sigma_diff, radius, q_levels) if params.target_mask is not None and os.path.isfile(params.target_mask): moving_mask = nib.load(params.target_mask) moving_mask = moving_mask.get_data().squeeze() moving_mask = (moving_mask>0).astype(np.int32) if params.reference_mask is not None and os.path.isfile(params.reference_mask): static_mask = nib.load(params.reference_mask) static_mask = static_mask.get_data().squeeze() static_mask = (static_mask>0).astype(np.int32) #Initialize the optimizer opt_iter = [int(i) for i in params.iter.split(',')] step_length = float(params.step_length) opt_tol = 1e-5 inv_iter = int(params.inversion_iter) inv_tol = float(params.inversion_tolerance) ss_sigma_factor = float(params.ss_sigma_factor) registration_optimizer = imwarp.SymmetricDiffeomorphicRegistration( similarity_metric, opt_iter, step_length, ss_sigma_factor, opt_tol, inv_iter, inv_tol, None) if hasattr(registration_optimizer, 'inv_type'): print('Inversion type: %s'%(registration_optimizer.inv_type,)) #Load the data moving, moving_affine = load_nifti(params.target) fixed, fixed_affine = load_nifti(params.reference) # If internediate is not None, we need to run two registrations if params.intermediate is not None: intermediate, intermediate_affine = load_nifti(params.intermediate) inter_to_reference_aff = readAntsAffine(params.inter_to_reference_aff, 'LPS', 'LPS') inter_to_target_aff = readAntsAffine(params.inter_to_target_aff, 'LPS', 'LPS') registration_optimizer.verbosity = VerbosityLevels.DEBUG inter_to_ref = registration_optimizer.optimize(fixed, intermediate, fixed_affine, intermediate_affine, inter_to_reference_aff) inter_to_moving = registration_optimizer.optimize(moving, intermediate, moving_affine, intermediate_affine, inter_to_target_aff) save_registration_results(inter_to_ref, params, inter_to_moving) else: print('Affine:', params.affine) if not params.affine: transform = np.eye(4) else: #http://fieldtrip.fcdonders.nl/faq/how_are_the_different_head_and_mri_coordinate_systems_defined if params.reference[:-3] == 'img': # Analyze ref_coordinate_system = 'LAS' else: # DICOM ref_coordinate_system = 'LPS' if params.target[:-3] == 'img': # Analyze tgt_coordinate_system = 'LAS' else: # DICOM tgt_coordinate_system = 'LPS' transform = readAntsAffine(params.affine, ref_coordinate_system, tgt_coordinate_system) init_affine = np.linalg.inv(moving_affine).dot(transform.dot(fixed_affine)) #Preprocess the data moving = (moving-moving.min())/(moving.max()-moving.min()) fixed = (fixed-fixed.min())/(fixed.max()-fixed.min()) #Run the registration if params.output_list is not None and 'affine_only' in params.output_list: print('Applying affine only') sh_direct=fixed.shape + (3,) sh_inv=moving.shape + (3,) direct = np.zeros(shape = sh_direct, dtype=np.float32) inv = np.zeros(shape = sh_inv, dtype=np.float32) mapping=imwarp.DiffeomorphicMap(3, direct, inv, None, init_affine) else: registration_optimizer.verbosity = VerbosityLevels.DEBUG mapping = registration_optimizer.optimize(fixed, moving, fixed_affine, moving_affine, transform) del registration_optimizer del similarity_metric save_registration_results(mapping, params)
# Result using CC wt1_cc_name = basedir + "\\warp\\SyNCC\\warpedDiff_SCIL_01_t1_strip_SCIL_01_b0_down_strip.nii.gz" wt1_cc, wt1_aff = load_nib(wt1_cc_name) wb0_cc_name = basedir + "\\warp\\SyNCC\\warpedDiff_SCIL_01_b0_down_strip_SCIL_01_t1_strip.nii.gz" wb0_cc, wb0_aff = load_nib(wb0_cc_name) # Result using MI wt1_mi_name = basedir + "\\warp\\SyNMI\\warpedDiff_SCIL_01_t1_strip_SCIL_01_b0_down_strip.nii.gz" wt1_mi, wt1_aff = load_nib(wt1_mi_name) wt1_b0up_mi_name = basedir + "\\warp\\SyNMI\\warpedDiff_SCIL_01_t1_strip_SCIL_01_b0_up_strip.nii.gz" wt1_b0up_mi, wt1_aff = load_nib(wt1_b0up_mi_name) wb0_mi_name = basedir + "\\warp\\SyNMI\\warpedDiff_SCIL_01_b0_down_strip_SCIL_01_t1_strip.nii.gz" wb0_mi, wb0_aff = load_nib(wb0_mi_name) wb0_up_mi_name = basedir + "\\warp\\SyNMI\\warpedDiff_SCIL_01_b0_up_strip_SCIL_01_t1_strip.nii.gz" wb0_up_mi, wb0_up_aff = load_nib(wb0_up_mi_name) A = readAntsAffine(basedir + reg_t1_toward_b0) T = np.linalg.inv(t1_aff).dot(A.dot(b0_aff)) shape = np.array(b0.shape, dtype=np.int32) wb0_mi_aligned = np.array( vfu.warp_3d_affine(wb0_mi.astype(np.float32), shape, T)) A = readAntsAffine(basedir + reg_t1_toward_b0_up) T = np.linalg.inv(t1_aff).dot(A.dot(b0up_aff)) shape = np.array(b0.shape, dtype=np.int32) wb0_up_mi_aligned = np.array( vfu.warp_3d_affine(wb0_up_mi.astype(np.float32), shape, T)) # Result using ECC wt1_ecc_name = basedir + "\\warp\\SyNECC\\warpedDiff_SCIL_01_t1_strip_SCIL_01_b0_down_strip.nii.gz" wt1_ecc, wt1_aff = load_nib(wt1_ecc_name) wt1_b0up_ecc_name = basedir + "\\warp\\SyNECC\\warpedDiff_SCIL_01_t1_strip_SCIL_01_b0_up_strip.nii.gz"