def test_applywarp(): with asrt.disabled(), run.dryrun(), mockFSLDIR( bin=('applywarp', )) as fsldir: applywarp = op.join(fsldir, 'bin', 'applywarp') result = fw.applywarp('src', 'ref', 'out', warp='warp', abs=True, super=True) expected = (applywarp + ' --in=src --ref=ref --out=out', ('--warp=warp', '--abs', '--super')) assert checkResult(result.stdout[0], *expected)
def apply_transform(cls, reg_data, transform, options, queue): """ Apply a previously calculated transformation to a data set """ output_space = options.pop("output-space", "ref") if output_space not in ("ref", "reg"): raise QpException( "FNIRT does not support output in transformed space") from fsl import wrappers as fsl reg = qpdata_to_fslimage(reg_data) trans = qpdata_to_fslimage(transform) # Applywarp generates an output for each volume of reference image # for some reason. So use just the first volume of the transform # as the reference space ref = qpdata_to_fslimage(transform.volume(0, qpdata=True)) log = six.StringIO() order = options.pop("interp-order", 1) interp = _interp(order) apply_output = fsl.applywarp(reg, ref, interp=interp, paddingsize=1, super=True, superlevel="a", out=fsl.LOAD, log={ "cmd": log, "stdout": log, "stderr": log }, warp=trans, rel=True) qpdata = fslimage_to_qpdata(apply_output["out"], name=reg_data.name) if output_space == "ref": # Default is to output in reference space pass else: qpdata = qpdata.resample(reg_data.grid, suffix="", order=order) log += "Resampling onto input grid\n" return qpdata, log.getvalue()
def _transform(img, warp, ref, premat=None, postmat=None, interp="trilinear", paddingsize=1, output_is_roi=False, output_roi_thresh=0.5): """ Transform an image :param img: fsl.data.Image containing image to transform :param warp: Transformation matrix or warp image :param ref: fsl.data.Image containing reference image :param premat: Optional Pre-warp affine transformation matrix :param premat: Optional Post-warp affine transformation matrix :param interp: Interpolation method :param paddingsize: Padding size in pixels :param output_is_roi: Output should be binarized as an ROI :param output_roi_threshold: Thresholding value for binarizing output ROI :return: fsl.data.Image containing transformed image """ kwargs = { "warp": warp, "premat": premat, "postmat": postmat, "rel": True, "super": True, "superlevel": "a", "interp": interp, "paddingsize": paddingsize, } ret = fsl.applywarp(img, ref, out=fsl.LOAD, **kwargs)["out"] if output_is_roi: # Binarise mask images ret = Image((ret.data > output_roi_threshold).astype(np.int), header=ret.header) return ret
def transform(wsp, img, trans, ref, use_flirt=False, interp="trilinear", paddingsize=1, premat=None, mask=False, mask_thresh=0.5): """ Transform an image :param wsp: Workspace, used for logging only :param img: Image to transform :param trans: Transformation matrix or warp image :param ref: Reference image :param use_flirt: Use flirt to apply the transformation which must be a matrix :param interp: Interpolation method :param paddingsize: Padding size in pixels :param premat: If trans is a warp, this can be set to a pre-warp affine transformation matrix :return: Transformed Image object """ if trans is None: raise ValueError("Transformation matrix not available - has registration been performed?") have_warp = isinstance(trans, Image) if use_flirt and have_warp: raise ValueError("Cannot transform using Flirt when we have a warp") elif use_flirt: if interp == "nn": interp = "nearestneighbour" ret = fsl.applyxfm(img, ref, trans, out=fsl.LOAD, interp=interp, paddingsize=paddingsize, log=wsp.fsllog)["out"] else: if have_warp: kwargs = {"warp" : trans, "premat" : premat, "rel" : True} elif premat: raise ValueError("Can't set a pre-transformation matrix unless using a warp") else: kwargs = {"premat" : trans} ret = fsl.applywarp(img, ref, out=fsl.LOAD, interp=interp, paddingsize=paddingsize, super=True, superlevel="a", log=wsp.fsllog, **kwargs)["out"] if mask: # Binarise mask images ret = Image((ret.data > mask_thresh).astype(np.int), header=ret.header) return ret
def epi_reg(wsp, epi_img, use_fmap=False, **kwargs): """ Do EPI registration """ struc.segment(wsp) wmseg = wsp.structural.wm_seg bbr_sch = os.path.join(os.environ["FSLDIR"], "etc/flirtsch/bbr.sch") if wsp.asl2struc is None: # Do pre-alignment in the same was as epi_reg wsp.asl2struc = fsl.flirt(epi_img, ref=wsp.structural.brain, omat=fsl.LOAD, dof=6, log=wsp.fsllog)["omat"] if not use_fmap: wsp.log.write(" - Running BBR\n") trans = fsl.flirt(epi_img, ref=wsp.structural.struc, dof=6, cost="bbr", wmseg=wmseg, init=wsp.asl2struc, omat=fsl.LOAD, out=fsl.LOAD, schedule=bbr_sch, log=wsp.fsllog)["omat"] out_img = fsl.applywarp(epi_img, ref=wsp.structural.struc, out=fsl.LOAD, premat=trans, interp="spline", log=wsp.fsllog)["out"] return {"out.nii.gz": out_img, "out": trans} else: dirmap = { "x": (1, "x"), "y": (2, "y"), "z": (3, "z"), "-x": (-1, "x-"), "-y": (-2, "y-"), "-z": (-3, "z-"), "x-": (-1, "x-"), "y-": (-2, "y-"), "z-": (-3, "z-"), } pedir, fdir = dirmap.get(wsp.pedir, (None, None)) if pedir is None: raise ValueError("Invalid phase encode direction specified: %s" % wsp.pedir) if wsp.nofmapreg: wsp.fmap2struc = np.identity(4) wsp.fmapmag_struc = wsp.fmapmag else: # Register fmap to structural image wsp.log.write(" - Registering fieldmap to structural\n") wsp.fmap2struc = fsl.flirt(wsp.fmapmagbrain, ref=wsp.structural.brain, dof=6, omat=fsl.LOAD)["omat"] flirt_result = fsl.flirt(wsp.fmapmag, ref=wsp.structural.struc, dof=6, init=wsp.fmap2struc, omat=fsl.LOAD, out=fsl.LOAD, nosearch=True) wsp.fmap2struc = flirt_result["omat"] wsp.fmapmag_struc = flirt_result["out"] # Unmask the fieldmap (necessary to avoid edge effects) wsp.fmap_mask = fsl.fslmaths(wsp.fmapmagbrain).abs().bin().run() wsp.fmap_mask = fsl.fslmaths(wsp.fmap).abs().bin().mul( wsp.fmap_mask).run() # The direction here should take into account the initial affine (it needs to be the direction in the EPI) wsp.fmap_unmasked = fsl.fugue(loadfmap=wsp.fmap, mask=wsp.fmap_mask, unmaskfmap=True, savefmap=fsl.LOAD, unwarpdir=fdir)["out"] # The following is a NEW HACK to fix extrapolation when fieldmap is too small wsp.fmap_struc_pad0 = fsl.applywarp(wsp.fmap_unmasked, ref=wsp.structural.struc, premat=wsp.fmap2struc, out=fsl.LOAD)["out"] wsp.fmap_struc_innermask = fsl.fslmaths( wsp.fmap_struc_pad0).abs().bin().run() wsp.fmap_struc_dilated = fsl.fugue(loadfmap=wsp.fmap_struc_pad0, mask=wsp.fmap_struc_innermask, unmaskfmap=True, unwarpdir=fdir, savefmap=fsl.LOAD)["savefmap"] wsp.fmap_struc = wsp.fmap_struc_dilated # Run bbr with fieldmap wsp.log.write("Running BBR with fieldmap\n") if not wsp.epi_reg_use_weighting: refweight = None wsp.reg.epi2struc = fsl.flirt(epi_img, ref=wsp.structural.struc, dof=6, cost="bbr", wmseg=wmseg, init=wsp.reg.asl2struc, omat=fsl.LOAD, schedule=bbr_sch, echospacing=wsp.echospacing, pedir=pedir, fieldmap=wsp.fmap_struc, refweight=refweight)["omat"] # Make equivalent warp fields wsp.log.write( "Making warp fields and applying registration to EPI series\n") wsp.reg.struc2epi = np.linalg.inv(wsp.reg.epi2struc) fsl.concatxfm(wsp.reg.struc2epi, wsp.fmap2struc, outmat=fsl.LOAD) fsl.applywarp(wsp.fmap, ref=epi_img, premat=wsp.fmap2epi, out=fsl.LOAD) wsp.fmap2epi_mask = fsl.fslmaths(wsp.fmap2epi).abs().bin().run() # ${vout}_fieldmaprads2epi -abs -bin ${vout}_fieldmaprads2epi_mask ret = fsl.fugue(loadfmap=wsp.fmap2epi, mask=wsp.fmap2epi_mask, saveshift=fsl.LOAD, unmaskshift=True, dwell=wsp.dwell, unwarpdir=fdir) print(ret) wsp.fmap2epi_shift = ret["fieldmaprads2epi_shift"] ret = fsl.convertwarp(wsp.structural.struc, s=wsp.fmap2epi_shift, postmat=wsp.epi2struc, out=fsl.LOAD, shiftdir=fdir, relout=True) print(ret) warp = ret["out"] ret = fsl.applywarp(epi_img, ref=wsp.structural.struc, out=fsl.LOAD, warp1=warp, interp="spline", rel=True) print(ret) return ret["out"], warp