Exemple #1
0
    def from_filename(cls,
                      file_path,
                      slice_number,
                      slice_thickness,
                      file_path_mask=None,
                      verbose=False,
                      ):

        slice = cls()

        if not ph.file_exists(file_path):
            raise exceptions.FileNotExistent(file_path)

        slice._dir_input = os.path.dirname(file_path)
        slice._filename = os.path.basename(file_path).split(".")[0]
        slice._slice_number = slice_number
        slice._slice_thickness = slice_thickness

        # Append stacks as SimpleITK and ITK Image objects
        slice.sitk = sitkh.read_nifti_image_sitk(file_path, sitk.sitkFloat64)
        slice.itk = sitkh.get_itk_from_sitk_image(slice.sitk)

        # Append masks (if provided)
        if file_path_mask is None:
            slice.sitk_mask = slice._generate_identity_mask()
            if verbose:
                ph.print_info(
                    "Identity mask created for '%s'." % (file_path))

        else:
            if not ph.file_exists(file_path_mask):
                raise exceptions.FileNotExistent(file_path_mask)
            slice.sitk_mask = sitkh.read_nifti_image_sitk(
                file_path_mask, sitk.sitkUInt8)
            try:
                # ensure mask occupies the same physical space
                slice.sitk_mask.CopyInformation(slice.sitk)
            except RuntimeError as e:
                raise IOError(
                    "Given image and its mask do not occupy the same space: %s" %
                    e.message)

        slice.itk_mask = sitkh.get_itk_from_sitk_image(slice.sitk_mask)

        # Store current affine transform of image
        slice._affine_transform_sitk = sitkh.get_sitk_affine_transform_from_sitk_image(
            slice.sitk)

        # Prepare history of affine transforms, i.e. encoded spatial
        #  position+orientation of slice, and motion estimates of slice
        #  obtained in the course of the registration/reconstruction process
        slice._history_affine_transforms = []
        slice._history_affine_transforms.append(slice._affine_transform_sitk)

        slice._history_motion_corrections = []
        slice._history_motion_corrections.append(sitk.Euler3DTransform())

        return slice
Exemple #2
0
    def read_transform(path_to_file, inverse=0, nii_as_nib=0, as_itk=0):

        if not ph.file_exists(path_to_file):
            raise IOError("Transform file '%s' not found" % path_to_file)

        extension = ph.strip_filename_extension(path_to_file)[1]
        if extension not in ALLOWED_TRANSFORMS and \
                extension not in ALLOWED_TRANSFORMS_DISPLACEMENTS:
            raise IOError("Transform file extension must be of type "
                          "%s (transformation) or %s (displacements)" %
                          (", ".join(ALLOWED_TRANSFORMS),
                           ", ".join(ALLOWED_TRANSFORMS_DISPLACEMENTS)))

        if extension in ALLOWED_TRANSFORMS:
            if as_itk:
                tranform_sitk = sitk.read_transform_itk(path_to_file,
                                                        inverse=inverse)
            else:
                transform_sitk = sitkh.read_transform_sitk(path_to_file,
                                                           inverse=inverse)
        else:
            # Used for sitk_to_nreg conversion only
            if nii_as_nib:
                displacement_sitk = nib.load(path_to_file)
                return displacement_sitk
            else:
                displacement_sitk = sitk.ReadImage(path_to_file,
                                                   sitk.sitkVectorFloat64)
                transform_sitk = sitk.DisplacementFieldTransform(
                    sitk.Image(displacement_sitk))
                if inverse:
                    # May throw RuntimeError
                    transform_sitk = transform_sitk.GetInverse()

        return transform_sitk
Exemple #3
0
    def read_similarities(self, directory):
        
        if not ph.directory_exists(directory):
            raise IOError("Directory '%s' does not exist." % directory)

        # Get filename paths
        path_to_file_filenames, path_to_file_similarities = self._get_filename_paths(
            directory)

        for f in [path_to_file_filenames, path_to_file_similarities]:
            if not ph.file_exists(path_to_file_filenames):
                raise IOError("File '%s' does not exist" % f)

        lines = ph.read_file_line_by_line(path_to_file_filenames)

        # Get image filenames
        image_names = [re.sub("\n", "", f) for f in lines[2:]]

        # Get computed measures
        measures = lines[1]
        measures = re.sub("# ", "", measures)
        measures = re.sub("\n", "", measures)
        self._measures = measures.split("\t")

        # Get computed similarities
        similarities_nda = np.loadtxt(path_to_file_similarities, skiprows=2)

        # Reconstruct similarity dictionary
        self._similarities = {}
        self._similarities["filenames"] = image_names
        for i_m, m in enumerate(self._measures):
            self._similarities[m] = similarities_nda[:, i_m]
Exemple #4
0
    def read_transform_nreg(path_to_file):

        if not ph.file_exists(path_to_file):
            raise IOError("NiftyReg transform file '%s' not found" %
                          path_to_file)

        extension = ph.strip_filename_extension(path_to_file)[1]
        if extension not in ALLOWED_TRANSFORMS and \
                extension not in ALLOWED_TRANSFORMS_DISPLACEMENTS:
            raise IOError("NiftyReg transform file extension must be of type "
                          "%s (reg_aladin) or %s (reg_f3d displacement)" %
                          (", ".join(ALLOWED_TRANSFORMS),
                           ", ".join(ALLOWED_TRANSFORMS_DISPLACEMENTS)))
        if extension in ALLOWED_TRANSFORMS:
            transform_nreg = np.loadtxt(path_to_file)
        else:
            transform_nreg = nib.load(path_to_file)

            # check that image is a NiftyReg displacement field
            header = transform_nreg.get_header()
            if int(header['intent_p1']) != 1 or \
                    int(header['intent_p2']) != 0 or \
                    int(header['intent_p3']) != 0 or \
                    int(header['intent_code']) != 1007:
                raise IOError("Provided image must represent a NiftyReg "
                              "displacement field")

        return transform_nreg
Exemple #5
0
    def from_filename(cls,
                      file_path,
                      slice_number,
                      file_path_mask=None,
                      verbose=False):

        slice = cls()

        if not ph.file_exists(file_path):
            raise exceptions.FileNotExistent(file_path)

        slice._dir_input = os.path.dirname(file_path)
        slice._filename = os.path.basename(file_path).split(".")[0]
        slice._slice_number = slice_number

        # Append stacks as SimpleITK and ITK Image objects
        slice.sitk = sitk.ReadImage(file_path, sitk.sitkFloat64)
        slice.itk = sitkh.get_itk_from_sitk_image(slice.sitk)

        # Append masks (if provided)
        if file_path_mask is None:
            slice.sitk_mask = slice._generate_identity_mask()
            if verbose:
                ph.print_info("Identity mask created for '%s'." % (file_path))

        else:
            if not ph.file_exists(file_path_mask):
                raise exceptions.FileNotExistent(file_path_mask)
            slice.sitk_mask = sitk.ReadImage(file_path_mask, sitk.sitkUInt8)

        slice.itk_mask = sitkh.get_itk_from_sitk_image(slice.sitk_mask)

        # Store current affine transform of image
        slice._affine_transform_sitk = sitkh.get_sitk_affine_transform_from_sitk_image(
            slice.sitk)

        # Prepare history of affine transforms, i.e. encoded spatial
        #  position+orientation of slice, and motion estimates of slice
        #  obtained in the course of the registration/reconstruction process
        slice._history_affine_transforms = []
        slice._history_affine_transforms.append(slice._affine_transform_sitk)

        slice._history_motion_corrections = []
        slice._history_motion_corrections.append(sitk.Euler3DTransform())

        return slice
Exemple #6
0
    def read_landmarks(path_to_file):

        if not ph.file_exists(path_to_file):
            raise IOError("Landmark file '%s' not found" % path_to_file)

        extension = ph.strip_filename_extension(path_to_file)[1]
        if extension not in ALLOWED_LANDMARKS:
            raise IOError("Landmark file extension must be of type %s " %
                          ", or ".join(ALLOWED_LANDMARKS))

        return np.loadtxt(path_to_file)
Exemple #7
0
    def read_transform_flirt(path_to_file):

        if not ph.file_exists(path_to_file):
            raise IOError("FLIRT transform file '%s' not found" % path_to_file)

        extension = ph.strip_filename_extension(path_to_file)[1]
        if extension not in ALLOWED_TRANSFORMS:
            raise IOError("FLIRT transform file extension must be of type %s" %
                          ", or ".join(ALLOWED_TRANSFORMS))

        return np.loadtxt(path_to_file)
Exemple #8
0
    def read_landmarks(path_to_file):

        if not ph.file_exists(path_to_file):
            raise IOError("Landmark file '%s' not found" % path_to_file)

        extension = ph.strip_filename_extension(path_to_file)[1]
        if extension not in ALLOWED_LANDMARKS:
            raise IOError("Landmark file extension must be of type %s " %
                          ", or ".join(ALLOWED_LANDMARKS))

        nda = np.loadtxt(path_to_file)

        if nda.shape[1] not in [2, 3]:
            raise IOError("Landmark array file must be of shape N x dim, "
                          "with dim either 2 or 3.")

        return nda
Exemple #9
0
    def read_image(path_to_file, as_itk=0):

        if not ph.file_exists(path_to_file):
            raise IOError("Image file '%s' not found" % path_to_file)

        extension = ph.strip_filename_extension(path_to_file)[1]
        if extension not in ALLOWED_IMAGES:
            raise IOError("Image file extension must be of type %s " %
                          ", or ".join(ALLOWED_IMAGES))

        # Read as itk.Image object
        if as_itk:
            image = itk.imread(path_to_file)

        # Read as sitk.Image object
        else:
            image = sitk.ReadImage(path_to_file)

        return image
def main():
    time_start = ph.start_timing()

    np.set_printoptions(precision=3)

    input_parser = InputArgparser(
        description="Perform automatic brain masking using "
        "fetal_brain_seg, part of the MONAIfbs package "
        "(https://github.com/gift-surg/MONAIfbs). ",
    )
    input_parser.add_filenames(required=True)
    input_parser.add_filenames_masks(required=False)
    input_parser.add_dir_output(required=False)
    input_parser.add_verbose(default=0)
    input_parser.add_log_config(default=0)
    input_parser.add_option(
        option_string="--neuroimage-legacy-seg",
        type=int,
        required=False,
        default=0,
        help="If set to 1, use the legacy method for fetal brain segmentation "
             "i.e. the two-step approach proposed in Ebner, Wang et al "
             "NeuroImage (2020)"
    )

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

    if args.neuroimage_legacy_seg:
        try:
            DIR_FETAL_BRAIN_SEG = os.environ["FETAL_BRAIN_SEG"]
        except KeyError as e:
            raise RuntimeError(
                "Environment variable FETAL_BRAIN_SEG is not specified. "
                "Specify the root directory of fetal_brain_seg "
                "(https://github.com/gift-surg/fetal_brain_seg) "
                "using "
                "'export FETAL_BRAIN_SEG=path_to_fetal_brain_seg_dir' "
                "(in bashrc).")
    else:
        try:
            import monaifbs
            DIR_FETAL_BRAIN_SEG = os.path.dirname(monaifbs.__file__)
        except ImportError as e:
            raise RuntimeError(
                "monaifbs not correctly installed. "
                "Please check its installation running "
                "pip install -e MONAIfbs/ "
            )

    print("Using executable from {}".format(DIR_FETAL_BRAIN_SEG))

    if args.filenames_masks is None and args.dir_output is None:
        raise IOError("Either --filenames-masks or --dir-output must be set")

    if args.dir_output is not None:
        args.filenames_masks = [
            os.path.join(args.dir_output, os.path.basename(f))
            for f in args.filenames
        ]

    if len(args.filenames) != len(args.filenames_masks):
        raise IOError("Number of filenames and filenames-masks must match")

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

    cd_fetal_brain_seg = "cd %s" % DIR_FETAL_BRAIN_SEG

    for f, m in zip(args.filenames, args.filenames_masks):

        if not ph.file_exists(f):
            raise IOError("File '%s' does not exist" % f)

        # use absolute path for input image
        f = os.path.abspath(f)

        # use absolute path for output image
        dir_output = os.path.dirname(m)
        if not os.path.isabs(dir_output):
            dir_output = os.path.realpath(
                os.path.join(os.getcwd(), dir_output))
            m = os.path.join(dir_output, os.path.basename(m))

        ph.create_directory(dir_output)

        # Change to root directory of fetal_brain_seg
        cmds = [cd_fetal_brain_seg]

        # Run masking independently (Takes longer but ensures that it does
        # not terminate because of provided 'non-brain images')
        cmd_args = ["python fetal_brain_seg.py"]
        cmd_args.append("--input_names '%s'" % f)
        cmd_args.append("--segment_output_names '%s'" % m)
        cmds.append(" ".join(cmd_args))

        # Execute both steps
        cmd = " && ".join(cmds)
        flag = ph.execute_command(cmd)

        if flag != 0:
            ph.print_warning(
                "Error using fetal_brain_seg. \n"
                "Execute '%s' for further investigation" %
                cmd)

        ph.print_info("Fetal brain segmentation written to '%s'" % m)

        if args.verbose:
            ph.show_nifti(f, segmentation=m)

    elapsed_time_total = ph.stop_timing(time_start)

    ph.print_title("Summary")
    exe_file_info = os.path.basename(os.path.abspath(__file__)).split(".")[0]
    print("%s | Computational Time: %s" % (exe_file_info, elapsed_time_total))

    return 0
    def run(self):
        if not ph.directory_exists(self._dir_motion_correction):
            raise exceptions.DirectoryNotExistent(self._dir_motion_correction)
        abs_path_to_directory = os.path.abspath(self._dir_motion_correction)

        for i in range(len(self._stacks)):
            stack_name = self._stacks[i].get_filename()

            # update stack position
            path_to_stack_transform = os.path.join(abs_path_to_directory,
                                                   "%s.tfm" % stack_name)
            if ph.file_exists(path_to_stack_transform):
                transform_stack_sitk = sitkh.read_transform_sitk(
                    path_to_stack_transform)
                transform_stack_sitk_inv = sitkh.read_transform_sitk(
                    path_to_stack_transform, inverse=True)
                self._stacks[i].update_motion_correction(transform_stack_sitk)
                ph.print_info("Stack '%s': Stack position updated" %
                              stack_name)
            else:
                transform_stack_sitk_inv = sitk.Euler3DTransform()

            # update slice positions
            pattern_trafo_slices = stack_name + self._prefix_slice + \
                "([0-9]+)[.]tfm"
            p = re.compile(pattern_trafo_slices)
            dic_slice_transforms = {
                int(p.match(f).group(1)): os.path.join(abs_path_to_directory,
                                                       p.match(f).group(0))
                for f in os.listdir(abs_path_to_directory) if p.match(f)
            }
            slices = self._stacks[i].get_slices()
            for i_slice in range(self._stacks[i].get_number_of_slices()):
                if i_slice in dic_slice_transforms.keys():
                    transform_slice_sitk = sitkh.read_transform_sitk(
                        dic_slice_transforms[i_slice])
                    transform_slice_sitk = \
                        sitkh.get_composite_sitk_affine_transform(
                            transform_slice_sitk, transform_stack_sitk_inv)
                    slices[i_slice].update_motion_correction(
                        transform_slice_sitk)

                    # # ------------------------- HACK -------------------------
                    # # 18 Jan 2019
                    # # HACK to use results of a previous version where image
                    # # slices were still exported
                    # # (Bug was that after stack intensity correction, the
                    # # previous v2v-reg was not passed on to the final
                    # # registration transform):
                    # import niftymic.base.slice as sl
                    # path_to_slice = re.sub(
                    #     ".tfm", ".nii.gz", dic_slice_transforms[i_slice])
                    # path_to_slice_mask = re.sub(
                    #     ".tfm", "_mask.nii.gz", dic_slice_transforms[i_slice])
                    # slice_sitk = sitk.ReadImage(path_to_slice)
                    # slice_sitk_mask = sitk.ReadImage(path_to_slice_mask)
                    # hack = sl.Slice.from_sitk_image(
                    #     # slice_sitk=slice_sitk,
                    #     slice_sitk=slice_sitk_mask,  # mask for Mask-SRR!
                    #     slice_sitk_mask=slice_sitk_mask,
                    #     slice_number=slices[i_slice].get_slice_number(),
                    #     slice_thickness=slices[i_slice].get_slice_thickness(),
                    # )
                    # self._stacks[i]._slices[i_slice] = hack
                    # # --------------------------------------------------------

                else:
                    self._stacks[i].delete_slice(slices[i_slice])

            # print update information
            ph.print_info("Stack '%s': Slice positions updated "
                          "(%d/%d slices deleted)" % (
                              stack_name,
                              len(self._stacks[i].get_deleted_slice_numbers()),
                              self._stacks[i].sitk.GetSize()[-1],
                          ))

            # delete entire stack if all slices were rejected
            if self._stacks[i].get_number_of_slices() == 0:
                ph.print_info("Stack '%s' removed as all slices were deleted" %
                              stack_name)
                self._stacks[i] = None

        # only return maintained stacks
        self._stacks = [s for s in self._stacks if s is not None]

        if len(self._stacks) == 0:
            raise RuntimeError(
                "All stacks removed. "
                "Did you check that the correct motion-correction directory "
                "was provided?")
Exemple #12
0
    def from_filename(cls,
                      file_path,
                      file_path_mask=None,
                      extract_slices=True,
                      verbose=False):

        stack = cls()

        if not ph.file_exists(file_path):
            raise exceptions.FileNotExistent(file_path)

            path_to_directory = os.path.dirname(file_path)

        # Strip extension from filename and remove potentially included "."
        filename = [re.sub("." + ext, "", os.path.basename(file_path))
                    for ext in ALLOWED_EXTENSIONS
                    if file_path.endswith(ext)][0]
        # filename = filename.replace(".", "p")

        stack._dir = os.path.dirname(file_path)
        stack._filename = filename

        # Append stacks as SimpleITK and ITK Image objects
        stack.sitk = sitk.ReadImage(file_path, sitk.sitkFloat64)
        stack.itk = sitkh.get_itk_from_sitk_image(stack.sitk)

        # Append masks (either provided or binary mask)
        if file_path_mask is None:
            stack.sitk_mask = stack._generate_identity_mask()
            if verbose:
                ph.print_info(
                    "Identity mask created for '%s'." % (file_path))

        else:
            if not ph.file_exists(file_path_mask):
                raise exceptions.FileNotExistent(file_path_mask)
            stack.sitk_mask = sitk.ReadImage(file_path_mask, sitk.sitkUInt8)
            stack._is_unity_mask = False

        # Append itk object
        stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask)

        # Extract all slices and their masks from the stack and store them
        if extract_slices:
            dimenson = stack.sitk.GetDimension()
            if dimenson == 3:
                stack._N_slices = stack.sitk.GetSize()[-1]
                stack._slices = stack._extract_slices()
            elif dimenson == 2:
                stack._N_slices = 1
                stack._slices = [stack.sitk[:, :]]
        else:
            stack._N_slices = 0
            stack._slices = None

        if verbose:
            ph.print_info(
                "Stack (image + mask) associated to '%s' successfully read." %
                (file_path))

        return stack
    def run(self, older_than_v3=False):
        if not ph.directory_exists(self._dir_motion_correction):
            raise exceptions.DirectoryNotExistent(
                self._dir_motion_correction)
        abs_path_to_directory = os.path.abspath(
            self._dir_motion_correction)

        path_to_rejected_slices = os.path.join(
            abs_path_to_directory, "rejected_slices.json")
        if ph.file_exists(path_to_rejected_slices):
            self._rejected_slices = ph.read_dictionary_from_json(
                path_to_rejected_slices)
            bool_check = True
        else:
            self._rejected_slices = None
            bool_check = False

        for i in range(len(self._stacks)):
            stack_name = self._stacks[i].get_filename()

            if not older_than_v3:
                # update stack position
                path_to_stack_transform = os.path.join(
                    abs_path_to_directory, "%s.tfm" % stack_name)
                if ph.file_exists(path_to_stack_transform):
                    transform_stack_sitk = sitkh.read_transform_sitk(
                        path_to_stack_transform)
                    transform_stack_sitk_inv = sitkh.read_transform_sitk(
                        path_to_stack_transform, inverse=True)
                    self._stacks[i].update_motion_correction(
                        transform_stack_sitk)
                    ph.print_info(
                        "Stack '%s': Stack position updated" % stack_name)
                else:
                    transform_stack_sitk_inv = sitk.Euler3DTransform()

                if self._volume_motion_only:
                    continue

                # update slice positions
                pattern_trafo_slices = stack_name + self._prefix_slice + \
                    "([0-9]+)[.]tfm"
                p = re.compile(pattern_trafo_slices)
                dic_slice_transforms = {
                    int(p.match(f).group(1)): os.path.join(
                        abs_path_to_directory, p.match(f).group(0))
                    for f in os.listdir(abs_path_to_directory) if p.match(f)
                }
                slices = self._stacks[i].get_slices()
                for i_slice in range(self._stacks[i].get_number_of_slices()):
                    if i_slice in dic_slice_transforms.keys():
                        transform_slice_sitk = sitkh.read_transform_sitk(
                            dic_slice_transforms[i_slice])
                        transform_slice_sitk = \
                            sitkh.get_composite_sitk_affine_transform(
                                transform_slice_sitk, transform_stack_sitk_inv)
                        slices[i_slice].update_motion_correction(
                            transform_slice_sitk)

                    else:
                        self._stacks[i].delete_slice(slices[i_slice])

            # ----------------------------- HACK -----------------------------
            # 18 Jan 2019
            # HACK to use results of a previous version where image slices were
            # still exported.
            # (There was a bug after stack intensity correction, which resulted
            # in v2v-reg transforms not being part of in the final registration
            # transforms; Thus, slice transformations (tfm's) were flawed and
            # could not be used):
            else:
                # Recover suffix for mask
                pattern = stack_name + self._prefix_slice + \
                    "[0-9]+[_]([a-zA-Z]+)[.]nii.gz"
                pm = re.compile(pattern)
                matches = list(set([pm.match(f).group(1) for f in os.listdir(
                    abs_path_to_directory) if pm.match(f)]))
                if len(matches) > 1:
                    raise RuntimeError("Suffix mask cannot be determined")
                suffix_mask = "_%s" % matches[0]

                # Recover stack
                path_to_stack = os.path.join(
                    abs_path_to_directory, "%s.nii.gz" % stack_name)
                path_to_stack_mask = os.path.join(
                    abs_path_to_directory, "%s%s.nii.gz" % (
                        stack_name, suffix_mask))
                stack = st.Stack.from_filename(
                    path_to_stack, path_to_stack_mask)

                # Recover slices
                pattern_trafo_slices = stack_name + self._prefix_slice + \
                    "([0-9]+)[.]tfm"
                p = re.compile(pattern_trafo_slices)
                dic_slice_transforms = {
                    int(p.match(f).group(1)): os.path.join(
                        abs_path_to_directory, p.match(f).group(0))
                    for f in os.listdir(abs_path_to_directory) if p.match(f)
                }
                slices = self._stacks[i].get_slices()
                for i_slice in range(self._stacks[i].get_number_of_slices()):
                    if i_slice in dic_slice_transforms.keys():
                        path_to_slice = re.sub(
                            ".tfm", ".nii.gz", dic_slice_transforms[i_slice])
                        path_to_slice_mask = re.sub(
                            ".tfm", "%s.nii.gz" % suffix_mask,
                            dic_slice_transforms[i_slice])
                        slice_sitk = sitk.ReadImage(path_to_slice)
                        slice_sitk_mask = sitk.ReadImage(path_to_slice_mask)
                        hack = sl.Slice.from_sitk_image(
                            slice_sitk=slice_sitk,
                            # slice_sitk=slice_sitk_mask,  # mask for Mask-SRR!
                            slice_sitk_mask=slice_sitk_mask,
                            slice_number=slices[i_slice].get_slice_number(),
                            slice_thickness=slices[
                                i_slice].get_slice_thickness(),
                        )
                        self._stacks[i]._slices[i_slice] = hack
                    else:
                        self._stacks[i].delete_slice(slices[i_slice])

                self._stacks[i].sitk = stack.sitk
                self._stacks[i].sitk_mask = stack.sitk_mask
                self._stacks[i].itk = stack.itk
                self._stacks[i].itk_mask = stack.itk_mask
            # -----------------------------------------------------------------

            # print update information
            ph.print_info(
                "Stack '%s': Slice positions updated "
                "(%d/%d slices deleted)" % (
                    stack_name,
                    len(self._stacks[i].get_deleted_slice_numbers()),
                    self._stacks[i].sitk.GetSize()[-1],
                )
            )

            # delete entire stack if all slices were rejected
            if self._stacks[i].get_number_of_slices() == 0:
                ph.print_info(
                    "Stack '%s' removed as all slices were deleted" %
                    stack_name)
                self._stacks[i] = None

        # only return maintained stacks
        self._stacks = [s for s in self._stacks if s is not None]

        if len(self._stacks) == 0:
            raise RuntimeError(
                "All stacks removed. "
                "Did you check that the correct motion-correction directory "
                "was provided?")
Exemple #14
0
    def from_filename(
        cls,
        file_path,
        file_path_mask=None,
        extract_slices=True,
        verbose=False,
        slice_thickness=None,
    ):

        stack = cls()

        if not ph.file_exists(file_path):
            raise exceptions.FileNotExistent(file_path)

            path_to_directory = os.path.dirname(file_path)

        # Strip extension from filename and remove potentially included "."
        filename = [
            re.sub("." + ext, "", os.path.basename(file_path))
            for ext in ALLOWED_EXTENSIONS if file_path.endswith(ext)
        ][0]
        # filename = filename.replace(".", "p")

        stack._dir = os.path.dirname(file_path)
        stack._filename = filename

        # Append stacks as SimpleITK and ITK Image objects
        stack.sitk = sitkh.read_nifti_image_sitk(file_path, sitk.sitkFloat64)
        stack.itk = sitkh.get_itk_from_sitk_image(stack.sitk)

        # Set slice thickness of acquisition
        if slice_thickness is None:
            stack._slice_thickness = stack.sitk.GetSpacing()[-1]
        else:
            stack._slice_thickness = slice_thickness

        # Append masks (either provided or binary mask)
        if file_path_mask is None:
            stack.sitk_mask = stack._generate_identity_mask()
            if verbose:
                ph.print_info("Identity mask created for '%s'." % (file_path))

        else:
            if not ph.file_exists(file_path_mask):
                raise exceptions.FileNotExistent(file_path_mask)
            stack.sitk_mask = sitkh.read_nifti_image_sitk(
                file_path_mask, sitk.sitkUInt8)
            try:
                # ensure masks occupy same physical space
                stack.sitk_mask.CopyInformation(stack.sitk)
            except RuntimeError as e:
                raise IOError(
                    "Given image and its mask do not occupy the same space: %s"
                    % e.message)
            stack._is_unity_mask = False

        # Append itk object
        stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask)

        # Store current affine transform of image
        stack._affine_transform_sitk = sitkh.get_sitk_affine_transform_from_sitk_image(
            stack.sitk)

        # Prepare history of affine transforms, i.e. encoded spatial
        #  position+orientation of stack, and motion estimates of stack
        #  obtained in the course of the registration/reconstruction process
        stack._history_affine_transforms = []
        stack._history_affine_transforms.append(stack._affine_transform_sitk)

        stack._history_motion_corrections = []
        stack._history_motion_corrections.append(sitk.Euler3DTransform())

        # Extract all slices and their masks from the stack and store them
        if extract_slices:
            dimenson = stack.sitk.GetDimension()
            if dimenson == 3:
                stack._N_slices = stack.sitk.GetSize()[-1]
                stack._slices = stack._extract_slices(
                    slice_thickness=stack.get_slice_thickness())
            elif dimenson == 2:
                stack._N_slices = 1
                stack._slices = [stack.sitk[:, :]]
        else:
            stack._N_slices = 0
            stack._slices = None

        if verbose:
            ph.print_info(
                "Stack (image + mask) associated to '%s' successfully read." %
                (file_path))

        return stack
Exemple #15
0
    def from_slice_filenames(
        cls,
        dir_input,
        prefix_stack,
        suffix_mask=None,
        dic_slice_filenames=None,
        prefix_slice="_slice",
        slice_thickness=None,
    ):

        stack = cls()

        if dir_input[-1] is not "/":
            dir_input += "/"

        stack._dir = dir_input
        stack._filename = prefix_stack

        # Get 3D images
        stack.sitk = sitkh.read_nifti_image_sitk(
            dir_input + prefix_stack + ".nii.gz", sitk.sitkFloat64)
        stack.itk = sitkh.get_itk_from_sitk_image(stack.sitk)

        # Store current affine transform of image
        stack._affine_transform_sitk = sitkh.get_sitk_affine_transform_from_sitk_image(
            stack.sitk)

        # Prepare history of affine transforms, i.e. encoded spatial
        #  position+orientation of stack, and motion estimates of stack
        #  obtained in the course of the registration/reconstruction process
        stack._history_affine_transforms = []
        stack._history_affine_transforms.append(stack._affine_transform_sitk)

        stack._history_motion_corrections = []
        stack._history_motion_corrections.append(sitk.Euler3DTransform())

        # Set slice thickness of acquisition
        if slice_thickness is None:
            stack._slice_thickness = float(stack.sitk.GetSpacing()[-1])
        else:
            stack._slice_thickness = float(slice_thickness)

        # Append masks (either provided or binary mask)
        if suffix_mask is not None and \
            os.path.isfile(dir_input +
                           prefix_stack + suffix_mask + ".nii.gz"):
            stack.sitk_mask = sitkh.read_nifti_image_sitk(
                dir_input + prefix_stack + suffix_mask + ".nii.gz",
                sitk.sitkUInt8)
            stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask)
            stack._is_unity_mask = False
        else:
            stack.sitk_mask = stack._generate_identity_mask()
            stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask)
            stack._is_unity_mask = True

        # Get slices
        if dic_slice_filenames is None:
            stack._N_slices = stack.sitk.GetDepth()
            stack._slices = [None] * stack._N_slices

            # Append slices as Slice objects
            for i in range(0, stack._N_slices):
                path_to_slice = os.path.join(
                    dir_input,
                    prefix_stack + prefix_slice + str(i) + ".nii.gz")
                path_to_slice_mask = os.path.join(
                    dir_input, prefix_stack + prefix_slice + str(i) +
                    suffix_mask + ".nii.gz")

                if ph.file_exists(path_to_slice_mask):
                    stack._slices[i] = sl.Slice.from_filename(
                        file_path=path_to_slice,
                        slice_number=i,
                        file_path_mask=path_to_slice_mask)
                else:
                    stack._slices[i] = sl.Slice.from_filename(
                        file_path=path_to_slice, slice_number=i)
        else:
            slice_numbers = sorted(dic_slice_filenames.keys())
            stack._N_slices = len(slice_numbers)
            stack._slices = [None] * stack._N_slices

            for i, slice_number in enumerate(slice_numbers):
                path_to_slice = os.path.join(
                    dir_input, dic_slice_filenames[slice_number] + ".nii.gz")
                path_to_slice_mask = os.path.join(
                    dir_input, dic_slice_filenames[slice_number] +
                    suffix_mask + ".nii.gz")

                if ph.file_exists(path_to_slice_mask):
                    stack._slices[i] = sl.Slice.from_filename(
                        file_path=path_to_slice,
                        slice_number=slice_number,
                        file_path_mask=path_to_slice_mask,
                        slice_thickness=stack.get_slice_thickness(),
                    )
                else:
                    stack._slices[i] = sl.Slice.from_filename(
                        file_path=path_to_slice,
                        slice_number=slice_number,
                        slice_thickness=stack.get_slice_thickness(),
                    )

        return stack
def main():
    time_start = ph.start_timing()

    np.set_printoptions(precision=3)

    input_parser = InputArgparser(
        description="Perform automatic brain masking using "
        "fetal_brain_seg (https://github.com/gift-surg/fetal_brain_seg). ", )
    input_parser.add_filenames(required=True)
    input_parser.add_filenames_masks(required=False)
    input_parser.add_dir_output(required=False)
    input_parser.add_verbose(default=0)
    input_parser.add_log_config(default=0)

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

    try:
        DIR_FETAL_BRAIN_SEG = os.environ["FETAL_BRAIN_SEG"]
    except KeyError as e:
        raise RuntimeError(
            "Environment variable FETAL_BRAIN_SEG is not specified. "
            "Specify the root directory of fetal_brain_seg "
            "(https://github.com/gift-surg/fetal_brain_seg) "
            "using "
            "'export FETAL_BRAIN_SEG=path_to_fetal_brain_seg_dir' "
            "(in bashrc).")

    if args.filenames_masks is None and args.dir_output is None:
        raise IOError("Either --filenames-masks or --dir-output must be set")

    if args.dir_output is not None:
        args.filenames_masks = [
            os.path.join(args.dir_output, os.path.basename(f))
            for f in args.filenames
        ]

    if len(args.filenames) != len(args.filenames_masks):
        raise IOError("Number of filenames and filenames-masks must match")

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

    cd_fetal_brain_seg = "cd %s" % DIR_FETAL_BRAIN_SEG

    for f, m in zip(args.filenames, args.filenames_masks):

        if not ph.file_exists(f):
            raise IOError("File '%s' does not exist" % f)

        # use absolute path for input image
        f = os.path.abspath(f)

        # use absolute path for output image
        dir_output = os.path.dirname(m)
        if not os.path.isabs(dir_output):
            dir_output = os.path.realpath(os.path.join(os.getcwd(),
                                                       dir_output))
            m = os.path.join(dir_output, os.path.basename(m))

        ph.create_directory(dir_output)

        # Change to root directory of fetal_brain_seg
        cmds = [cd_fetal_brain_seg]

        # Run masking independently (Takes longer but ensures that it does
        # not terminate because of provided 'non-brain images')
        cmd_args = ["python fetal_brain_seg.py"]
        cmd_args.append("--input_names '%s'" % f)
        cmd_args.append("--segment_output_names '%s'" % m)
        cmds.append(" ".join(cmd_args))

        # Execute both steps
        cmd = " && ".join(cmds)
        flag = ph.execute_command(cmd)

        if flag != 0:
            ph.print_warning("Error using fetal_brain_seg. \n"
                             "Execute '%s' for further investigation" % cmd)

        ph.print_info("Fetal brain segmentation written to '%s'" % m)

        if args.verbose:
            ph.show_nifti(f, segmentation=m)

    return 0
Exemple #17
0
    def from_slice_filenames(
        cls,
        dir_input,
        prefix_stack,
        suffix_mask=None,
        dic_slice_filenames=None,
        prefix_slice="_slice",
        slice_thickness=None,
    ):

        stack = cls()

        if dir_input[-1] is not "/":
            dir_input += "/"

        stack._dir = dir_input
        stack._filename = prefix_stack

        # Get 3D images
        stack.sitk = sitkh.read_nifti_image_sitk(
            dir_input + prefix_stack + ".nii.gz", sitk.sitkFloat64)
        stack.itk = sitkh.get_itk_from_sitk_image(stack.sitk)

        # Set slice thickness of acquisition
        if slice_thickness is None:
            stack._slice_thickness = stack.sitk.GetSpacing()[-1]
        else:
            stack._slice_thickness = slice_thickness

        # Append masks (either provided or binary mask)
        if suffix_mask is not None and \
            os.path.isfile(dir_input +
                           prefix_stack + suffix_mask + ".nii.gz"):
            stack.sitk_mask = sitkh.read_nifti_image_sitk(
                dir_input + prefix_stack + suffix_mask + ".nii.gz",
                sitk.sitkUInt8)
            stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask)
            stack._is_unity_mask = False
        else:
            stack.sitk_mask = stack._generate_identity_mask()
            stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask)
            stack._is_unity_mask = True

        # Get slices
        if dic_slice_filenames is None:
            stack._N_slices = stack.sitk.GetDepth()
            stack._slices = [None] * stack._N_slices

            # Append slices as Slice objects
            for i in range(0, stack._N_slices):
                path_to_slice = os.path.join(
                    dir_input,
                    prefix_stack + prefix_slice + str(i) + ".nii.gz")
                path_to_slice_mask = os.path.join(
                    dir_input, prefix_stack + prefix_slice + str(i) +
                    suffix_mask + ".nii.gz")

                if ph.file_exists(path_to_slice_mask):
                    stack._slices[i] = sl.Slice.from_filename(
                        file_path=path_to_slice,
                        slice_number=i,
                        file_path_mask=path_to_slice_mask)
                else:
                    stack._slices[i] = sl.Slice.from_filename(
                        file_path=path_to_slice, slice_number=i)
        else:
            slice_numbers = sorted(dic_slice_filenames.keys())
            stack._N_slices = len(slice_numbers)
            stack._slices = [None] * stack._N_slices

            for i, slice_number in enumerate(slice_numbers):
                path_to_slice = os.path.join(
                    dir_input, dic_slice_filenames[slice_number] + ".nii.gz")
                path_to_slice_mask = os.path.join(
                    dir_input, dic_slice_filenames[slice_number] +
                    suffix_mask + ".nii.gz")

                if ph.file_exists(path_to_slice_mask):
                    stack._slices[i] = sl.Slice.from_filename(
                        file_path=path_to_slice,
                        slice_number=slice_number,
                        file_path_mask=path_to_slice_mask,
                        slice_thickness=stack.get_slice_thickness(),
                    )
                else:
                    stack._slices[i] = sl.Slice.from_filename(
                        file_path=path_to_slice,
                        slice_number=slice_number,
                        slice_thickness=stack.get_slice_thickness(),
                    )

        return stack
Exemple #18
0
def main():

    time_start = ph.start_timing()

    flag_individual_cases_only = 1

    flag_batch_script = 0
    batch_ctr = [32]

    flag_correct_bias_field = 0
    # flag_correct_intensities = 0

    flag_collect_segmentations = 0
    flag_select_images_segmentations = 0

    flag_reconstruct_volume_subject_space = 0
    flag_reconstruct_volume_subject_space_irtk = 0
    flag_reconstruct_volume_subject_space_show_comparison = 0
    flag_register_to_template = 0
    flag_register_to_template_irtk = 0
    flag_show_srr_template_space = 0
    flag_reconstruct_volume_template_space = 0
    flag_collect_volumetric_reconstruction_results = 0
    flag_show_volumetric_reconstruction_results = 0

    flag_rsync_stuff = 0

    # Analysis
    flag_remove_failed_cases_for_analysis = 1
    flag_postop = 2  # 0... preop, 1...postop, 2... pre+postop

    flag_evaluate_image_similarities = 0
    flag_analyse_image_similarities = 1

    flag_evaluate_slice_residual_similarities = 0
    flag_analyse_slice_residual_similarities = 0

    flag_analyse_stacks = 0
    flag_analyse_qualitative_assessment = 0

    flag_collect_data_blinded_analysis = 0
    flag_anonymize_data_blinded_analysis = 0

    provide_comparison = 0
    intensity_correction = 1
    isotropic_resolution = 0.75
    alpha = 0.02
    outlier_rejection = 1
    threshold = 0.7
    threshold_first = 0.6

    # metric = "ANTSNeighborhoodCorrelation"
    # metric_radius = 5
    # multiresolution = 0

    prefix_srr = "srr_"
    prefix_srr_qa = "masked_"

    # ----------------------------------Set Up---------------------------------
    if flag_correct_bias_field:
        dir_batch = os.path.join(utils.DIR_BATCH_ROOT, "BiasFieldCorrection")
    elif flag_reconstruct_volume_subject_space:
        dir_batch = os.path.join(utils.DIR_BATCH_ROOT,
                                 "VolumetricReconstructionSubjectSpace")
    elif flag_register_to_template:
        dir_batch = os.path.join(utils.DIR_BATCH_ROOT,
                                 "VolumetricReconstructionRegisterToTemplate")
    elif flag_reconstruct_volume_template_space:
        dir_batch = os.path.join(utils.DIR_BATCH_ROOT,
                                 "VolumetricReconstructionTemplateSpace")
    else:
        dir_batch = os.path.join(utils.DIR_BATCH_ROOT, "foo")
    file_prefix_batch = os.path.join(dir_batch, "command")

    if flag_batch_script:
        verbose = 0
    else:
        verbose = 1

    data_reader = dr.ExcelSheetDataReader(utils.EXCEL_FILE)
    data_reader.read_data()
    cases = data_reader.get_data()

    if flag_analyse_qualitative_assessment:
        data_reader = dr.ExcelSheetQualitativeAssessmentReader(utils.QA_FILE)
        data_reader.read_data()
        qualitative_assessment = data_reader.get_data()

        statistical_evaluation = se.StatisticalEvaluation(
            qualitative_assessment)
        statistical_evaluation.run_tests(ref="seg_manual")
        ph.exit()

    cases_similarities = []
    cases_stacks = []

    if flag_individual_cases_only:
        N_cases = len(INDIVIDUAL_CASE_IDS)
    else:
        N_cases = len(cases.keys())

    i_case = 0
    for case_id in sorted(cases.keys()):
        if flag_individual_cases_only and case_id not in INDIVIDUAL_CASE_IDS:
            continue
        if not flag_analyse_image_similarities and \
                not flag_analyse_slice_residual_similarities:
            i_case += 1
            ph.print_title("%d/%d: %s" % (i_case, N_cases, case_id))

        if flag_rsync_stuff:
            dir_output = utils.get_directory_case_recon_seg_mode(
                case_id=case_id, recon_space="template_space", seg_mode="")

            dir_input = re.sub("Volumes/spina/",
                               "Volumes/medic-volumetric_res/SpinaBifida/",
                               dir_output)
            cmd = "rsync -avuhn --exclude 'motion_correction' %sseg_manual %s" % (
                dir_input, dir_output)
            ph.print_execution(cmd)
            # ph.execute_command(cmd)

        # -------------------------Correct Bias Field--------------------------
        if flag_correct_bias_field:
            filenames = utils.get_filenames_preprocessing_bias_field(case_id)
            paths_to_filenames = [
                os.path.join(utils.get_directory_case_original(case_id), f)
                for f in filenames
            ]
            dir_output = utils.get_directory_case_preprocessing(
                case_id, stage="01_N4ITK")

            # no image found matching the pattern
            if len(paths_to_filenames) == 0:
                continue

            cmd_args = []
            cmd_args.append("--filenames %s" % " ".join(paths_to_filenames))
            cmd_args.append("--dir-output %s" % dir_output)
            cmd_args.append("--prefix-output ''")
            cmd = "niftymic_correct_bias_field %s" % (" ").join(cmd_args)

            ph.execute_command(cmd,
                               flag_print_to_file=flag_batch_script,
                               path_to_file="%s%d.txt" %
                               (file_prefix_batch, ph.add_one(batch_ctr)))

        # # Skip case in case segmentations have not been provided yet
        # if not ph.directory_exists(utils.get_directory_case_segmentation(
        #         case_id, utils.SEGMENTATION_INIT, SEG_MODES[0])):
        #     continue

        # ------------------------Collect Segmentations------------------------
        if flag_collect_segmentations:
            # Skip case in case segmentations have been collected already
            if ph.directory_exists(
                    utils.get_directory_case_segmentation(
                        case_id, utils.SEGMENTATION_SELECTED, SEG_MODES[0])):
                ph.print_info("skipped")
                continue

            filenames = utils.get_segmented_image_filenames(
                case_id, subfolder=utils.SEGMENTATION_INIT)

            for i_seg_mode, seg_mode in enumerate(SEG_MODES):
                directory_selected = utils.get_directory_case_segmentation(
                    case_id, utils.SEGMENTATION_SELECTED, seg_mode)
                ph.create_directory(directory_selected)
                paths_to_filenames_init = [
                    os.path.join(
                        utils.get_directory_case_segmentation(
                            case_id, utils.SEGMENTATION_INIT, seg_mode), f)
                    for f in filenames
                ]
                paths_to_filenames_selected = [
                    os.path.join(directory_selected, f) for f in filenames
                ]
                for i in range(len(filenames)):
                    cmd = "cp -p %s %s" % (paths_to_filenames_init[i],
                                           paths_to_filenames_selected[i])
                    # ph.print_execution(cmd)
                    ph.execute_command(cmd)

        if flag_select_images_segmentations:
            filenames = utils.get_segmented_image_filenames(
                case_id, subfolder=utils.SEGMENTATION_SELECTED)
            paths_to_filenames = [
                os.path.join(
                    utils.get_directory_case_preprocessing(case_id,
                                                           stage="01_N4ITK"),
                    f) for f in filenames
            ]
            paths_to_filenames_masks = [
                os.path.join(
                    utils.get_directory_case_segmentation(
                        case_id, utils.SEGMENTATION_SELECTED, "seg_manual"), f)
                for f in filenames
            ]
            for i in range(len(filenames)):
                ph.show_niftis(
                    [paths_to_filenames[i]],
                    segmentation=paths_to_filenames_masks[i],
                    # viewer="fsleyes",
                )
                ph.pause()
                ph.killall_itksnap()

        # # -------------------------Correct Intensities-----------------------
        # if flag_correct_intensities:
        #     filenames = utils.get_segmented_image_filenames(case_id)
        #     paths_to_filenames_bias = [os.path.join(
        #         utils.get_directory_case_preprocessing(
        #             case_id, stage="01_N4ITK"), f) for f in filenames]
        #     print paths_to_filenames_bias

        # -----------------Reconstruct Volume in Subject Space-----------------
        if flag_reconstruct_volume_subject_space:

            filenames = utils.get_segmented_image_filenames(
                case_id, subfolder=utils.SEGMENTATION_SELECTED)
            # filenames = filenames[0:2]

            paths_to_filenames = [
                os.path.join(
                    utils.get_directory_case_preprocessing(case_id,
                                                           stage="01_N4ITK"),
                    f) for f in filenames
            ]

            # Estimate target stack
            target_stack_index = utils.get_target_stack_index(
                case_id, utils.SEGMENTATION_SELECTED, "seg_auto", filenames)

            for i, seg_mode in enumerate(SEG_MODES):
                # Get mask filenames
                paths_to_filenames_masks = [
                    os.path.join(
                        utils.get_directory_case_segmentation(
                            case_id, utils.SEGMENTATION_SELECTED, seg_mode), f)
                    for f in filenames
                ]

                if flag_reconstruct_volume_subject_space_irtk:
                    if seg_mode != "seg_manual":
                        continue
                    utils.export_irtk_call_to_workstation(
                        case_id=case_id,
                        filenames=filenames,
                        seg_mode=seg_mode,
                        isotropic_resolution=isotropic_resolution,
                        target_stack_index=target_stack_index,
                        kernel_mask_dilation=(15, 15, 4))

                else:
                    dir_output = utils.get_directory_case_recon_seg_mode(
                        case_id=case_id,
                        recon_space="subject_space",
                        seg_mode=seg_mode)
                    # dir_output = "/tmp/foo"

                    cmd_args = []
                    cmd_args.append("--filenames %s" %
                                    " ".join(paths_to_filenames))
                    cmd_args.append("--filenames-masks %s" %
                                    " ".join(paths_to_filenames_masks))
                    cmd_args.append("--dir-output %s" % dir_output)
                    cmd_args.append("--use-masks-srr 0")
                    cmd_args.append("--isotropic-resolution %f" %
                                    isotropic_resolution)
                    cmd_args.append("--target-stack-index %d" %
                                    target_stack_index)
                    cmd_args.append("--intensity-correction %d" %
                                    intensity_correction)
                    cmd_args.append("--outlier-rejection %d" %
                                    outlier_rejection)
                    cmd_args.append("--threshold-first %f" % threshold_first)
                    cmd_args.append("--threshold %f" % threshold)
                    # cmd_args.append("--metric %s" % metric)
                    # cmd_args.append("--multiresolution %d" % multiresolution)
                    # cmd_args.append("--metric-radius %s" % metric_radius)
                    # if i > 0:
                    #     cmd_args.append("--reconstruction-space %s" % (
                    #         utils.get_path_to_recon(
                    #             utils.get_directory_case_recon_seg_mode(
                    #                 case_id, "seg_manual"))))
                    # cmd_args.append("--two-step-cycles 0")
                    cmd_args.append("--verbose %d" % verbose)
                    cmd_args.append("--provide-comparison %d" %
                                    provide_comparison)
                    # cmd_args.append("--iter-max 1")

                    cmd = "niftymic_reconstruct_volume %s" % (
                        " ").join(cmd_args)

                    ph.execute_command(
                        cmd,
                        flag_print_to_file=flag_batch_script,
                        path_to_file="%s%d.txt" %
                        (file_prefix_batch, ph.add_one(batch_ctr)))

        if flag_reconstruct_volume_subject_space_show_comparison:
            recon_paths = []
            for seg_mode in SEG_MODES:
                path_to_recon = utils.get_path_to_recon(
                    utils.get_directory_case_recon_seg_mode(
                        case_id=case_id,
                        recon_space="subject_space",
                        seg_mode=seg_mode))
                recon_paths.append(path_to_recon)
            recon_path_irtk = os.path.join(
                utils.get_directory_case_recon_seg_mode(
                    case_id=case_id,
                    recon_space="subject_space",
                    seg_mode="IRTK"), "IRTK_SRR.nii.gz")
            show_modes = list(SEG_MODES)
            if ph.file_exists(recon_path_irtk):
                recon_paths.append(recon_path_irtk)
                show_modes.append("irtk")
            ph.show_niftis(recon_paths)
            ph.print_info("Sequence: %s" % (" -- ").join(show_modes))
            ph.pause()
            ph.killall_itksnap()

        # -------------------------Register to template------------------------
        if flag_register_to_template:
            for seg_mode in SEG_MODES:

                cmd_args = []
                # register seg_auto-recon to template space
                if seg_mode == "seg_auto":

                    path_to_recon = utils.get_path_to_recon(
                        utils.get_directory_case_recon_seg_mode(
                            case_id=case_id,
                            recon_space="subject_space",
                            seg_mode=seg_mode))

                    template_stack_estimator = \
                        tse.TemplateStackEstimator.from_mask(
                            ph.append_to_filename(path_to_recon, "_mask"))
                    path_to_reference = \
                        template_stack_estimator.get_path_to_template()

                    dir_input_motion_correction = os.path.join(
                        utils.get_directory_case_recon_seg_mode(
                            case_id=case_id,
                            recon_space="subject_space",
                            seg_mode=seg_mode), "motion_correction")

                    dir_output = utils.get_directory_case_recon_seg_mode(
                        case_id=case_id,
                        recon_space="template_space",
                        seg_mode=seg_mode)
                    # dir_output = "/home/mebner/tmp"
                    # # ------- DELETE -----
                    # dir_output = re.sub("data", "foo+1", dir_output)
                    # dir_output = re.sub(
                    #     "volumetric_reconstruction/20180126/template_space/seg_auto",
                    #     "", dir_output)
                    # # -------
                    # cmd_args.append("--use-fixed-mask 1")
                    cmd_args.append("--use-moving-mask 1")

                    # HACK
                    path_to_initial_transform = os.path.join(
                        utils.DIR_INPUT_ROOT_DATA, case_id,
                        "volumetric_reconstruction", "20180126",
                        "template_space", "seg_manual",
                        "registration_transform_sitk.txt")
                    cmd_args.append("--initial-transform %s" %
                                    path_to_initial_transform)
                    cmd_args.append("--use-flirt 0")
                    cmd_args.append("--use-regaladin 1")
                    cmd_args.append("--test-ap-flip 0")

                # register remaining recons to registered seg_auto-recon
                else:
                    path_to_reference = utils.get_path_to_recon(
                        utils.get_directory_case_recon_seg_mode(
                            case_id=case_id,
                            recon_space="template_space",
                            seg_mode="seg_auto"),
                        suffix="ResamplingToTemplateSpace",
                    )
                    path_to_initial_transform = os.path.join(
                        utils.get_directory_case_recon_seg_mode(
                            case_id=case_id,
                            recon_space="template_space",
                            seg_mode="seg_auto"),
                        "registration_transform_sitk.txt")

                    path_to_recon = utils.get_path_to_recon(
                        utils.get_directory_case_recon_seg_mode(
                            case_id=case_id,
                            recon_space="subject_space",
                            seg_mode=seg_mode))
                    dir_input_motion_correction = os.path.join(
                        utils.get_directory_case_recon_seg_mode(
                            case_id=case_id,
                            recon_space="subject_space",
                            seg_mode=seg_mode), "motion_correction")
                    dir_output = utils.get_directory_case_recon_seg_mode(
                        case_id=case_id,
                        recon_space="template_space",
                        seg_mode=seg_mode)

                    cmd_args.append("--use-fixed-mask 0")
                    cmd_args.append("--use-moving-mask 0")
                    cmd_args.append("--initial-transform %s" %
                                    path_to_initial_transform)
                    cmd_args.append("--use-flirt 0")
                    cmd_args.append("--use-regaladin 1")
                    cmd_args.append("--test-ap-flip 0")

                cmd_args.append("--moving %s" % path_to_recon)
                cmd_args.append("--fixed %s" % path_to_reference)
                cmd_args.append("--dir-input %s" % dir_input_motion_correction)
                cmd_args.append("--dir-output %s" % dir_output)
                cmd_args.append("--write-transform 1")
                cmd_args.append("--verbose %d" % verbose)
                cmd = "niftymic_register_image %s" % (" ").join(cmd_args)

                ph.execute_command(cmd,
                                   flag_print_to_file=flag_batch_script,
                                   path_to_file="%s%d.txt" %
                                   (file_prefix_batch, ph.add_one(batch_ctr)))

        if flag_register_to_template_irtk:
            dir_input = utils.get_directory_case_recon_seg_mode(
                case_id=case_id, recon_space="subject_space", seg_mode="IRTK")
            dir_output = utils.get_directory_case_recon_seg_mode(
                case_id=case_id, recon_space="template_space", seg_mode="IRTK")
            path_to_recon = os.path.join(dir_input, "IRTK_SRR.nii.gz")
            path_to_reference = utils.get_path_to_recon(
                utils.get_directory_case_recon_seg_mode(
                    case_id=case_id,
                    recon_space="template_space",
                    seg_mode="seg_manual"),
                suffix="ResamplingToTemplateSpace",
            )
            path_to_initial_transform = os.path.join(
                utils.get_directory_case_recon_seg_mode(
                    case_id=case_id,
                    recon_space="template_space",
                    seg_mode="seg_manual"), "registration_transform_sitk.txt")

            cmd_args = []
            cmd_args.append("--fixed %s" % path_to_reference)
            cmd_args.append("--moving %s" % path_to_recon)
            cmd_args.append("--initial-transform %s" %
                            path_to_initial_transform)
            cmd_args.append("--use-fixed-mask 0")
            cmd_args.append("--use-moving-mask 0")
            cmd_args.append("--use-flirt 0")
            cmd_args.append("--use-regaladin 1")
            cmd_args.append("--test-ap-flip 0")
            cmd_args.append("--dir-output %s" % dir_output)
            cmd_args.append("--verbose %d" % verbose)
            cmd = "niftymic_register_image %s" % (" ").join(cmd_args)
            ph.execute_command(cmd)

        if flag_show_srr_template_space:
            recon_paths = []
            show_modes = list(SEG_MODES)
            # show_modes.append("IRTK")
            for seg_mode in show_modes:
                dir_input = utils.get_directory_case_recon_seg_mode(
                    case_id=case_id,
                    recon_space="template_space",
                    seg_mode=seg_mode)
                # # ------- DELETE -----
                # dir_input = re.sub("data", "foo+1", dir_input)
                # dir_input = re.sub(
                #     "volumetric_reconstruction/20180126/template_space/seg_auto",
                #     "", dir_input)
                # # -------
                path_to_recon_space = utils.get_path_to_recon(
                    dir_input,
                    suffix="ResamplingToTemplateSpace",
                )
                recon_paths.append(path_to_recon_space)
            ph.show_niftis(recon_paths)
            ph.print_info("Sequence: %s" % (" -- ").join(show_modes))
            ph.pause()
            ph.killall_itksnap()

        # -----------------Reconstruct Volume in Template Space----------------
        if flag_reconstruct_volume_template_space:
            for seg_mode in SEG_MODES:
                path_to_recon_space = utils.get_path_to_recon(
                    utils.get_directory_case_recon_seg_mode(
                        case_id=case_id,
                        recon_space="template_space",
                        seg_mode=seg_mode),
                    suffix="ResamplingToTemplateSpace",
                )
                dir_input = os.path.join(
                    utils.get_directory_case_recon_seg_mode(
                        case_id=case_id,
                        recon_space="template_space",
                        seg_mode=seg_mode), "motion_correction")
                dir_output = utils.get_directory_case_recon_seg_mode(
                    case_id=case_id,
                    recon_space="template_space",
                    seg_mode=seg_mode)
                # dir_output = os.path.join("/tmp/spina/template_space/%s-%s" % (
                #     case_id, seg_mode))

                cmd_args = []
                cmd_args.append("--dir-input %s" % dir_input)
                cmd_args.append("--dir-output %s" % dir_output)
                cmd_args.append("--reconstruction-space %s" %
                                path_to_recon_space)
                cmd_args.append("--alpha %s" % alpha)
                cmd_args.append("--verbose %s" % verbose)
                cmd_args.append("--use-masks-srr 0")

                # cmd_args.append("--minimizer L-BFGS-B")
                # cmd_args.append("--alpha 0.006")
                # cmd_args.append("--reconstruction-type HuberL2")
                # cmd_args.append("--data-loss arctan")
                # cmd_args.append("--iterations 5")
                # cmd_args.append("--data-loss-scale 0.7")

                cmd = "niftymic_reconstruct_volume_from_slices %s" % \
                    (" ").join(cmd_args)
                ph.execute_command(cmd,
                                   flag_print_to_file=flag_batch_script,
                                   path_to_file="%s%d.txt" %
                                   (file_prefix_batch, ph.add_one(batch_ctr)))

        # ----------------Collect SRR results in Template Space----------------
        if flag_collect_volumetric_reconstruction_results:
            directory = utils.get_directory_case_recon_summary(case_id)
            ph.create_directory(directory)

            # clear potentially existing files
            cmd = "rm -f %s/*.nii.gz" % (directory)
            ph.execute_command(cmd)

            # Collect SRRs
            for seg_mode in SEG_MODES:
                path_to_recon_src = utils.get_path_to_recon(
                    utils.get_directory_case_recon_seg_mode(
                        case_id=case_id,
                        recon_space="template_space",
                        seg_mode=seg_mode), )
                path_to_recon = os.path.join(
                    directory, "%s%s.nii.gz" % (prefix_srr, seg_mode))

                cmd = "cp -p %s %s" % (path_to_recon_src, path_to_recon)
                ph.execute_command(cmd)

            # Collect IRTK recon
            path_to_recon_src = os.path.join(
                utils.get_directory_case_recon_seg_mode(
                    case_id=case_id,
                    recon_space="template_space",
                    seg_mode="IRTK"),
                "IRTK_SRR_LinearResamplingToTemplateSpace.nii.gz")

            path_to_recon = os.path.join(directory,
                                         "%s%s.nii.gz" % (prefix_srr, "irtk"))

            cmd = "cp -p %s %s" % (path_to_recon_src, path_to_recon)
            ph.execute_command(cmd)

            # Collect evaluation mask
            path_to_recon = utils.get_path_to_recon(
                utils.get_directory_case_recon_seg_mode(
                    case_id=case_id,
                    recon_space="subject_space",
                    seg_mode="seg_auto"))

            template_stack_estimator = \
                tse.TemplateStackEstimator.from_mask(
                    ph.append_to_filename(path_to_recon, "_mask"))
            path_to_template = \
                template_stack_estimator.get_path_to_template()
            path_to_template_mask_src = ph.append_to_filename(
                path_to_template, "_mask_dil")
            path_to_template_mask = "%s/" % directory

            cmd = "cp -p %s %s" % (path_to_template_mask_src,
                                   path_to_template_mask)
            ph.execute_command(cmd)

        if flag_show_volumetric_reconstruction_results:
            dir_output = utils.get_directory_case_recon_summary(case_id)
            paths_to_recons = []
            for seg_mode in RECON_MODES:
                path_to_recon = os.path.join(
                    dir_output, "%s%s.nii.gz" % (prefix_srr, seg_mode))
                paths_to_recons.append(path_to_recon)
            path_to_mask = "%s/STA*.nii.gz" % dir_output
            cmd = ph.show_niftis(paths_to_recons, segmentation=path_to_mask)
            sitkh.write_executable_file([cmd], dir_output=dir_output)
            ph.pause()
            ph.killall_itksnap()

        # ---------------------Evaluate Image Similarities---------------------
        if flag_evaluate_image_similarities:
            dir_input = utils.get_directory_case_recon_summary(case_id)
            dir_output = utils.get_directory_case_recon_similarities(case_id)
            paths_to_recons = []
            for seg_mode in ["seg_auto", "detect", "irtk"]:
                path_to_recon = os.path.join(
                    dir_input, "%s%s.nii.gz" % (prefix_srr, seg_mode))
                paths_to_recons.append(path_to_recon)
            path_to_reference = os.path.join(
                dir_input, "%s%s.nii.gz" % (prefix_srr, "seg_manual"))
            path_to_reference_mask = utils.get_path_to_mask(dir_input)

            cmd_args = []
            cmd_args.append("--filenames %s" % " ".join(paths_to_recons))
            cmd_args.append("--reference %s" % path_to_reference)
            cmd_args.append("--reference-mask %s" % path_to_reference_mask)
            # cmd_args.append("--verbose 1")
            cmd_args.append("--dir-output %s" % dir_output)

            exe = re.sub("pyc", "py",
                         os.path.abspath(evaluate_image_similarity.__file__))
            cmd_args.insert(0, exe)

            # clear potentially existing files
            cmd = "rm -f %s/*.txt" % (dir_output)
            ph.execute_command(cmd)

            cmd = "python %s" % " ".join(cmd_args)
            ph.execute_command(cmd)

        # -----------------Evaluate Slice Residual Similarities----------------
        if flag_evaluate_slice_residual_similarities:

            path_to_reference_mask = utils.get_path_to_mask(
                utils.get_directory_case_recon_summary(case_id))

            dir_output_root = \
                utils.get_directory_case_slice_residual_similarities(case_id)

            # clear potentially existing files
            # cmd = "rm -f %s/*.txt" % (dir_output_root)
            # ph.execute_command(cmd)

            for seg_mode in SEG_MODES:
                dir_input = os.path.join(
                    utils.get_directory_case_recon_seg_mode(
                        case_id=case_id,
                        recon_space="template_space",
                        seg_mode=seg_mode,
                    ), "motion_correction")
                path_to_reference = os.path.join(
                    utils.get_directory_case_recon_summary(case_id),
                    "%s%s.nii.gz" % (prefix_srr, seg_mode))
                dir_output = os.path.join(dir_output_root, seg_mode)

                cmd_args = []
                cmd_args.append("--dir-input %s" % dir_input)
                cmd_args.append("--reference %s" % path_to_reference)
                cmd_args.append("--reference-mask %s" % path_to_reference_mask)
                cmd_args.append("--use-reference-mask 1")
                cmd_args.append("--use-slice-masks 0")
                # cmd_args.append("--verbose 1")
                cmd_args.append("--dir-output %s" % dir_output)

                exe = re.sub("pyc", "py", os.path.abspath(esrs.__file__))
                cmd_args.insert(0, exe)

                cmd = "python %s" % " ".join(cmd_args)
                ph.execute_command(cmd)

        # Collect data for blinded analysis
        if flag_collect_data_blinded_analysis:
            if flag_remove_failed_cases_for_analysis and case_id in RECON_FAILED_CASE_IDS:
                continue

            dir_input = utils.get_directory_case_recon_summary(case_id)
            # pattern = "STA([0-9]+)[_]mask.nii.gz"
            pattern = "STA([0-9]+)[_]mask_dil.nii.gz"
            p = re.compile(pattern)
            gw = [
                p.match(f).group(1) for f in os.listdir(dir_input)
                if p.match(f)
            ][0]

            dir_output = os.path.join(
                utils.get_directory_blinded_analysis(case_id, "open"), case_id)

            exe = re.sub("pyc", "py", os.path.abspath(mswm.__file__))

            recons = []

            for seg_mode in RECON_MODES:
                path_to_recon = os.path.join(
                    dir_input, "%s%s.nii.gz" % (prefix_srr, seg_mode))

                cmd_args = []
                cmd_args.append("--filename %s" % path_to_recon)
                cmd_args.append("--gestational-age %s" % gw)
                cmd_args.append("--dir-output %s" % dir_output)
                cmd_args.append("--prefix-output %s" % prefix_srr_qa)
                cmd_args.append("--verbose 0")
                cmd_args.insert(0, exe)

                cmd = "python %s" % " ".join(cmd_args)
                # ph.execute_command(cmd)

                recon = "%s%s" % (prefix_srr_qa,
                                  os.path.basename(path_to_recon))
                recons.append(recon)
            ph.write_show_niftis_exe(recons, dir_output)

        if flag_anonymize_data_blinded_analysis:
            dir_input = os.path.join(
                utils.get_directory_blinded_analysis(case_id, "open"), case_id)
            dir_output_dictionaries = utils.get_directory_anonymized_dictionares(
                case_id)
            dir_output_anonymized_images = os.path.join(
                utils.get_directory_blinded_analysis(case_id, "anonymized"),
                case_id)

            if not ph.directory_exists(dir_input):
                continue
            ph.create_directory(dir_output_dictionaries)
            ph.create_directory(dir_output_anonymized_images)

            data_anonymizer = da.DataAnonymizer()
            # Create random dictionary (only required once)
            # data_anonymizer.set_prefix_identifiers("%s_" % case_id)
            # data_anonymizer.read_nifti_filenames_from_directory(dir_input)
            # data_anonymizer.generate_identifiers()
            # data_anonymizer.generate_randomized_dictionary()
            # data_anonymizer.write_dictionary(
            #     dir_output_dictionaries, "dictionary_%s" % case_id)

            # Read dictionary
            data_anonymizer.read_dictionary(dir_output_dictionaries,
                                            "dictionary_%s" % case_id)

            # Anonymize files
            if 0:
                ph.clear_directory(dir_output_anonymized_images)
                data_anonymizer.anonymize_files(dir_input,
                                                dir_output_anonymized_images)

                # Write executable script
                filenames = [
                    "%s.nii.gz" % f
                    for f in sorted(data_anonymizer.get_identifiers())
                ]
                ph.write_show_niftis_exe(filenames,
                                         dir_output_anonymized_images)

            # Reveal anonymized files
            if 1:
                filenames = data_anonymizer.reveal_anonymized_files(
                    dir_output_anonymized_images)
                filenames = sorted(["%s" % f for f in filenames])
                ph.write_show_niftis_exe(filenames,
                                         dir_output_anonymized_images)

            # Reveal additional, original files
            # data_anonymizer.reveal_original_files(dir_output)

            # relative_directory = re.sub(
            #     utils.get_directory_blinded_analysis(case_id, "anonymized"),
            #     ".",
            #     dir_output_anonymized_images)
            # paths_to_filenames = [os.path.join(
            #     relative_directory, f) for f in filenames]

        # ---------------------Analyse Image Similarities---------------------
        if flag_analyse_image_similarities or \
                flag_analyse_slice_residual_similarities or \
                flag_analyse_stacks:
            if flag_remove_failed_cases_for_analysis:
                if case_id in RECON_FAILED_CASE_IDS:
                    continue
            if cases[case_id]['postrep'] == flag_postop or flag_postop == 2:
                cases_similarities.append(case_id)
                cases_stacks.append(
                    utils.get_segmented_image_filenames(
                        case_id,
                        # subfolder=utils.SEGMENTATION_INIT,
                        subfolder=utils.SEGMENTATION_SELECTED,
                    ))

        dir_output_analysis = os.path.join(
            # "/Users/mebner/UCL/UCL/Publications",
            "/home/mebner/Dropbox/UCL/Publications",
            "2018_MICCAI/brain_reconstruction_paper")

    if flag_analyse_image_similarities:
        dir_inputs = []
        filename = "image_similarities_postop%d.txt" % flag_postop
        for case_id in cases_similarities:
            dir_inputs.append(
                utils.get_directory_case_recon_similarities(case_id))
        cmd_args = []
        cmd_args.append("--dir-inputs %s" % " ".join(dir_inputs))
        cmd_args.append("--dir-output %s" % dir_output_analysis)
        cmd_args.append("--filename %s" % filename)

        exe = re.sub("pyc", "py",
                     os.path.abspath(src.analyse_image_similarities.__file__))
        cmd_args.insert(0, exe)

        cmd = "python %s" % " ".join(cmd_args)
        ph.execute_command(cmd)

    if flag_analyse_slice_residual_similarities:
        dir_inputs = []
        filename = "slice_residuals_postop%d.txt" % flag_postop
        for case_id in cases_similarities:
            dir_inputs.append(
                utils.get_directory_case_slice_residual_similarities(case_id))
        cmd_args = []
        cmd_args.append("--dir-inputs %s" % " ".join(dir_inputs))
        cmd_args.append("--subfolder %s" % " ".join(SEG_MODES))
        cmd_args.append("--dir-output %s" % dir_output_analysis)
        cmd_args.append("--filename %s" % filename)

        exe = re.sub(
            "pyc", "py",
            os.path.abspath(src.analyse_slice_residual_similarities.__file__))
        cmd_args.insert(0, exe)

        cmd = "python %s" % " ".join(cmd_args)
        # print len(cases_similarities)
        # print cases_similarities
        ph.execute_command(cmd)

    if flag_analyse_stacks:
        cases_stacks_N = [len(s) for s in cases_stacks]
        ph.print_subtitle("%d cases -- Number of stacks" % len(cases_stacks))
        ph.print_info("min: %g" % np.min(cases_stacks_N))
        ph.print_info("mean: %g" % np.mean(cases_stacks_N))
        ph.print_info("median: %g" % np.median(cases_stacks_N))
        ph.print_info("max: %g" % np.max(cases_stacks_N))

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

    return 0
def main():

    time_start = ph.start_timing()

    np.set_printoptions(precision=3)

    input_parser = InputArgparser(
        description="Register an obtained reconstruction (moving) "
        "to a template image/space (fixed) using rigid registration. "
        "The resulting registration can optionally be applied to previously "
        "obtained motion correction slice transforms so that a volumetric "
        "reconstruction is possible in the (standard anatomical) space "
        "defined by the fixed.", )
    input_parser.add_fixed(required=True)
    input_parser.add_moving(required=True)
    input_parser.add_output(help="Path to registration transform (.txt)",
                            required=True)
    input_parser.add_fixed_mask(required=False)
    input_parser.add_moving_mask(required=False)
    input_parser.add_option(
        option_string="--initial-transform",
        type=str,
        help="Path to initial transform. "
        "If not provided, registration will be initialized based on "
        "rigid alignment of eigenbasis of the fixed/moving image masks "
        "using principal component analysis",
        default=None)
    input_parser.add_v2v_method(
        option_string="--method",
        help="Registration method used for the registration.",
        default="RegAladin",
    )
    input_parser.add_argument(
        "--init-pca",
        "-init-pca",
        action='store_true',
        help="If given, PCA-based initializations will be refined using "
        "RegAladin registrations.")
    input_parser.add_dir_input_mc()
    input_parser.add_verbose(default=0)
    input_parser.add_log_config(default=1)

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

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

    if not args.output.endswith(".txt"):
        raise IOError("output filename '%s' invalid; "
                      "allowed transformation extensions are: '.txt'" %
                      (args.output))

    if args.initial_transform is not None and args.init_pca:
        raise IOError(
            "Both --initial-transform and --init-pca cannot be activated. "
            "Choose one.")

    dir_output = os.path.dirname(args.output)
    ph.create_directory(dir_output)

    debug = False

    # --------------------------------Read Data--------------------------------
    ph.print_title("Read Data")
    fixed = st.Stack.from_filename(file_path=args.fixed,
                                   file_path_mask=args.fixed_mask,
                                   extract_slices=False)
    moving = st.Stack.from_filename(file_path=args.moving,
                                    file_path_mask=args.moving_mask,
                                    extract_slices=False)

    path_to_tmp_output = os.path.join(
        DIR_TMP, ph.append_to_filename(os.path.basename(args.moving),
                                       "_warped"))

    # ---------------------------- Initialization ----------------------------
    if args.initial_transform is None and args.init_pca:
        ph.print_title("Estimate (initial) transformation using PCA")

        if args.moving_mask is None or args.fixed_mask is None:
            ph.print_warning("Fixed and moving masks are strongly recommended")
        transform_initializer = tinit.TransformInitializer(
            fixed=fixed,
            moving=moving,
            similarity_measure="NMI",
            refine_pca_initializations=True,
        )
        transform_initializer.run()
        transform_init_sitk = transform_initializer.get_transform_sitk()

    elif args.initial_transform is not None:
        transform_init_sitk = sitkh.read_transform_sitk(args.initial_transform)

    else:
        transform_init_sitk = None

    if transform_init_sitk is not None:
        sitk.WriteTransform(transform_init_sitk, args.output)

    # -------------------Register Reconstruction to Template-------------------
    ph.print_title("Registration")

    # If --init-pca given, RegAladin run already performed
    if args.method == "RegAladin" and not args.init_pca:

        path_to_transform_regaladin = os.path.join(DIR_TMP,
                                                   "transform_regaladin.txt")

        # Convert SimpleITK to RegAladin transform
        if transform_init_sitk is not None:
            cmd = "simplereg_transform -sitk2nreg %s %s" % (
                args.output, path_to_transform_regaladin)
            ph.execute_command(cmd, verbose=False)

        # Run NiftyReg
        cmd_args = ["reg_aladin"]
        cmd_args.append("-ref '%s'" % args.fixed)
        cmd_args.append("-flo '%s'" % args.moving)
        cmd_args.append("-res '%s'" % path_to_tmp_output)
        if transform_init_sitk is not None:
            cmd_args.append("-inaff '%s'" % path_to_transform_regaladin)
        cmd_args.append("-aff '%s'" % path_to_transform_regaladin)
        cmd_args.append("-rigOnly")
        cmd_args.append("-ln 2")  # seems to perform better for spina bifida
        cmd_args.append("-voff")
        if args.fixed_mask is not None:
            cmd_args.append("-rmask '%s'" % args.fixed_mask)

        # To avoid error "0 correspondences between blocks were found" that can
        # occur for some cases. Also, disable moving mask, as this would be ignored
        # anyway
        cmd_args.append("-noSym")
        # if args.moving_mask is not None:
        #     cmd_args.append("-fmask '%s'" % args.moving_mask)

        ph.print_info("Run Registration (RegAladin) ... ", newline=False)
        ph.execute_command(" ".join(cmd_args), verbose=debug)
        print("done")

        # Convert RegAladin to SimpleITK transform
        cmd = "simplereg_transform -nreg2sitk '%s' '%s'" % (
            path_to_transform_regaladin, args.output)
        ph.execute_command(cmd, verbose=False)

    elif args.method == "FLIRT":
        path_to_transform_flirt = os.path.join(DIR_TMP, "transform_flirt.txt")

        # Convert SimpleITK into FLIRT transform
        if transform_init_sitk is not None:
            cmd = "simplereg_transform -sitk2flirt '%s' '%s' '%s' '%s'" % (
                args.output, args.fixed, args.moving, path_to_transform_flirt)
            ph.execute_command(cmd, verbose=False)

        # Define search angle ranges for FLIRT in all three dimensions
        # search_angles = ["-searchr%s -%d %d" % (x, 180, 180)
        #                  for x in ["x", "y", "z"]]

        cmd_args = ["flirt"]
        cmd_args.append("-in '%s'" % args.moving)
        cmd_args.append("-ref '%s'" % args.fixed)
        if transform_init_sitk is not None:
            cmd_args.append("-init '%s'" % path_to_transform_flirt)
        cmd_args.append("-omat '%s'" % path_to_transform_flirt)
        cmd_args.append("-out '%s'" % path_to_tmp_output)
        cmd_args.append("-dof 6")
        # cmd_args.append((" ").join(search_angles))
        if args.moving_mask is not None:
            cmd_args.append("-inweight '%s'" % args.moving_mask)
        if args.fixed_mask is not None:
            cmd_args.append("-refweight '%s'" % args.fixed_mask)
        ph.print_info("Run Registration (FLIRT) ... ", newline=False)
        ph.execute_command(" ".join(cmd_args), verbose=debug)
        print("done")

        # Convert FLIRT to SimpleITK transform
        cmd = "simplereg_transform -flirt2sitk '%s' '%s' '%s' '%s'" % (
            path_to_transform_flirt, args.fixed, args.moving, args.output)
        ph.execute_command(cmd, verbose=False)
    ph.print_info("Registration transformation written to '%s'" % args.output)

    if args.dir_input_mc is not None:
        ph.print_title("Update Motion-Correction Transformations")
        transform_sitk = sitkh.read_transform_sitk(args.output, inverse=1)

        if args.dir_input_mc.endswith("/"):
            subdir_mc = args.dir_input_mc.split("/")[-2]
        else:
            subdir_mc = args.dir_input_mc.split("/")[-1]
        dir_output_mc = os.path.join(dir_output, subdir_mc)

        ph.create_directory(dir_output_mc, delete_files=True)
        pattern = REGEX_FILENAMES + "[.]tfm"
        p = re.compile(pattern)
        trafos = [t for t in os.listdir(args.dir_input_mc) if p.match(t)]
        for t in trafos:
            path_to_input_transform = os.path.join(args.dir_input_mc, t)
            path_to_output_transform = os.path.join(dir_output_mc, t)
            t_sitk = sitkh.read_transform_sitk(path_to_input_transform)
            t_sitk = sitkh.get_composite_sitk_affine_transform(
                transform_sitk, t_sitk)
            sitk.WriteTransform(t_sitk, path_to_output_transform)
        ph.print_info("%d transformations written to '%s'" %
                      (len(trafos), dir_output_mc))

        # Copy rejected_slices.json file
        path_to_rejected_slices = os.path.join(args.dir_input_mc,
                                               "rejected_slices.json")
        if ph.file_exists(path_to_rejected_slices):
            ph.copy_file(path_to_rejected_slices, dir_output_mc)

    if args.verbose:
        cmd_args = ["simplereg_resample"]
        cmd_args.append("-f %s" % args.fixed)
        cmd_args.append("-m %s" % args.moving)
        cmd_args.append("-t %s" % args.output)
        cmd_args.append("-o %s" % path_to_tmp_output)
        ph.execute_command(" ".join(cmd_args))

        ph.show_niftis([args.fixed, path_to_tmp_output])

    elapsed_time_total = ph.stop_timing(time_start)

    # Summary
    ph.print_title("Summary")
    exe_file_info = os.path.basename(os.path.abspath(__file__)).split(".")[0]
    print("%s | Computational Time: %s" % (exe_file_info, elapsed_time_total))

    return 0
Exemple #20
0
    def test_register_image(self):
        filename = "registration_transform_sitk.txt"
        gestational_age = 28

        path_to_recon = os.path.join(
            self.dir_data, "register_image",
            "SRR_stacks3_TK1_lsmr_alpha0p02_itermax5.nii.gz")
        dir_input_mc = os.path.join(self.dir_data, "register_image",
                                    "motion_correction")

        path_to_transform_res = os.path.join(self.dir_output, filename)
        path_to_transform_ref = os.path.join(self.dir_data, "register_image",
                                             filename)
        dir_ref_mc = os.path.join(self.dir_data, "register_image",
                                  "motion_correction_ref")
        path_to_rejected_slices_ref = os.path.join(dir_ref_mc,
                                                   "rejected_slices.json")

        template = os.path.join(DIR_TEMPLATES,
                                "STA%d.nii.gz" % gestational_age)
        template_mask = os.path.join(DIR_TEMPLATES,
                                     "STA%d_mask.nii.gz" % gestational_age)

        cmd_args = ["niftymic_register_image"]
        cmd_args.append("--fixed %s" % template)
        cmd_args.append("--moving %s" % path_to_recon)
        cmd_args.append("--fixed-mask %s" % template_mask)
        cmd_args.append("--moving-mask %s" %
                        ph.append_to_filename(path_to_recon, self.suffix_mask))
        cmd_args.append("--dir-input-mc %s" % dir_input_mc)
        cmd_args.append("--output %s" % path_to_transform_res)
        cmd_args.append("--init-pca")
        # cmd_args.append("--verbose 1")
        self.assertEqual(ph.execute_command(" ".join(cmd_args)), 0)

        # Check registration transform
        res_sitk = sitkh.read_transform_sitk(path_to_transform_res)
        ref_sitk = sitkh.read_transform_sitk(path_to_transform_ref)

        res_nda = res_sitk.GetParameters()
        ref_nda = ref_sitk.GetParameters()
        diff_nda = np.array(res_nda) - ref_nda

        self.assertAlmostEqual(np.linalg.norm(diff_nda),
                               0,
                               places=self.precision)

        # Check individual slice transforms
        pattern = REGEX_FILENAMES + "[.]tfm"
        p = re.compile(pattern)
        dir_res_mc = os.path.join(self.dir_output, "motion_correction")
        trafos_res = sorted([
            os.path.join(dir_res_mc, t) for t in os.listdir(dir_res_mc)
            if p.match(t)
        ])
        trafos_ref = sorted([
            os.path.join(dir_ref_mc, t) for t in os.listdir(dir_res_mc)
            if p.match(t)
        ])
        self.assertEqual(len(trafos_res), len(trafos_ref))
        for i in range(len(trafos_ref)):
            nda_res = sitkh.read_transform_sitk(trafos_res[i]).GetParameters()
            nda_ref = sitkh.read_transform_sitk(trafos_ref[i]).GetParameters()
            nda_diff = np.linalg.norm(np.array(nda_res) - nda_ref)
            self.assertAlmostEqual(nda_diff, 0, places=self.precision)

        # Check rejected_slices.json
        path_to_rejected_slices_res = os.path.join(dir_res_mc,
                                                   "rejected_slices.json")
        self.assertEqual(ph.file_exists(path_to_rejected_slices_res), True)
        rejected_slices_res = ph.read_dictionary_from_json(
            path_to_rejected_slices_res)
        rejected_slices_ref = ph.read_dictionary_from_json(
            path_to_rejected_slices_ref)
        self.assertEqual(rejected_slices_res == rejected_slices_ref, True)