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)
Example #2
0
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)
Example #3
0
# 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"