Пример #1
0
    def run(self):

        if self.movdir.is_file():
            moving_imgs = [self.movdir]
        else:
            moving_imgs = common.get_file_paths(
                self.movdir, ignore_folder=RESOLUTION_IMG_FOLDER
            )  # This breaks if not ran from config dir

        if len(moving_imgs) < 1:
            raise common.LamaDataException("No volumes in {}".format(
                self.movdir))

        for mov in moving_imgs:
            mov_basename = mov.stem
            outdir = self.stagedir / mov_basename
            outdir.mkdir(parents=True)

            cmd = {
                'mov': str(mov),
                'fixed': str(self.fixed),
                'outdir': str(outdir),
                'elxparam_file': str(self.elxparam_file),
                'threads': self.threads,
                'fixed': str(self.fixed)
            }
            if self.fixed_mask is not None:
                cmd['fixed_mask'] = str(self.fixed_mask)

            run_elastix(cmd)

            # Rename the registered output.
            elx_outfile = outdir / f'result.0.{self.filetype}'
            new_out_name = outdir / f'{mov_basename}.{self.filetype}'

            try:
                shutil.move(elx_outfile, new_out_name)
            except IOError:
                logging.error(
                    'Cannot find elastix output. Ensure the following is not set: (WriteResultImage  "false")'
                )
                raise

            move_intemediate_volumes(outdir)

            # add registration metadata
            reg_metadata_path = outdir / common.INDV_REG_METADATA
            fixed_vol_relative = relpath(self.fixed, outdir)
            reg_metadata = {'fixed_vol': fixed_vol_relative}

            with open(reg_metadata_path, 'w') as fh:
                fh.write(yaml.dump(reg_metadata, default_flow_style=False))
Пример #2
0
def pad_volumes(indirs: Iterable[Path],
                max_dims: Tuple,
                outdir: Path,
                clobber: bool,
                filetype: str = 'nrrd'):
    """
    Pad volumes, masks, labels. Output files will have same name as original, but be in a new output folder

    Parameters
    ----------
    indirs
        one or more directories containing volumes to pad (Will search subdirectories for volumes)
    max_dims
        dimensions to pad to (z, y, x)
    outdir
        path to output dir
    """

    if clobber and outdir:
        print('Specifiy either --clobber or an output dir (-o)')
        return
    if not clobber and not outdir:
        print('Specifiy either --clobber or an output dir (-o)')
        return

    if not max_dims:
        max_dims = get_largest_dimensions(indirs)

    print(f'Zero padding to {max_dims}')

    outdir = outdir

    for dir_ in indirs:
        dir_ = Path(dir_)

        if clobber:
            result_dir = dir_
        else:
            result_dir = outdir / dir_.name
            result_dir.mkdir(exist_ok=True, parents=True)

        volpaths = common.get_file_paths(dir_)

        # print('Padding to {} - {} volumes/masks:'.format(str(max_dims), str(len(volpaths))))
        # pad_info = Dict()

        for path in volpaths:

            if clobber:
                outpath = path
            else:
                outpath = result_dir / path.name

            loader = common.LoadImage(path)
            vol = loader.img
            if not vol:
                logging.error('error loading image for padding: {}'.format(
                    loader.error_msg))
                sys.exit()
            vol_dims = vol.GetSize()

            # The voxel differences between the vol dims and the max dims
            diffs = [m - v for m, v in zip(max_dims, vol_dims)]

            # How many pixels to add to the upper bounds of each dimension, divide by two and round down to nearest int
            upper_extend = [d // 2 for d in diffs]

            # In case of differnces that cannot be /2. Get the remainder to add to the lower bound
            remainders = [d % 2 for d in diffs]

            # Add the remainders to the upper bound extension to get the lower bound extension
            lower_extend = [u + r for u, r in zip(upper_extend, remainders)]

            # if any values are negative, stop. We need all volumes to be the same size
            for ex_val in zip(lower_extend, upper_extend):

                if ex_val[0] < 0 or ex_val[1] < 0:
                    msg = (
                        "\ncan't pad images\n"
                        "{} is larger than the specified volume size\n"
                        "Current vol size:{},\n"
                        "Max vol size: {}"
                        "\nCheck the 'pad_dims' in the config file\n".format(
                            basename(path), str(vol_dims), str(max_dims)))

                    logging.error(msg)
                    raise common.LamaDataException(msg)

            # Pad the volume. New pixels set to zero
            padded_vol = sitk.ConstantPad(vol, upper_extend, lower_extend, 0)
            padded_vol.SetOrigin((0, 0, 0))
            padded_vol.SetSpacing((1, 1, 1))

            sitk.WriteImage(padded_vol, str(outpath), True)
            # pad_info['data'][input_basename]['pad'] = [upper_extend, lower_extend]
    print('Finished padding')
Пример #3
0
    def run(self):

        # If inputs_vols is a file get the specified root and paths from it
        if isdir(self.movdir):
            movlist = common.get_file_paths(self.movdir)
        else:
            movlist = common.get_inputs_from_file_list(self.movdir,
                                                       self.config_dir)

        if len(movlist) < 1:
            raise common.LamaDataException("No volumes in {}".format(
                self.movdir))

        for fixed in movlist:  # Todo: change variable name fixed to moving
            tp_file_paths = defaultdict(list)
            full_tp_file_paths = []
            fixed_basename = splitext(basename(fixed))[0]
            fixed_dir = self.paths.make(join(self.stagedir, fixed_basename),
                                        'f')

            for moving in movlist:
                if basename(fixed) == basename(moving):
                    continue
                moving_basename = splitext(basename(moving))[0]
                outdir = join(fixed_dir, moving_basename)
                common.mkdir_force(outdir)

                run_elastix({
                    'mov': moving,
                    'fixed': fixed,
                    'outdir': outdir,
                    'elxparam_file': self.elxparam_file,
                    'threads': self.threads,
                    'fixed': fixed
                })
                # Get the resolution tforms
                tforms = list(
                    sorted([
                        x for x in os.listdir(outdir)
                        if x.startswith(REOLSUTION_TP_PREFIX)
                    ]))
                # get the full tform that spans all resolutions
                full_tp_file_paths.append(join(outdir, FULL_STAGE_TP_FILENAME))

                # Add the tforms to a resolution-specific list so we can generate deformations from any range
                # of deformations later
                for i, tform in enumerate(tforms):
                    tp_file_paths[i].append(join(outdir, tform))

                # add registration metadata
                reg_metadata_path = join(outdir, common.INDV_REG_METADATA)
                fixed_vol_relative = relpath(fixed, outdir)
                reg_metadata = {'fixed_vol': fixed_vol_relative}
                with open(reg_metadata_path, 'w') as fh:
                    fh.write(yaml.dump(reg_metadata, default_flow_style=False))

            for i, files_ in tp_file_paths.items():
                mean_tfom_name = "{}{}.txt".format(REOLSUTION_TP_PREFIX, i)
                self.generate_mean_tranform(files_, fixed, fixed_dir,
                                            mean_tfom_name, self.filetype)
            self.generate_mean_tranform(full_tp_file_paths, fixed, fixed_dir,
                                        FULL_STAGE_TP_FILENAME, self.filetype)
Пример #4
0
    def run(self):

        if self.movdir.is_file():
            moving_imgs = [self.movdir]
        else:
            moving_imgs = common.get_file_paths(
                self.movdir,
                ignore_folders=[RESOLUTION_IMGS_DIR, IMG_PYRAMID_DIR
                                ])  # This breaks if not ran from config dir

        if len(moving_imgs) < 1:
            raise common.LamaDataException("No volumes in {}".format(
                self.movdir))

        for mov in moving_imgs:
            mov_basename = mov.stem
            outdir = self.stagedir / mov_basename
            outdir.mkdir(parents=True)

            cmd = {
                'mov': str(mov),
                'fixed': str(self.fixed),
                'outdir': str(outdir),
                'elxparam_file': str(self.elxparam_file),
                'threads': self.threads,
                'fixed': str(self.fixed)
            }
            if self.fixed_mask is not None:
                cmd['fixed_mask'] = str(self.fixed_mask)

            run_elastix(cmd)

            # Rename the registered output.
            if self.rename_output:
                elx_outfile = outdir / f'result.0.{self.filetype}'
                new_out_name = outdir / f'{mov_basename}.{self.filetype}'

                try:
                    shutil.move(elx_outfile, new_out_name)
                except IOError:
                    logging.error(
                        'Cannot find elastix output. Ensure the following is not set: (WriteResultImage  "false")'
                    )
                    raise

                move_intemediate_volumes(outdir)

            # add registration metadata
            reg_metadata_path = outdir / common.INDV_REG_METADATA
            fixed_vol_relative = relpath(self.fixed, outdir)
            reg_metadata = {'fixed_vol': fixed_vol_relative}

            with open(reg_metadata_path, 'w') as fh:
                fh.write(yaml.dump(reg_metadata, default_flow_style=False))

            if self.fix_folding:
                # Remove any folds folds in the Bsplines, overwtite inplace
                tform_param_file = outdir / ELX_TRANSFORM_NAME
                unfold_bsplines(tform_param_file, tform_param_file)

                # Retransform the moving image with corrected tform file
                cmd = [
                    'transformix', '-in',
                    str(mov), '-out',
                    str(outdir), '-tp', tform_param_file
                ]
                subprocess.call(cmd)
                unfolded_moving_img = outdir / 'result.nrrd'
                new_out_name.unlink()
                shutil.move(unfolded_moving_img, new_out_name)