def shift_modify_header(img: MincAtom,
                        shifted_img: MincAtom,
                        newx: float,
                        newy: float,
                        newz: float):
    s = Stages()
    #Copy file to new location
    stage = CmdStage(inputs=(img,), outputs=(shifted_img,), memory=1,
                     cmd=['cp', img.path, shifted_img.path])
    print(stage.render())
    s.add(stage)
    #Alter header of copied image to shift
    xspace_start = 'xspace:start='+newx
    yspace_start = 'yspace:start='+newy
    zspace_start = 'zspace:start='+newz
    stage = CmdStage(inputs=(shifted_img,), outputs=(shifted_img,), memory=1,
                     cmd=['minc_modify_header','-dinsert',xspace_start,
                          '-dinsert',yspace_start,
                          '-dinsert',zspace_start,
                          shifted_img.path])
    print(stage.render())
    s.add(stage)
    #Alter header of copied image with header modification
    append_history_string = ':history= >>> copy and shift: '+ shifted_img.path +' to '+ shifted_img.path
    stage = CmdStage(inputs=(shifted_img,), outputs=(shifted_img,), memory=1,
                     cmd=['minc_modify_header','-sappend',
                          append_history_string,
                          shifted_img.path])
    print(stage.render())
    s.add(stage)
    return Result(stages=s, output=shifted_img)
def dist_corr_basket(img: MincAtom,
                     dc_img: MincAtom):

    stage = CmdStage(inputs=(img,), outputs=(dc_img,), memory=4,
                     cmd=['distortion_correction_september_2014.pl',
                          '-spawn','-output-dir', img.pipeline_sub_dir,
                          img.path])
    print(stage.render())
    stage.set_log_file(log_file_name=os.path.join(img.pipeline_sub_dir,"dist_corr.log"))

    return Result(stages=Stages([stage]), output=dc_img)
Пример #3
0
def dramms_warp_simple(img: NiiAtom,
                       xfm: DrammsXfmAtom,
                       like: Optional[NiiAtom] = None,
                       extra_flags: Tuple[str] = (),
                       use_nn_interpolation=None,
                       invert: bool = False,
                       new_name_wo_ext: str = None,
                       subdir: str = None) -> Result[NiiAtom]:
    """
    Resample an image, ignoring mask/labels
    ...
    new_name_wo_ext -- string indicating a user specified file name (without extension)
    """

    s = Stages()

    if invert:
        inv_xfm = xfm.newname_with_suffix("_inverted")
        s.add(
            CmdStage(cmd=["dramms-defop", "-i", xfm.path, inv_xfm.path],
                     inputs=(xfm, ),
                     outputs=(inv_xfm, )))
        xfm = inv_xfm

    if not subdir:
        subdir = 'resampled'

    if not new_name_wo_ext:
        # FIXME the path to `outf` is wrong.  For instance, resampling a mask file ends up in the initial model
        # FIXME directory instead of in the resampled directory.
        # FIXME At the same time, `like.newname(...)` doesn't work either, for similar reasons.
        # FIXME Not clear if there's a general "automagic" fix for this.
        # FIXME Also, using the xfm's filename is wrong, since we might be resampling, e.g., a mask.
        # FIXME We should basically use the same naming scheme as is used to generate the xfm's name but
        # FIXME use the files for resampling, not registration
        outf = img.newname(name=xfm.filename_wo_ext + '-resampled',
                           subdir=subdir)
    else:
        # we have the output filename without extension. This should replace the entire
        # current "base" of the filename.
        outf = img.newname(name=new_name_wo_ext, subdir=subdir)

    stage = CmdStage(
        inputs=(xfm, like, img),
        outputs=(outf, ),
        cmd=(['dramms-warp'] + (['-n'] if use_nn_interpolation else []) +
             (['-transform %s' % xfm.path])  #if xfm is not identity else [])
             + ['-like %s' % like.path, img.path, outf.path]))

    s.add(stage)

    return Result(stages=s, output=outf)
def antsRegistration(fixed: MincAtom,
                     moving: MincAtom,
                     transform: XfmAtom,
                     output_dir: str,
                     warped: str = "Warped.nii.gz",
                     inversewarped: str = "InverseWarped.nii.gz",
                     dimensionality: int = 3):
    #TODO warped and inversewarped output to the working directory
    stage = CmdStage(
        inputs=(fixed, moving),
        outputs=(transform, ),
        cmd=[
            'antsRegistration',
            '--verbose 1',
            '--float 0',
            '--minc',
            '--dimensionality %s' % dimensionality,
            '--output [%s,%s,%s]' % (transform.path.replace(
                '0_GenericAffine.xfm', ''), warped, inversewarped),
            '--interpolation Linear',
            '--use-histogram-matching 0',
            '--winsorize-image-intensities [0.01,0.99]',
            '--initial-moving-transform [%s,%s,1]' %
            (fixed.path, moving.path),  #1 indicates center of mass
            '--transform Translation[0.1]',
            '--metric MI[%s,%s,1,32,Regular,0.25]' % (fixed.path, moving.path),
            '--convergence [1000x500x250x0,1e-6,10]',
            '--shrink-factors 12x8x4x2',
            '--smoothing-sigmas 4x3x2x1vox'
        ],
        log_file=os.path.join(output_dir, "join_sections.log"))

    return Result(stages=Stages([stage]), output=(transform))
def deep_segment(
    image: FileAtom,
    deep_segment_pipeline: FileAtom,
    anatomical_suffix: str,
    count_suffix: str,
    outline_suffix: str = None,
    cell_min_area: int = None,
    cell_mean_area: float = None,
    cell_max_area: int = None,
    temp_dir: str = None,
):
    anatomical = image.newname_with_suffix("_" + anatomical_suffix)
    count = image.newname_with_suffix("_" + count_suffix)
    outline = image.newname_with_suffix(
        "_" + outline_suffix) if outline_suffix else None
    stage = CmdStage(inputs=(image, deep_segment_pipeline),
                     outputs=(anatomical, count),
                     cmd=['deep_segment.py',
                          '--segment-intensity 1',
                          '--temp-dir %s' % temp_dir if temp_dir else "",
                          '--learner %s' % deep_segment_pipeline.path,
                          '--image %s' % image.path,
                          '--image-output %s' % anatomical.path,
                          '--centroids-output %s' % count.path,
                          '--outlines-output %s' % outline.path if outline_suffix else ""
                          '--cell-min-area %s' % cell_min_area if cell_min_area else "",
                          '--process-clusters --cell-mean-area %s --cell-max-area %s' % (cell_mean_area, cell_max_area)\
                              if (cell_mean_area and cell_max_area) else ""
                          ])
    return Result(stages=Stages([stage]), output=(anatomical, count, outline))
Пример #6
0
    def blur(img, fwhm, gradient=True, subdir='tmp'):
        # note c3d can take voxel rather than fwhm specification, but the Algorithms interface
        # currently doesn't allow this to be used ... maybe an argument from switching from mincblur
        if fwhm in (-1, 0, None):
            if gradient:
                raise ValueError(
                    "can't compute gradient without a positive FWHM")
            return Result(stages=Stages(), output=Namespace(img=img))

        if gradient:
            out_gradient = img.newname_with("_blur%s_grad" % fwhm)
        else:
            out_gradient = None

        out_img = img.newname_with("_blurred%s" % fwhm)

        cmd = CmdStage(cmd=[
            'c3d', '-smooth',
            "%smm" % fwhm, '-o', out_img.path, img.path
        ] + (['-gradient', '-o', out_gradient.path] if gradient else []),
                       inputs=(img),
                       outputs=(out_img, out_gradient) if gradient else
                       (out_img, ))
        return Result(stages=Stages((cmd, )),
                      output=Namespace(img=out_img, gradient=out_gradient)
                      if gradient else Namespace(img=out_img))
def crop_to_brain(img: MincAtom,
                  cropped_img: MincAtom,
                  crop_to_brain_options):

    stage = CmdStage(inputs=(img,), outputs=(cropped_img,), memory=4,
                     cmd=['crop_to_brain.py',
                          '--bbox_x',str(crop_to_brain_options.bbox_x),
                          '--bbox_y',str(crop_to_brain_options.bbox_y),
                          '--bbox_z',str(crop_to_brain_options.bbox_z),
                          '--intermediate_bbox=1.5',
                          '--buffer_z',str(crop_to_brain_options.buffer_z),
                          '--clobber',
                          img.path, cropped_img.path])
    print(stage.render())
    stage.set_log_file(log_file_name=os.path.join(img.pipeline_sub_dir,"crop_to_brain.log"))

    return Result(stages=Stages([stage]), output=cropped_img)
Пример #8
0
def as_deformation(xfm):
    c = CmdStage(cmd=[
        "transformix", "-def", "all", "-out", dirname, "-tp", xfm.path, "-xfm",
        out_path
    ],
                 inputs=(xfm, ),
                 outputs=NotImplemented)
    return Result(stages=Stages([c]), output=NotImplemented)
Пример #9
0
 def scale_transform(xfm, scale, newname_wo_ext):
     scaled_xfm = xfm.newname_with_suffix("_scaled%s" % scale)
     c = CmdStage(
         cmd=["dramms-defop", "-m",
              str(scale), xfm.path, scaled_xfm.path],
         inputs=(xfm, ),
         outputs=(scaled_xfm, ))
     return Result(stages=Stages([c]), output=scaled_xfm)
Пример #10
0
def smooth_vector(source: MincAtom, fwhm: float) -> Result[MincAtom]:
    outf = source.newname_with_suffix(
        "_smooth_fwhm%s" % fwhm, subdir="tmp")  # TODO smooth_displacement_?
    cmd = [
        'smooth_vector', '--clobber', '--filter',
        '--fwhm=%s' % fwhm, source.path, outf.path
    ]
    stage = CmdStage(inputs=(source, ), outputs=(outf, ), cmd=cmd)
    return Result(stages=Stages([stage]), output=outf)
 def set_params(stage: CmdStage):
     img_pyminc = pyminc.volumeFromFile(img.path)
     ref_pyminc = pyminc.volumeFromFile(ref.path)
     count = np.maximum(ref_pyminc.data.count, img_pyminc.data.count)
     sum = ref_pyminc.data.count[0] + img_pyminc.data.count[0]
     for index, arg in enumerate(stage.cmd):
         stage.cmd[index] = arg.format(start='0,0,0,',
                                       count='%s,%s,%s' %
                                       (sum, count[1], count[2]))
Пример #12
0
def surface_mask2(input: MincAtom,
                  surface: FileAtom,
                  args: List[str] = []) -> Result[MincAtom]:
    mask_vol = surface.newname_with_suffix("_mask", ext=".mnc")
    stage = CmdStage(inputs=(input, surface),
                     outputs=(mask_vol, ),
                     cmd=["surface_mask2", "-clobber"] + args +
                     [input.path, surface.path, mask_vol.path])
    return Result(stages=Stages([stage]), output=mask_vol)
Пример #13
0
    def register(
            source: MincAtom,
            target: MincAtom,
            conf: Conf,
            initial_source_transform: Optional[XfmAtom] = None,
            transform_name_wo_ext: str = None,
            generation: int = None,  # not used; remove from API (fix ANTS)
            resample_source: bool = False,
            resample_subdir: str = "resampled") -> Result[XfmHandler]:
        if conf is None:
            raise ValueError("no configuration supplied")

        out_dir = os.path.join(
            source.pipeline_sub_dir, source.output_sub_dir,
            "%s_elastix_to_%s" %
            (source.filename_wo_ext, target.filename_wo_ext))

        # elastix chooses this for us:
        out_img = NiiAtom(
            name=os.path.join(out_dir, "result.%d.mnc" %
                              0),  # TODO number of param files ?!?!
            pipeline_sub_dir=source.pipeline_sub_dir,
            output_sub_dir=source.output_sub_dir)
        #out_xfm = XfmAtom(name = "%s_elastix_to_%s.xfm" % (source.filename_wo_ext, target.filename_wo_ext),
        #                  pipeline_sub_dir=source.pipeline_sub_dir, output_sub_dir=source.output_sub_dir)
        out_xfm = XfmAtom(
            name=os.path.join(out_dir, "TransformParameters.%d.txt" %
                              0),  # TODO number of param files ?!?!
            pipeline_sub_dir=source.pipeline_sub_dir,
            output_sub_dir=source.output_sub_dir)
        cmd = (['elastix', '-f', source.path, '-m', target.path] +
               (flatten(*[["-p", x] for x in conf])) +
               (["-fMask", source.mask.path] if source.mask else []) +
               (["-mMask", target.mask.path] if target.mask else []) +
               (["-t0", initial_source_transform.path]
                if initial_source_transform else []) + (["-out", out_dir]))
        s = CmdStage(cmd=cmd,
                     inputs=(source, target) +
                     ((source.mask, ) if source.mask else
                      ()) + ((target.mask, ) if target.mask else ()),
                     outputs=(out_xfm, out_img))

        #s2 = CmdStage(cmd=['transformix', '-out', os.path.join(resample_subdir, "%s" % c),
        #                   "-tp", out_xfm, "-in", out_name],
        #              inputs=(), outputs=())

        xfm = XfmHandler(source=source,
                         target=target,
                         xfm=out_xfm,
                         resampled=out_img)
        return Result(stages=Stages([s]), output=xfm)


# one question is whether we should have separate NLIN/LSQ12/LSQ6 interfaces or not, given that these differences seem
# like they should be rather irrelevant to general registration procedures ... at present minctracc
# is the main difficulty, since it uses different
def concat_xfm(xfms: List[XfmAtom], outxfm: XfmAtom, output_dir: str):
    stage = CmdStage(inputs=tuple(xfms),
                     outputs=(outxfm, ),
                     cmd=[
                         'xfmconcat', '-clobber',
                         ' '.join(xfm.path for xfm in xfms.__iter__()),
                         outxfm.path
                     ],
                     log_file=os.path.join(output_dir, "join_sections.log"))
    return Result(stages=Stages([stage]), output=(outxfm))
Пример #15
0
def dramms_invert(defs: DrammsXfmAtom,
                  out_defs: Optional[DrammsXfmAtom] = None):
    out_defs = out_defs or defs.newname_with_suffix("_inverted")

    return Result(stages=Stages([
        CmdStage(cmd=['dramms-defop', '-i', defs.path, out_defs.path],
                 inputs=(defs, ),
                 outputs=(out_defs, ))
    ]),
                  output=out_defs)
Пример #16
0
def itk_convert_xfm(xfm: ITKXfmAtom, out_ext: str) -> Result[ITKXfmAtom]:
    if xfm.ext == out_ext:
        return Result(stages=Stages(), output=xfm)
    else:
        out_xfm = xfm.newext(out_ext)
        cmd = CmdStage(
            inputs=(xfm, ),
            outputs=(out_xfm, ),
            cmd=["itk_convert_xfm", "--clobber", xfm.path, out_xfm.path])
        return Result(stages=Stages((cmd, )), output=out_xfm)
Пример #17
0
def transform_objects(
        input_obj: FileAtom,
        xfm: XfmAtom) -> Result[FileAtom]:  # XfmAtom -> XfmHandler??
    output_obj = input_obj.newname_with_suffix("_resampled_via_%s" %
                                               xfm.filename_wo_ext)
    stage = CmdStage(
        inputs=(input_obj, xfm),
        outputs=(output_obj, ),
        cmd=["transform_objects", input_obj.path, xfm.path, output_obj.path])
    return Result(stages=Stages([stage]), output=output_obj)
Пример #18
0
def reconstitute_laplacian_grid(cortex: MincAtom, grid: MincAtom,
                                midline: MincAtom) -> Result[MincAtom]:
    output_grid = grid.newname_with_suffix("_reconstituted")
    stage = CmdStage(inputs=(cortex, grid, midline),
                     outputs=(output_grid, ),
                     cmd=[
                         "reconstitute_laplacian_grid", midline.path,
                         cortex.path, grid.path, output_grid.path
                     ])
    return Result(stages=Stages([stage]), output=output_grid)
def mincmath(imgs: List[MincAtom], result: MincAtom, output_dir: str):
    stage = CmdStage(inputs=tuple(imgs),
                     outputs=(result, ),
                     cmd=[
                         'mincmath', '-clobber', '-add',
                         ' '.join(img.path for img in imgs.__iter__()),
                         result.path
                     ],
                     log_file=os.path.join(output_dir, "join_sections.log"))
    return Result(stages=Stages([stage]), output=result)
def varian_recon_ge3dmice_saddle(fids: List[FileAtom],
                                 imgs: List[MincAtom],
                                 varian_recon_options,
                                 output_dir: str):

    stage = CmdStage(inputs=tuple(fids), outputs=tuple(imgs), memory=25,
                     cmd=['mri_recon.py', 'ge3dmice_sg_cylA' , '--petable_ordered_pairs', '--grappa_coil_decouple',
                          '--outputreps', '--phasedriftcorr',
                          '--mouse_list',varian_recon_options.mouse_list,
                          '--petable',varian_recon_options.petable,
                          '--grappa_coil_groupings',varian_recon_options.grappa_coil_groupings,
                          '--procpar_file_name', varian_recon_options.procpar_file_name,
                          '--clobber', '--fermi_ellipse' if varian_recon_options.fermi_ellipse else '',
                          varian_recon_options.fid_input_directory,
                          os.path.join(output_dir,varian_recon_options.output_file_name)])
    print(stage.render())
    stage.set_log_file(log_file_name=os.path.join(output_dir,"varian_recon.log"))

    return Result(stages=Stages([stage]), output=imgs)
Пример #21
0
def dramms_combine(t1: DrammsXfmAtom,
                   t2: DrammsXfmAtom,
                   name: Optional[str] = None):
    # TODO this is a hack ... implement more sane naming (factor from xfmconcat?)
    out_xfm = t1.newname(name="concat_of_%s_and_%s" %
                         (t1.filename_wo_ext, t2.filename_wo_ext),
                         subdir="transforms")
    s = CmdStage(cmd=['dramms-combine', '-c', t1.path, t2.path, out_xfm.path],
                 inputs=(t1, t2),
                 outputs=(out_xfm))
    return Result(stages=Stages([s]), output=out_xfm)
Пример #22
0
def itk_to_dramms(xfm: ITKXfmAtom) -> Result[DrammsXfmAtom]:
    out_xfm = xfm.newname_with_suffix("_dramms")
    return Result(stages=Stages([
        CmdStage(cmd=[
            'dramms-convert', '-f', 'ITK', '-i', xfm.path, '-F', 'DRAMMS',
            '-o', out_xfm.path
        ],
                 inputs=(xfm, ),
                 outputs=(out_xfm, ))
    ]),
                  output=out_xfm)
Пример #23
0
def convert(infile: ImgAtom, out_ext: str) -> Result[ImgAtom]:
    s = Stages()
    outfile = infile.newext(ext=out_ext)
    if infile.mask is not None:
        outfile.mask = s.defer(convert(infile.mask, out_ext=out_ext))
    if infile.labels is not None:
        outfile.mask = s.defer(convert(infile.labels, out_ext=out_ext))
    s.add(
        CmdStage(inputs=(infile, ),
                 outputs=(outfile, ),
                 cmd=['c3d', infile.path, '-o', outfile.path]))
    return Result(stages=s, output=outfile)
Пример #24
0
def average_images(
        imgs: Sequence[ImgAtom],
        dimensions: int = 3,
        normalize: bool = False,
        output_dir: str = '.',
        name_wo_ext: str = "average",
        out_ext: Optional[str] = None,
        avg_file: Optional[ITKImgAtom] = None) -> Result[ITKImgAtom]:

    s = Stages()

    if len(imgs) == 0:
        raise ValueError(
            "`AverageImages` arg `imgs` is empty (can't average zero files)")

    ext = out_ext or imgs[0].ext

    # the output_dir basically gives us the equivalent of the pipeline_sub_dir for
    # regular input files to a pipeline, so use that here
    avg = avg_file or ImgAtom(name=os.path.join(output_dir,
                                                '%s.todo' % name_wo_ext),
                              orig_name=None,
                              pipeline_sub_dir=output_dir)
    avg.ext = ext

    # if all input files have masks associated with them, add the combined mask to
    # the average:
    # TODO what if avg_file has a mask ... should that be used instead? (then rename avg -> avg_file above)
    all_inputs_have_masks = all((img.mask for img in imgs))
    if all_inputs_have_masks:
        combined_mask = (ImgAtom(name=os.path.join(
            avg_file.dir, '%s_mask.todo' % avg_file.filename_wo_ext),
                                 orig_name=None,
                                 pipeline_sub_dir=avg_file.pipeline_sub_dir)
                         if avg_file is not None else ImgAtom(
                             name=os.path.join(output_dir, '%s_mask.todo' %
                                               name_wo_ext),
                             orig_name=None,
                             pipeline_sub_dir=output_dir))
        combined_mask.ext = ext
        s.defer(
            max(imgs=sorted({img_inst.mask
                             for img_inst in imgs}),
                out_img=combined_mask))
        avg.mask = combined_mask
    s.add(
        CmdStage(
            inputs=imgs,
            outputs=(avg, ),
            cmd=["AverageImages",
                 str(dimensions), avg.path,
                 "%d" % normalize] + [img.path for img in imgs]))
    return Result(stages=s, output=avg)
Пример #25
0
 def average_transforms(xfms, avg_xfm):
     intermediate_xfm = avg_xfm.newname_with_suffix("_inter", subdir="tmp")
     s = Stages()
     s.add(
         CmdStage(cmd=[
             "echo",
             ('(Transform "WeightedCombinationTransform")\n'
              '(SubTransforms %s)\n'
              '(NormalizeCombinationsWeights "true")\n') %
             ' '.join(sorted(xfm.path for xfm in xfms))
         ],
                  inputs=xfms,
                  outputs=(intermediate_xfm, )))
     s.add(
         CmdStage(cmd=[
             "transformix", "-def", "all", "-out",
             os.path.dirname(avg_xfm.path), "-tp", intermediate_xfm.path,
             "-xfm", avg_xfm.path
         ],
                  inputs=(intermediate_xfm, ),
                  outputs=(avg_xfm, )))
Пример #26
0
 def scale_transform(xfm, scale):
     scaled_xfm = xfm.newname_with_suffix("_scaled_%s" % scale)
     # don't actually evaluate the resulting vector field:
     s = CmdStage(cmd=[
         "echo",
         ('(Transform "WeightedCombinationTransform")\n'
          '(SubTransforms %s)\n'
          '(Scales %s)\n') % (xfm.path, scale)
     ],
                  inputs=(xfm, ),
                  outputs=(scaled_xfm, ))
     return Result(stages=Stages([s]), output=scaled_xfm)
Пример #27
0
 def scale_transform(xfm, scale, newname_wo_ext):
     s = Stages()
     defs = s.defer(as_deformation(transform=xfm.xfm, reference=xfm.source))
     scaled_defs = (defs.xfm.newname(newname_wo_ext) if newname_wo_ext else
                    defs.xfm.newname_with_suffix("_scaled_%s" % scale))
     s.defer(
         CmdStage(cmd=[
             'c3d', '-scale',
             str(scale), defs.path, "-o", scaled_defs.path
         ],
                  inputs=(defs, ),
                  outputs=(scaled_defs, )))
     return Result(stages=s, output=scaled_defs)
Пример #28
0
def lin_from_nlin(xfm: XfmHandler) -> Result[XfmHandler]:
    # TODO add dir argument
    out_xfm = xfm.xfm.newname_with_suffix("_linear_part", subdir="tmp")
    stage = CmdStage(
        inputs=(xfm.source, xfm.xfm),
        outputs=(out_xfm, ),
        cmd=(['lin_from_nlin', '-clobber', '-lsq12'] +
             (['-mask', xfm.source.mask.path] if xfm.source.mask else []) +
             [xfm.target.path, xfm.xfm.path, out_xfm.path]))
    return Result(stages=Stages([stage]),
                  output=XfmHandler(xfm=out_xfm,
                                    source=xfm.source,
                                    target=xfm.target))
Пример #29
0
 def to_mni_xfm(xfm):
     s = Stages()
     defs = xfm.newname_with_suffix("_defs", subdir="tmp")
     s.add(
         CmdStage(cmd=[
             "transformix", "-def", "all", "-out", defs.dir, "-tp",
             xfm.path, "-xfm",
             os.path.join(defs.filename_wo_ext, defs.ext)
         ],
                  inputs=(xfm, ),
                  outputs=(defs, )))
     out_xfm = s.defer(itk.itk_convert_xfm(defs, out_ext=".mnc"))
     return Result(stages=s, output=out_xfm)
def TV_stitch_wrap(brain_directory: FileAtom, brain_name: str,
                   slice_directory: str, TV_stitch_options, Zstart: int,
                   Zend: int, output_dir: str):
    #TODO inputs should be tiles not just brain_directory
    stitched = []
    for z in range(Zstart, Zend + 1):
        slice_stitched = FileAtom(
            os.path.join(slice_directory, brain_name + "_Z%04d.tif" % z))
        stitched.append(slice_stitched)

    stage = CmdStage(
        inputs=(brain_directory, ),
        outputs=tuple(stitched),
        cmd=[
            'TV_stitch.py',
            '--clobber',
            #'--verbose',
            '--Zstart %s' % Zstart,
            '--Zend %s' % Zend,
            '--save_positions_file %s_positions.txt' %
            os.path.join(stitched[0].dir, brain_name + '_Zstart' + str(Zstart))
            if TV_stitch_options.save_positions_file else "",
            '--keeptmp' if TV_stitch_options.keep_tmp else "",
            '--scaleoutput %s' % TV_stitch_options.scale_output
            if TV_stitch_options.scale_output else '',
            # '--skip_tile_match' if TV_stitch_options.skip_tile_match else '',
            # '--Ystart %s' % TV_stitch_options.Ystart if TV_stitch_options.Ystart else '',
            # '--Yend %s' % TV_stitch_options.Yend if TV_stitch_options.Yend else '',
            # '--Xstart %s' % TV_stitch_options.Xstart if TV_stitch_options.Xstart else '',
            # '--Xend %s' % TV_stitch_options.Xend if TV_stitch_options.Xend else '',
            # '--nogradimag' if TV_stitch_options.no_gradient_image else '',
            # '--use_positions_file %s' % TV_stitch_options.use_positions_file
            # if TV_stitch_options.use_positions_file else '',
            # '--overlapx %s' % TV_stitch_options.overlapx if TV_stitch_options.overlapx else '',
            # '--overlapy %s' % TV_stitch_options.overlapy if TV_stitch_options.overlapy else '',
            # '--channel %s' % TV_stitch_options.channel if TV_stitch_options.channel else '',
            # '--Zref %s' % TV_stitch_options.Zref if TV_stitch_options.Zref else '',
            # '--Zstack_pzIcorr' if TV_stitch_options.inormalize_piezo_stack else '',
            # '--fastpiezo' if TV_stitch_options.fast_piezo else '',
            # '--short' if TV_stitch_options.short_int else '',
            # '--file_type %s' % TV_stitch_options.use_positions_file if TV_stitch_options.use_positions_file else '',
            # '--TV_file_type %s' % TV_stitch_options.use_positions_file if TV_stitch_options.use_positions_file el
            # '--use_IM' if TV_stitch_options.use_imagemagick else '',
            os.path.join(brain_directory.path, brain_name),
            os.path.join(stitched[0].dir, brain_name)
        ],
        log_file=os.path.join(output_dir, "TV_stitch.log"))

    return Result(stages=Stages([stage]), output=(stitched))