コード例 #1
0
def main():

    time_start = ph.start_timing()

    # Set print options for numpy
    np.set_printoptions(precision=3)

    # Read input
    input_parser = InputArgparser(
        description="Script to study reconstruction parameters and their "
        "impact on the volumetric reconstruction quality. "
        "This script can only be used to sweep through one single parameter, "
        "e.g. the regularization parameter 'alpha'. ")
    input_parser.add_filenames(required=True)
    input_parser.add_filenames_masks()
    input_parser.add_suffix_mask(default="_mask")
    input_parser.add_dir_input_mc()
    input_parser.add_dir_output(required=True)
    input_parser.add_reconstruction_space()
    input_parser.add_reference(
        help="Path to reference NIfTI image file. If given the volumetric "
        "reconstructed is performed in this physical space. "
        "Either a reconstruction space or a reference must be provided",
        required=False)
    input_parser.add_reference_mask(default=None)
    input_parser.add_study_name()
    input_parser.add_reconstruction_type(default="TK1L2")
    input_parser.add_measures(
        default=["PSNR", "MAE", "RMSE", "SSIM", "NCC", "NMI"])
    input_parser.add_tv_solver(default="PD")
    input_parser.add_iterations(default=50)
    input_parser.add_rho(default=0.1)
    input_parser.add_iter_max(default=10)
    input_parser.add_minimizer(default="lsmr")
    input_parser.add_log_config(default=1)
    input_parser.add_use_masks_srr(default=0)
    input_parser.add_verbose(default=1)
    input_parser.add_slice_thicknesses(default=None)
    input_parser.add_argument(
        "--append",
        "-append",
        action='store_true',
        help="If given, results are appended to previously executed parameter "
        "study with identical parameters and study name store in the output "
        "directory.")

    # Range for parameter sweeps
    input_parser.add_alphas(default=list(np.linspace(0.01, 0.5, 5)))
    input_parser.add_data_losses(default=["linear"]
                                 # default=["linear", "arctan"]
                                 )
    input_parser.add_data_loss_scales(default=[1]
                                      # default=[0.1, 0.5, 1.5]
                                      )

    args = input_parser.parse_args()
    input_parser.print_arguments(args)

    if args.reference is None and args.reconstruction_space is None:
        raise IOError("Either reference (--reference) or reconstruction space "
                      "(--reconstruction-space) must be provided.")

    if args.log_config:
        input_parser.log_config(os.path.abspath(__file__))

    # --------------------------------Read Data--------------------------------
    ph.print_title("Read Data")

    data_reader = dr.MultipleImagesReader(
        file_paths=args.filenames,
        file_paths_masks=args.filenames_masks,
        suffix_mask=args.suffix_mask,
        dir_motion_correction=args.dir_input_mc,
        stacks_slice_thicknesses=args.slice_thicknesses,
    )

    data_reader.read_data()
    stacks = data_reader.get_data()
    ph.print_info("%d input stacks read for further processing" % len(stacks))

    if args.reference is not None:
        reference = st.Stack.from_filename(file_path=args.reference,
                                           file_path_mask=args.reference_mask,
                                           extract_slices=False)

        reconstruction_space = stacks[0].get_resampled_stack(reference.sitk)
        reconstruction_space = \
            reconstruction_space.get_stack_multiplied_with_mask()
        x_ref = sitk.GetArrayFromImage(reference.sitk).flatten()
        x_ref_mask = sitk.GetArrayFromImage(reference.sitk_mask).flatten()

    else:
        reconstruction_space = st.Stack.from_filename(
            file_path=args.reconstruction_space, extract_slices=False)
        reconstruction_space = stacks[0].get_resampled_stack(
            reconstruction_space.sitk)
        reconstruction_space = \
            reconstruction_space.get_stack_multiplied_with_mask()
        x_ref = None
        x_ref_mask = None

    # ----------------------------Set Up Parameters----------------------------
    parameters = {}
    parameters["alpha"] = args.alphas
    if len(args.data_losses) > 1:
        parameters["data_loss"] = args.data_losses
    if len(args.data_loss_scales) > 1:
        parameters["data_loss_scale"] = args.data_loss_scales

    # --------------------------Set Up Parameter Study-------------------------
    ph.print_title("Run Parameter Study")
    if args.study_name is None:
        name = args.reconstruction_type
    else:
        name = args.study_name

    reconstruction_info = {
        "shape": reconstruction_space.sitk.GetSize()[::-1],
        "origin": reconstruction_space.sitk.GetOrigin(),
        "spacing": reconstruction_space.sitk.GetSpacing(),
        "direction": reconstruction_space.sitk.GetDirection(),
    }

    # Create Tikhonov solver from which all information can be extracted
    # (also for other reconstruction types)
    tmp = tk.TikhonovSolver(
        stacks=stacks,
        reconstruction=reconstruction_space,
        alpha=args.alphas[0],
        iter_max=args.iter_max,
        data_loss=args.data_losses[0],
        data_loss_scale=args.data_loss_scales[0],
        reg_type="TK1",
        minimizer=args.minimizer,
        verbose=args.verbose,
        use_masks=args.use_masks_srr,
    )
    solver = tmp.get_solver()

    parameter_study_interface = \
        deconv_interface.DeconvolutionParameterStudyInterface(
            A=solver.get_A(),
            A_adj=solver.get_A_adj(),
            D=solver.get_B(),
            D_adj=solver.get_B_adj(),
            b=solver.get_b(),
            x0=solver.get_x0(),
            alpha=solver.get_alpha(),
            x_scale=solver.get_x_scale(),
            data_loss=solver.get_data_loss(),
            data_loss_scale=solver.get_data_loss_scale(),
            iter_max=solver.get_iter_max(),
            minimizer=solver.get_minimizer(),
            iterations=args.iterations,
            measures=args.measures,
            dimension=3,
            L2=16. / reconstruction_space.sitk.GetSpacing()[0]**2,
            reconstruction_type=args.reconstruction_type,
            rho=args.rho,
            dir_output=args.dir_output,
            parameters=parameters,
            name=name,
            reconstruction_info=reconstruction_info,
            x_ref=x_ref,
            x_ref_mask=x_ref_mask,
            tv_solver=args.tv_solver,
            verbose=args.verbose,
            append=args.append,
        )
    parameter_study_interface.set_up_parameter_study()
    parameter_study = parameter_study_interface.get_parameter_study()

    # Run parameter study
    parameter_study.run()

    print("\nComputational time for Deconvolution Parameter Study %s: %s" %
          (name, parameter_study.get_computational_time()))

    return 0
コード例 #2
0
def main():

    # Set print options
    np.set_printoptions(precision=3)
    pd.set_option('display.width', 1000)

    input_parser = InputArgparser(description=".", )
    input_parser.add_filenames(required=True)
    input_parser.add_reference(required=True)
    input_parser.add_reference_mask()
    input_parser.add_dir_output(required=False)
    input_parser.add_measures(
        default=["PSNR", "RMSE", "MAE", "SSIM", "NCC", "NMI"])
    input_parser.add_verbose(default=0)
    args = input_parser.parse_args()
    input_parser.print_arguments(args)

    ph.print_title("Image similarity")
    data_reader = dr.MultipleImagesReader(args.filenames)
    data_reader.read_data()
    stacks = data_reader.get_data()

    reference = st.Stack.from_filename(args.reference, args.reference_mask)

    for stack in stacks:
        try:
            stack.sitk - reference.sitk
        except RuntimeError as e:
            raise IOError(
                "All provided images must be at the same image space")

    x_ref = sitk.GetArrayFromImage(reference.sitk)

    if args.reference_mask is None:
        indices = np.where(x_ref != np.inf)
    else:
        x_ref_mask = sitk.GetArrayFromImage(reference.sitk_mask)
        indices = np.where(x_ref_mask > 0)

    measures_dic = {
        m: lambda x, m=m: SimilarityMeasures.similarity_measures[m]
        (x[indices], x_ref[indices])
        # SimilarityMeasures.similarity_measures[m](x, x_ref)
        for m in args.measures
    }

    observer = obs.Observer()
    observer.set_measures(measures_dic)
    for stack in stacks:
        nda = sitk.GetArrayFromImage(stack.sitk)
        observer.add_x(nda)

    if args.verbose:
        stacks_comparison = [s for s in stacks]
        stacks_comparison.insert(0, reference)
        sitkh.show_stacks(
            stacks_comparison,
            segmentation=reference,
        )

    observer.compute_measures()
    measures = observer.get_measures()

    # Store information in array
    error = np.zeros((len(stacks), len(measures)))
    cols = measures
    rows = []
    for i_stack, stack in enumerate(stacks):
        error[i_stack, :] = np.array([measures[m][i_stack] for m in measures])
        rows.append(stack.get_filename())

    header = "# Ref: %s, Ref-Mask: %d, %s \n" % (
        reference.get_filename(),
        args.reference_mask is None,
        ph.get_time_stamp(),
    )
    header += "# %s\n" % ("\t").join(measures)

    path_to_file_filenames = os.path.join(args.dir_output, "filenames.txt")
    path_to_file_similarities = os.path.join(args.dir_output,
                                             "similarities.txt")

    # Write to files
    ph.write_to_file(path_to_file_similarities, header)
    ph.write_array_to_file(path_to_file_similarities, error, verbose=False)
    text = header
    text += "%s\n" % "\n".join(rows)
    ph.write_to_file(path_to_file_filenames, text)

    # Print to screen
    ph.print_subtitle("Computed Similarities")
    df = pd.DataFrame(error, rows, cols)
    print(df)

    return 0
コード例 #3
0
def main():

    time_start = ph.start_timing()

    # Set print options for numpy
    np.set_printoptions(precision=3)

    # Read input
    input_parser = InputArgparser(
        description="Script to study reconstruction parameters and their "
        "impact on the volumetric reconstruction quality.",
    )
    input_parser.add_dir_input()
    input_parser.add_filenames()
    input_parser.add_image_selection()
    input_parser.add_dir_output(required=True)
    input_parser.add_suffix_mask(default="_mask")
    input_parser.add_reconstruction_space()
    input_parser.add_reference(
        help="Path to reference NIfTI image file. If given the volumetric "
        "reconstructed is performed in this physical space. "
        "Either a reconstruction space or a reference must be provided",
        required=False)
    input_parser.add_reference_mask(default=None)
    input_parser.add_study_name()
    input_parser.add_reconstruction_type(default="TK1L2")
    input_parser.add_measures(default=["PSNR", "RMSE", "SSIM", "NCC", "NMI"])
    input_parser.add_tv_solver(default="PD")
    input_parser.add_iterations(default=50)
    input_parser.add_rho(default=0.1)
    input_parser.add_iter_max(default=10)
    input_parser.add_minimizer(default="lsmr")
    input_parser.add_alpha(default=0.01)
    input_parser.add_data_loss(default="linear")
    input_parser.add_data_loss_scale(default=1)
    input_parser.add_log_script_execution(default=1)
    input_parser.add_verbose(default=1)

    # Range for parameter sweeps
    input_parser.add_alpha_range(default=[0.001, 0.05, 20])  # TK1L2
    # input_parser.add_alpha_range(default=[0.001, 0.003, 10])  # TVL2, HuberL2
    input_parser.add_data_losses(
        # default=["linear", "arctan"]
    )
    input_parser.add_data_loss_scale_range(
        # default=[0.1, 1.5, 2]
    )

    args = input_parser.parse_args()
    input_parser.print_arguments(args)

    if args.reference is None and args.reconstruction_space is None:
        raise IOError("Either reference (--reference) or reconstruction space "
                      "(--reconstruction-space) must be provided.")

    # Write script execution call
    if args.log_script_execution:
        input_parser.write_performed_script_execution(
            os.path.abspath(__file__))

    # --------------------------------Read Data--------------------------------
    ph.print_title("Read Data")

    # Neither '--dir-input' nor '--filenames' was specified
    if args.filenames is not None and args.dir_input is not None:
        raise IOError(
            "Provide input by either '--dir-input' or '--filenames' "
            "but not both together")

    # '--dir-input' specified
    elif args.dir_input is not None:
        data_reader = dr.ImageSlicesDirectoryReader(
            path_to_directory=args.dir_input,
            suffix_mask=args.suffix_mask,
            image_selection=args.image_selection)

    # '--filenames' specified
    elif args.filenames is not None:
        data_reader = dr.MultipleImagesReader(
            args.filenames, suffix_mask=args.suffix_mask)

    else:
        raise IOError(
            "Provide input by either '--dir-input' or '--filenames'")

    data_reader.read_data()
    stacks = data_reader.get_data()
    ph.print_info("%d input stacks read for further processing" % len(stacks))

    if args.reference is not None:
        reference = st.Stack.from_filename(
            file_path=args.reference,
            file_path_mask=args.reference_mask,
            extract_slices=False)

        reconstruction_space = stacks[0].get_resampled_stack(reference.sitk)
        reconstruction_space = \
            reconstruction_space.get_stack_multiplied_with_mask()
        x_ref = sitk.GetArrayFromImage(reference.sitk).flatten()
        x_ref_mask = sitk.GetArrayFromImage(reference.sitk_mask).flatten()

    else:
        reconstruction_space = st.Stack.from_filename(
            file_path=args.reconstruction_space,
            extract_slices=False)
        reconstruction_space = stacks[0].get_resampled_stack(
            reconstruction_space.sitk)
        reconstruction_space = \
            reconstruction_space.get_stack_multiplied_with_mask()
        x_ref = None
        x_ref_mask = None

    # ----------------------------Set Up Parameters----------------------------
    parameters = {}
    parameters["alpha"] = np.linspace(
        args.alpha_range[0], args.alpha_range[1], int(args.alpha_range[2]))
    if args.data_losses is not None:
        parameters["data_loss"] = args.data_losses
    if args.data_loss_scale_range is not None:
        parameters["data_loss_scale"] = np.linspace(
            args.data_loss_scale_range[0],
            args.data_loss_scale_range[1],
            int(args.data_loss_scale_range[2]))

    # --------------------------Set Up Parameter Study-------------------------
    if args.study_name is None:
        name = args.reconstruction_type
    else:
        name = args.study_name

    reconstruction_info = {
        "shape": reconstruction_space.sitk.GetSize()[::-1],
        "origin": reconstruction_space.sitk.GetOrigin(),
        "spacing": reconstruction_space.sitk.GetSpacing(),
        "direction": reconstruction_space.sitk.GetDirection(),
    }

    # Create Tikhonov solver from which all information can be extracted
    # (also for other reconstruction types)
    tmp = tk.TikhonovSolver(
        stacks=stacks,
        reconstruction=reconstruction_space,
        alpha=args.alpha,
        iter_max=args.iter_max,
        data_loss=args.data_loss,
        data_loss_scale=args.data_loss_scale,
        reg_type="TK1",
        minimizer=args.minimizer,
        verbose=args.verbose,
    )
    solver = tmp.get_solver()

    parameter_study_interface = \
        deconv_interface.DeconvolutionParameterStudyInterface(
            A=solver.get_A(),
            A_adj=solver.get_A_adj(),
            D=solver.get_B(),
            D_adj=solver.get_B_adj(),
            b=solver.get_b(),
            x0=solver.get_x0(),
            alpha=solver.get_alpha(),
            x_scale=solver.get_x_scale(),
            data_loss=solver.get_data_loss(),
            data_loss_scale=solver.get_data_loss_scale(),
            iter_max=solver.get_iter_max(),
            minimizer=solver.get_minimizer(),
            iterations=args.iterations,
            measures=args.measures,
            dimension=3,
            L2=16./reconstruction_space.sitk.GetSpacing()[0]**2,
            reconstruction_type=args.reconstruction_type,
            rho=args.rho,
            dir_output=args.dir_output,
            parameters=parameters,
            name=name,
            reconstruction_info=reconstruction_info,
            x_ref=x_ref,
            x_ref_mask=x_ref_mask,
            tv_solver=args.tv_solver,
            verbose=args.verbose,
        )
    parameter_study_interface.set_up_parameter_study()
    parameter_study = parameter_study_interface.get_parameter_study()

    # Run parameter study
    parameter_study.run()

    print("\nComputational time for Deconvolution Parameter Study %s: %s" %
          (name, parameter_study.get_computational_time()))

    return 0
コード例 #4
0
def main():

    # Read input
    input_parser = InputArgparser(
        description="Script to evaluate the similarity of simulated stack "
        "from obtained reconstruction against the original stack. "
        "This function takes the result of "
        "simulate_stacks_from_reconstruction.py as input.", )
    input_parser.add_filenames(required=True)
    input_parser.add_filenames_masks()
    input_parser.add_dir_output(required=True)
    input_parser.add_suffix_mask(default="_mask")
    input_parser.add_measures(default=["NCC", "SSIM"])
    input_parser.add_option(
        option_string="--prefix-simulated",
        type=str,
        help="Specify the prefix of the simulated stacks to distinguish them "
        "from the original data.",
        default="Simulated_",
    )
    input_parser.add_option(
        option_string="--dir-input-simulated",
        type=str,
        help="Specify the directory where the simulated stacks are. "
        "If not given, it is assumed that they are in the same directory "
        "as the original ones.",
        default=None)
    input_parser.add_slice_thicknesses(default=None)

    args = input_parser.parse_args()
    input_parser.print_arguments(args)

    # --------------------------------Read Data--------------------------------
    ph.print_title("Read Data")

    # Read original data
    filenames_original = args.filenames
    data_reader = dr.MultipleImagesReader(
        file_paths=filenames_original,
        file_paths_masks=args.filenames_masks,
        suffix_mask=args.suffix_mask,
        stacks_slice_thicknesses=args.slice_thicknesses,
    )
    data_reader.read_data()
    stacks_original = data_reader.get_data()

    # Read data simulated from obtained reconstruction
    if args.dir_input_simulated is None:
        dir_input_simulated = os.path.dirname(filenames_original[0])
    else:
        dir_input_simulated = args.dir_input_simulated
    filenames_simulated = [
        os.path.join("%s", "%s%s") %
        (dir_input_simulated, args.prefix_simulated, os.path.basename(f))
        for f in filenames_original
    ]
    data_reader = dr.MultipleImagesReader(filenames_simulated,
                                          suffix_mask=args.suffix_mask)
    data_reader.read_data()
    stacks_simulated = data_reader.get_data()

    for i in range(len(stacks_original)):
        try:
            stacks_original[i].sitk - stacks_simulated[i].sitk
        except:
            raise IOError(
                "Images '%s' and '%s' do not occupy the same space!" %
                (filenames_original[i], filenames_simulated[i]))

    similarity_measures = {
        m: SimilarityMeasures.similarity_measures[m]
        for m in args.measures
    }
    similarities = np.zeros(len(args.measures))

    for i in range(len(stacks_original)):
        nda_3D_original = sitk.GetArrayFromImage(stacks_original[i].sitk)
        nda_3D_simulated = sitk.GetArrayFromImage(stacks_simulated[i].sitk)
        nda_3D_mask = sitk.GetArrayFromImage(stacks_original[i].sitk_mask)

        path_to_file = os.path.join(
            args.dir_output,
            "Similarity_%s.txt" % stacks_original[i].get_filename())
        text = "# Similarity: %s vs %s (%s)." % (os.path.basename(
            filenames_original[i]), os.path.basename(
                filenames_simulated[i]), ph.get_time_stamp())
        text += "\n#\t" + ("\t").join(args.measures)
        text += "\n"
        ph.write_to_file(path_to_file, text, "w")
        for k in range(nda_3D_original.shape[0]):
            x_2D_original = nda_3D_original[k, :, :]
            x_2D_simulated = nda_3D_simulated[k, :, :]

            # zero slice, i.e. rejected during motion correction
            if np.abs(x_2D_simulated).sum() < 1e-6:
                x_2D_simulated[:] = np.nan
            x_2D_mask = nda_3D_mask[k, :, :]

            indices = np.where(x_2D_mask > 0)

            for m, measure in enumerate(args.measures):
                if len(indices[0]) > 0:
                    similarities[m] = similarity_measures[measure](
                        x_2D_original[indices], x_2D_simulated[indices])
                else:
                    similarities[m] = np.nan
            ph.write_array_to_file(path_to_file, similarities.reshape(1, -1))

    return 0
コード例 #5
0
def main():

    time_start = ph.start_timing()

    # Set print options
    np.set_printoptions(precision=3)
    pd.set_option('display.width', 1000)

    input_parser = InputArgparser(description=".", )
    input_parser.add_filenames()
    input_parser.add_filenames_masks()
    input_parser.add_dir_input_mc()
    input_parser.add_suffix_mask(default="_mask")
    input_parser.add_reference(required=True)
    input_parser.add_reference_mask()
    input_parser.add_dir_output(required=False)
    input_parser.add_log_config(default=1)
    input_parser.add_measures(default=["PSNR", "RMSE", "SSIM", "NCC", "NMI"])
    input_parser.add_verbose(default=0)
    input_parser.add_slice_thicknesses(default=None)
    input_parser.add_option(option_string="--use-reference-mask",
                            type=int,
                            default=1)
    input_parser.add_option(option_string="--use-slice-masks",
                            type=int,
                            default=1)

    args = input_parser.parse_args()
    input_parser.print_arguments(args)

    if args.log_config:
        input_parser.log_config(os.path.abspath(__file__))

    # --------------------------------Read Data--------------------------------
    ph.print_title("Read Data")

    data_reader = dr.MultipleImagesReader(
        file_paths=args.filenames,
        file_paths_masks=args.filenames_masks,
        suffix_mask=args.suffix_mask,
        dir_motion_correction=args.dir_input_mc,
        stacks_slice_thicknesses=args.slice_thicknesses,
    )

    data_reader.read_data()
    stacks = data_reader.get_data()
    ph.print_info("%d input stacks read for further processing" % len(stacks))

    reference = st.Stack.from_filename(args.reference, args.reference_mask)

    ph.print_title("Slice Residual Similarity")
    residual_evaluator = res_ev.ResidualEvaluator(
        stacks=stacks,
        reference=reference,
        measures=args.measures,
        use_reference_mask=args.use_reference_mask,
        use_slice_masks=args.use_slice_masks,
    )
    residual_evaluator.compute_slice_projections()
    residual_evaluator.evaluate_slice_similarities()
    residual_evaluator.write_slice_similarities(args.dir_output)

    elapsed_time = ph.stop_timing(time_start)
    ph.print_title("Summary")
    print("Computational Time for Slice Residual Evaluation: %s" %
          (elapsed_time))

    return 0
コード例 #6
0
def main():

    time_start = ph.start_timing()

    # Set print options
    np.set_printoptions(precision=3)
    pd.set_option('display.width', 1000)

    input_parser = InputArgparser(
        description=".",
    )
    input_parser.add_filenames()
    input_parser.add_filenames_masks()
    input_parser.add_dir_input_mc()
    input_parser.add_suffix_mask(default="_mask")
    input_parser.add_reference(required=True)
    input_parser.add_reference_mask()
    input_parser.add_dir_output(required=False)
    input_parser.add_log_config(default=1)
    input_parser.add_measures(
        default=["PSNR", "MAE", "RMSE", "SSIM", "NCC", "NMI"])
    input_parser.add_verbose(default=0)
    input_parser.add_target_stack(default=None)
    input_parser.add_intensity_correction(default=1)
    input_parser.add_slice_thicknesses(default=None)
    input_parser.add_option(
        option_string="--use-reference-mask", type=int, default=1)
    input_parser.add_option(
        option_string="--use-slice-masks", type=int, default=1)

    args = input_parser.parse_args()
    input_parser.print_arguments(args)

    if args.log_config:
        input_parser.log_config(os.path.abspath(__file__))

    # --------------------------------Read Data--------------------------------
    ph.print_title("Read Data")

    data_reader = dr.MultipleImagesReader(
        file_paths=args.filenames,
        file_paths_masks=args.filenames_masks,
        suffix_mask=args.suffix_mask,
        dir_motion_correction=args.dir_input_mc,
        stacks_slice_thicknesses=args.slice_thicknesses,
    )

    data_reader.read_data()
    stacks = data_reader.get_data()
    ph.print_info("%d input stacks read for further processing" % len(stacks))

    # Specify target stack for intensity correction and reconstruction space
    if args.target_stack is None:
        target_stack_index = 0
    else:
        filenames = ["%s.nii.gz" % s.get_filename() for s in stacks]
        filename_target_stack = os.path.basename(args.target_stack)
        try:
            target_stack_index = filenames.index(filename_target_stack)
        except ValueError as e:
            raise ValueError(
                "--target-stack must correspond to an image as provided by "
                "--filenames")

    # ---------------------------Intensity Correction--------------------------
    if args.intensity_correction:
        ph.print_title("Intensity Correction")
        intensity_corrector = ic.IntensityCorrection()
        intensity_corrector.use_individual_slice_correction(False)
        intensity_corrector.use_stack_mask(True)
        intensity_corrector.use_reference_mask(True)
        intensity_corrector.use_verbose(False)

        for i, stack in enumerate(stacks):
            if i == target_stack_index:
                ph.print_info("Stack %d (%s): Reference image. Skipped." % (
                    i + 1, stack.get_filename()))
                continue
            else:
                ph.print_info("Stack %d (%s): Intensity Correction ... " % (
                    i + 1, stack.get_filename()), newline=False)
            intensity_corrector.set_stack(stack)
            intensity_corrector.set_reference(
                stacks[target_stack_index].get_resampled_stack(
                    resampling_grid=stack.sitk,
                    interpolator="NearestNeighbor",
                ))
            intensity_corrector.run_linear_intensity_correction()
            stacks[i] = intensity_corrector.get_intensity_corrected_stack()
            print("done (c1 = %g) " %
                  intensity_corrector.get_intensity_correction_coefficients())

    # ----------------------- Slice Residual Similarity -----------------------
    reference = st.Stack.from_filename(args.reference, args.reference_mask)

    ph.print_title("Slice Residual Similarity")
    residual_evaluator = res_ev.ResidualEvaluator(
        stacks=stacks,
        reference=reference,
        measures=args.measures,
        use_reference_mask=args.use_reference_mask,
        use_slice_masks=args.use_slice_masks,
    )
    residual_evaluator.compute_slice_projections()
    residual_evaluator.evaluate_slice_similarities()
    residual_evaluator.write_slice_similarities(args.dir_output)

    elapsed_time = ph.stop_timing(time_start)
    ph.print_title("Summary")
    print("Computational Time for Slice Residual Evaluation: %s" %
          (elapsed_time))

    return 0