Esempio n. 1
0
def test_pvc():
    """
    FIXME we need to test the PVC initialization step
    and how to do this is not finalized
    """
    d = np.random.rand(5, 5, 5, 6)
    img = AslImage(name="asldata", image=d, tis=[1.5], order="prt")
    wsp = Workspace(infertiss=True, inferbat=True)

    wsp.pgm = Image(np.random.rand(5, 5, 5))
    wsp.pwm = Image(np.random.rand(5, 5, 5))

    steps = basil.basil_steps(wsp, img)
    assert (len(steps) == 3)

    options = _get_defaults(img)
    #    options.update({
    #        "incpve" : True,
    #    })
    _check_step(steps[0], desc_text="tissue", options=options)
    #    _check_step(steps[1], desc_text="PVE", options=options)

    options.update({
        "method": "spatialvb",
        "param-spatial-priors": "N+",
        "PSP_byname1": "ftiss",
        "PSP_byname1_type": "M",
        "max-iterations": 200,
        "convergence": "maxits",
    })
    options.pop("max-trials")
    _check_step(steps[2], desc_text="spatial")
Esempio n. 2
0
    def parse_args(self, argv=None, values=None):
        if argv is None:
            argv = sys.argv[1:]
        options, args = OptionParser.parse_args(self, argv, values)
        if options.optfile:
            # When an option file is specifeid, extract the options, build
            # a new argv vector and re-parse it. This is the only way to ensure
            # that options in the file work identically to CLI options.
            new_argv = self._add_from_file(argv, options.optfile)
            options, args = OptionParser.parse_args(self, new_argv, values)

        # Deal with case where asldata is given as separate files
        if args and options.asldata is None:
            merged_data = None
            for idx, fname in enumerate(args):
                img = Image(fname)
                shape = list(img.shape)
                if img.ndim == 3:
                    shape += [
                        1,
                    ]
                if merged_data is None:
                    merged_data = np.zeros(shape[:3] + [shape[3] * len(args)])
                merged_data[...,
                            idx * shape[3]:(idx + 1) * shape[3]] = img.data
            merged_img = Image(merged_data, header=img.header)
            temp_asldata = tempfile.NamedTemporaryFile(prefix="oxasl",
                                                       delete=True)
            options.asldata = temp_asldata.name
            merged_img.save(options.asldata)

        return options, args
Esempio n. 3
0
def _test_getProperties(frame, overlayList, displayCtx):
    vol1 = Image(op.join(datadir, '3d.nii.gz'), name='vol1')
    vol2 = Image(op.join(datadir, '3d.nii.gz'), name='vol2')
    mesh = GiftiMesh(op.join(datadir, 'gifti', 'white.surf.gii'))

    overlayList.extend([vol1, vol2, mesh])

    displayCtx.getDisplay(vol1).alpha = 97
    displayCtx.getOpts(vol1).clipImage = vol2

    vprops = ftman.getProperties(vol1, displayCtx)
    assert vprops['alpha'] == 97
    assert vprops['interpolation'] == 'none'
    assert 'transform' not in vprops
    ci = vprops['clipImage']
    assert isinstance(ci, ftman.ToReplace) and ci.value == 'vol2'

    vprops = ftman.getProperties(vol2, displayCtx)
    assert vprops['alpha'] == 100
    assert vprops['interpolation'] == 'none'
    assert 'transform' not in vprops
    assert 'clipImage' not in vprops

    displayCtx.getDisplay(mesh).alpha = 43

    mprops = ftman.getProperties(mesh, displayCtx)
    assert mprops['alpha'] == 43
    assert 'refImage' not in mprops

    displayCtx.getOpts(mesh).refImage = vol1
    mprops = ftman.getProperties(mesh, displayCtx)
    assert mprops['alpha'] == 43
    ri = mprops['refImage']
    assert isinstance(ri, ftman.ToReplace) and ri.value == 'vol1'
Esempio n. 4
0
    def run(self, prev_output, log=sys.stdout, fsllog=None, **kwargs):
        """
        Update the MVN from a previous step to include initial estimates
        for PVC parameters
        """
        log.write("Initialising partial volume correction...\n")
        mask = self.options["mask"]
        # set the inital GM amd WM values using a simple PV correction
        wm_cbf_ratio = 0.4

        # Modified pvgm map
        temp_pgm = np.copy(self.options["pgm"].data)
        temp_pgm[temp_pgm < 0.2] = 0.2

        # First part of correction psuedo WM CBF term
        prev_ftiss = prev_output["mean_ftiss"].data
        wm_cbf_term = (prev_ftiss * wm_cbf_ratio) * self.options["pwm"].data

        gmcbf_init = (prev_ftiss - wm_cbf_term) / temp_pgm
        wmcbf_init = gmcbf_init * wm_cbf_ratio

        mvn = prev_output["finalMVN"]
        gmcbf_init = Image(gmcbf_init, header=mvn.header)
        wmcbf_init = Image(wmcbf_init, header=mvn.header)

        # load these into the MVN
        mvn = prev_output["finalMVN"]
        from .wrappers import mvntool
        params = prev_output["paramnames"]
        mvn = mvntool(mvn, params.index("ftiss")+1, output=LOAD, mask=mask, write=True, valim=gmcbf_init, var=0.1, log=fsllog)["output"]
        mvn = mvntool(mvn, params.index("fwm")+1, output=LOAD, mask=mask, write=True, valim=wmcbf_init, var=0.1, log=fsllog)["output"]
        log.write("DONE\n")
        return {"finalMVN" : mvn, "gmcbf_init" : gmcbf_init, "wmcbf_init" : wmcbf_init}
Esempio n. 5
0
def single_volume(wsp, img, moco=True, discard_first=True):
    """
    Convert a potentially 4D image into a single 3D volume

    :param moco: If True, perform basic motion correction
    :param discard_first: If True, discard first volume if nvols > 1

    """
    if img is not None:
        wsp.log.write(" - Pre-processing image: %s\n" % img.name)
        if img.ndim == 4:
            if discard_first and img.shape[3] > 1:
                wsp.log.write(
                    "   - Removing first volume to ensure data is in steady state\n"
                )
                img = Image(img.data[..., :-1], header=img.header)

            if moco and img.shape[3] > 1:
                if moco:
                    wsp.log.write("   - Motion correcting\n")
                    img = fsl.mcflirt(img, out=fsl.LOAD, log=wsp.fsllog)["out"]

            wsp.log.write("   - Taking mean across time axis\n")
            img = Image(np.mean(img.data, axis=-1), header=img.header)

        return img
    else:
        return None
def _test_SelectionActions(ortho, overlayList, displayCtx):
    img1 = Image(np.random.randint(1, 65536, (20, 20, 20)))
    img2 = Image(np.random.randint(1, 65536, (20, 20, 20)))
    overlayList[:] = [img1, img2]
    displayCtx.selectOverlay(img1)
    idle.block(2)
    ortho.profile = 'edit'
    idle.block(2)
    profile = ortho.getCurrentProfile()
    profile.mode = 'sel'
    profile.drawMode = False
    idle.block(2)
    ed = profile.editor(img1)

    # clear
    ed.getSelection().addToSelection(np.ones((4, 4, 4)), offset=(8, 8, 8))
    idle.block(2)
    profile.clearSelection()
    assert np.all(ed.getSelection().getSelection() == 0)

    # fill
    ed.getSelection().addToSelection(np.ones((4, 4, 4)), offset=(8, 8, 8))
    idle.block(2)
    profile.fillValue = 999
    profile.fillSelection()
    exp = np.copy(img1[:])
    exp[8:12, 8:12, 8:12] = 999
    assert np.all(img1[:] == exp)

    # erase
    profile.clearSelection()
    ed.getSelection().addToSelection(np.ones((4, 4, 4)), offset=(3, 3, 3))
    idle.block(2)
    profile.eraseValue = -999
    profile.eraseSelection()
    exp = np.copy(img1[:])
    exp[3:7, 3:7, 3:7] = -999
    assert np.all(img1[:] == exp)

    # invert
    ed.getSelection().addToSelection(np.ones((4, 4, 4)), offset=(8, 8, 8))
    idle.block(2)
    profile.invertSelection()
    exp = np.ones(img1.shape)
    exp[8:12, 8:12, 8:12] = 0
    assert np.all(ed.getSelection().getSelection() == exp)

    # copy+paste
    profile.clearSelection()
    ed.getSelection().addToSelection(np.ones((4, 4, 4)), offset=(8, 8, 8))
    displayCtx.selectOverlay(img2)
    profile.copySelection()
    displayCtx.selectOverlay(img1)
    idle.block(2)
    profile.pasteSelection()
    idle.block(2)
    exp = np.copy(img1[:])
    exp[8:12, 8:12, 8:12] = img2[8:12, 8:12, 8:12]
    assert np.all(img1[:] == exp)
Esempio n. 7
0
def get_perfusion_data(outdir,
                       gm_pve_asl,
                       wm_pve_asl,
                       gm_thresh,
                       wm_thresh,
                       min_gm_thresh,
                       min_wm_thresh,
                       log=sys.stdout):
    perfusion_data = [
        {
            "suffix": "",
            "f": Image(os.path.join(outdir, "perfusion_calib")),
            "var": Image(os.path.join(outdir, "perfusion_var_calib")),
            "mask": None,
        },
    ]
    if os.path.isdir(os.path.join(outdir, "pvcorr")):
        log.write(
            " - Found partial volume corrected results - will mask ROIs using 'base' GM/WM masks (PVE thresholds: %.2f / %.2f)\n"
            % (min_gm_thresh, min_wm_thresh))
        perfusion_data.extend([
            {
                "suffix": "_gm",
                "f": Image(os.path.join(outdir, "pvcorr", "perfusion_calib")),
                "var":
                Image(os.path.join(outdir, "pvcorr", "perfusion_var_calib")),
                "mask": gm_pve_asl.data > min_gm_thresh,
            },
            {
                "suffix":
                "_wm",
                "f":
                Image(os.path.join(outdir, "pvcorr", "perfusion_wm_calib")),
                "var":
                Image(os.path.join(outdir, "pvcorr",
                                   "perfusion_wm_var_calib")),
                "mask":
                wm_pve_asl.data > min_wm_thresh,
            },
        ])
    else:
        log.write(
            " - No partial volume corrected results - will mask ROIs using 'pure' GM/WM masks (PVE thresholds: %.2f / %.2f)\n"
            % (gm_thresh, wm_thresh))
        perfusion_data.extend([
            {
                "suffix": "_gm",
                "f": Image(os.path.join(outdir, "perfusion_calib")),
                "var": Image(os.path.join(outdir, "perfusion_var_calib")),
                "mask": gm_pve_asl.data > gm_thresh,
            },
            {
                "suffix": "_wm",
                "f": Image(os.path.join(outdir, "perfusion_calib")),
                "var": Image(os.path.join(outdir, "perfusion_var_calib")),
                "mask": wm_pve_asl.data > wm_thresh,
            },
        ])
    return perfusion_data
Esempio n. 8
0
def get_tissrefmask(wsp):
    """
    Calculate a calibration reference mask for a particular known tissue type
    """
    page = wsp.report.page("auto_calib_mask")
    page.heading("Calibration reference region")
    page.text("Reference region was automatically generated for tissue type: %s" % wsp.tissref.upper())
    page.heading("Partial volume map for %s tissue (from structural segmentation)" % wsp.tissref.upper(), level=1)
    wsp.calibration.refpve = getattr(wsp.structural, "%s_pv" % wsp.tissref.lower())
    page.image("refpve", LightboxImage(wsp.calibration.refpve, bgimage=wsp.structural.brain))

    if wsp.tissref == "csf" and not wsp.csfmaskingoff:
        wsp.log.write(" - Doing automatic ventricle selection using standard atlas\n")
        # By deafult now we do FNRIT transformation of ventricle mask
        # FIXME disabled as not being used in ASL_CALIB at present
        #wsp.calibration.struc2stdfnirt = wsp.ifnone("stdmaskfnirt", True)

        # Select ventricles based on standard space atlas
        page.heading("Automatic ventricle selection", level=1)
        page.text("Standard space ventricles mask (from Harvard-Oxford atlas) eroded by 1 pixel")
        atlases = AtlasRegistry()
        atlases.rescanAtlases()
        atlas = atlases.loadAtlas("harvardoxford-subcortical", loadSummary=False, resolution=2)
        ventricles = ((atlas.data[..., 2] + atlas.data[..., 13]) > 0.1).astype(np.int)
        wsp.calibration.ventricles = Image(scipy.ndimage.binary_erosion(ventricles, structure=np.ones([3, 3, 3]), border_value=1).astype(np.int), header=atlas.header)
        std_img = Image(os.path.join(os.environ["FSLDIR"], "data", "standard", 'MNI152_T1_2mm_brain'))
        page.image("ventricles_std", LightboxImage(wsp.calibration.ventricles, bgimage=std_img))

        page.heading("Structural space ventricles mask", level=1)
        # FIXME nearest neighbour interpolation?
        wsp.calibration.ventricles_struc = reg.change_space(wsp, wsp.calibration.ventricles, "struc")
        page.text("This is the above image transformed into structural space. The transformation was obtained by registering the structural image to the standard brain image")
        page.image("ventricles_struc", LightboxImage(wsp.calibration.ventricles_struc, bgimage=wsp.structural.brain))

        wsp.log.write(" - Masking FAST output with standard space derived ventricle mask\n")
        wsp.calibration.refpve_pre_mask = wsp.calibration.refpve
        refpve_data = np.copy(wsp.calibration.refpve.data)
        refpve_data[wsp.calibration.ventricles_struc.data == 0] = 0
        wsp.calibration.refpve = Image(refpve_data, header=wsp.calibration.refpve.header)
        wsp.calibration.refpve_post = wsp.calibration.refpve

        page.heading("Structural space ventricles PVE", level=1)
        page.text("This is the CSF partial volume masked by the ventricles mask. It should select only the ventricles from the original partial volume image.")
        page.image("refpve_post", LightboxImage(wsp.calibration.refpve, bgimage=wsp.structural.brain))

    wsp.log.write(" - Transforming tissue reference mask into ASL space\n")
    # FIXME calibration image may not be in ASL space! Oxford_asl does not handle this currently
    wsp.calibration.refpve_calib = reg.change_space(wsp, wsp.calibration.refpve, "native")
    #wsp.calibration.refpve_calib.data[wsp.calibration.refpve_calib.data < 0.001] = 0 # Better for display
    page.heading("Reference region in ASL space", level=1)
    page.text("Partial volume map")
    page.image("refpve_calib", LightboxImage(wsp.calibration.refpve_calib, bgimage=wsp.calibration.calib_img))

    # Threshold reference mask conservatively to select only reference tissue
    wsp.log.write(" - Thresholding reference mask\n")
    wsp.calibration.refmask = Image((wsp.calibration.refpve_calib.data > 0.9).astype(np.int), header=wsp.calibration.refpve_calib.header)

    page.text("Reference Mask (thresholded at 0.9")
    page.image("refmask", LightboxImage(wsp.calibration.refmask, bgimage=wsp.calibration.calib_img))
Esempio n. 9
0
    def get_for_row(self, afq_object, row):
        nearest_warp, nearest_space = self.fnames[row['ses']][row['subject']]

        our_templ = afq_object.reg_template_img
        subj = Image(row['dwi_file'])
        their_templ = Image(nearest_space)
        warp = readFnirt(nearest_warp, their_templ, subj)

        return ConformedFnirtMapping(warp, our_templ.affine)
Esempio n. 10
0
def qpdata_to_fslimage(qpd, grid=None):
    """ 
    Convert QpData to fsl.data.image.Image
    """
    from fsl.data.image import Image
    if grid is None:
        return Image(qpd.raw(), name=qpd.name, xform=qpd.grid.affine)
    else:
        return Image(qpd.resample(grid), name=qpd.name, xform=grid.affine)
Esempio n. 11
0
 def img(self):
     """
     Return an Image object by loading from the file
     """
     img = Image(self._fname, loadData=False)
     if self._md:
         for key, value in self._md:
             img.setMeta(key, value)
     return img
Esempio n. 12
0
    def get_for_subses(self, subses_dict, reg_template, reg_subject):
        nearest_warp, nearest_space = self.fnames[subses_dict['ses']][
            subses_dict['subject']]

        our_templ = reg_template
        subj = Image(subses_dict['dwi_file'])
        their_templ = Image(nearest_space)
        warp = readFnirt(nearest_warp, their_templ, subj)

        return ConformedFnirtMapping(warp, our_templ.affine)
Esempio n. 13
0
def _slicetiming_correction(
    asl_name, t1_name, tis, rpts, 
    slicedt, sliceband, n_slices
    ):
    """
    Performs rescaling of ASL series, `asl_name`, accounting for 
    the estimated T1t in a given voxel, `t1_name`.

    satrecov_model: S(t) = M_0 * (1 - exp{-t/T1t})

    Divides the value in a voxel by the above model evaluated at 
    t = TI + n*slicedt where n is the slice number of the voxel 
    within a band. This accounts for the voxel being imaged at a 
    different time than its supposed TI.

    Multiplies the value in a voxel by the above model evaluated 
    at t = TI, i.e. scales the values as if they had been imaged 
    at the TI that was specified in the ASL sequence.

    Returns the slice-timing corrected ASL series, `stcorr_img`, 
    and the scaling factors used to perform the correction, 
    `stcorr_factors_img` where:
        `stcorr_factors` = S(TI) / S(TI + n*slicedt)
        `stcorr_img` = `stcorr_factors` * `asl_name`
    """
    # timing information for scan
    # supposed measurement time of slice
    tis_array = np.repeat(np.array(tis), 2*np.array(rpts)).reshape(1, 1, 1, -1)
    # actual measurment time of slice
    slice_numbers = np.tile(
        np.arange(0, sliceband),
        n_slices // sliceband
    ).reshape(1, 1, -1, 1)
    slice_times = tis_array + (slicedt * slice_numbers)
    # load images
    asl_img = Image(str(asl_name))
    t1_img = Image(str(t1_name))
    # check dimensions of t1 image to see if time series or not
    if t1_img.ndim == 3:
        t1_data = t1_img.data[..., np.newaxis]
    elif t1_img.ndim == 4:
        t1_data = t1_img.data
    # multiply asl sequence by satrecov model evaluated at TI
    numexp = - tis_array / t1_data
    num = 1 - np.exp(numexp)
    # divide asl sequence by satrecov model evaluated at actual slice-time
    denexp = - slice_times / t1_data
    den = 1 - np.exp(denexp)
    # evaluate scaling factors
    stcorr_factors = num / den
    stcorr_factors_img = Image(stcorr_factors, header=asl_img.header)
    # correct asl series
    stcorr_data = asl_img.data * stcorr_factors
    stcorr_img = Image(stcorr_data, header=asl_img.header)
    return stcorr_img, stcorr_factors_img
Esempio n. 14
0
def binarise(pve_name, threshold=0.5):
    """
    Binarise a PVE image given a threshold.

    The default threshold is 0.5, the threshold used by asl_reg 
    to obtain a white matter segmentation from a white matter 
    PVE image.
    """
    pve = Image(str(pve_name))
    seg = Image(np.where(pve.data>threshold, 1., 0.), header=pve.header)
    return seg
Esempio n. 15
0
def _get_imgs(shape=(5, 5, 5)):
    """
    Create test images
    """
    perf_d = np.random.rand(5, 5, 5)
    perf_img = Image(name="perfusion", image=perf_d)

    calib_d = np.random.rand(5, 5, 5)
    calib_img = Image(name="calib", image=calib_d)

    return perf_img, calib_img
Esempio n. 16
0
def run(wsp):
    """
    Do initialization on supplied structural data - copy relevant image and do brain extraction

    FIXME copy across all supplied structural data
    """
    wsp.log.write("\nInitialising structural data\n")
    wsp.sub("structural")

    if wsp.fslanat:
        wsp.log.write(
            " - Using FSL_ANAT output directory for structural data: %s\n" %
            wsp.fslanat)
        biascorr = os.path.join(wsp.fslanat, "T1_biascorr")
        biascorr_brain = os.path.join(wsp.fslanat, "T1_biascorr_brain")
        if glob.glob(biascorr + ".*") and glob.glob(biascorr_brain + ".*"):
            wsp.log.write(" - Using bias-corrected structural images\n")
            wsp.structural.struc = Image(biascorr)
            wsp.structural.brain = Image(biascorr_brain)
        else:
            wsp.log.write(" - Using non bias-corrected structural images\n")
            wsp.structural.struc = Image(os.path.join(wsp.fslanat, "T1"))
            wsp.structural.brain = Image(os.path.join(wsp.fslanat, "T1_brain"))
    elif wsp.struc:
        wsp.log.write(" - Using structural image provided by user: %s\n" %
                      wsp.struc.name)
        wsp.structural.struc = wsp.struc
        wsp.structural.brain = wsp.struc_brain
    #elif wsp.structural.struc_lores
    #    wsp.log.write("Low-resolution tructural image: %s\n" % wsp.structural.struc_lores.name)
    else:
        wsp.log.write(
            " - No structural data supplied - output will be native space only\n"
        )

    if wsp.structural.struc is not None and wsp.structural.brain is None:
        wsp.log.write(" - Brain-extracting structural image\n")
        bet_result = fsl.bet(wsp.structural.struc,
                             output=fsl.LOAD,
                             seg=True,
                             mask=True,
                             log=wsp.fsllog)
        wsp.structural.brain = bet_result["output"]
        #wsp.structural.brain_mask = bet_result["output_mask"]

    if wsp.structural.brain is not None and wsp.structural.brain_mask is None:
        # FIXME - for now get the mask by binarising the brain image for compatibility with oxford_asl
        # although this gives slightly different results compared to using the mask returned by BET
        wsp.structural.brain_mask = Image(
            (wsp.structural.brain.data != 0).astype(np.int),
            header=wsp.structural.struc.header)

    if wsp.structural.struc is not None:
        segment(wsp)
Esempio n. 17
0
def correct_img(wsp, img, linear_mat):
    """
    Apply combined warp/linear transformations to an image in ASL space

    :param img: fsl.data.image.Image to correct
    :param linear_mat: img->ASL space linear transformation matrix.
    :return: Corrected Image

    If a jacobian is present, also corrects for quantitative signal magnitude as volume has been locally scaled

    FIXME there are slight differences to oxford_asl here due to use of spline interpolation rather than
    applyxfm4D which uses sinc interpolation.

    Required workspace attributesd
    -----------------------------

     - ``asldata_mean`` : Mean ASL image used as reference space

    Optional workspace attributes
    -----------------------------

     - ``total_warp``      : Combined warp image
     - ``jacobian``        : Jacobian associated with warp image
     - ``senscorr``        : Sensitivity correction
    """
    if wsp.corrected.total_warp is not None:
        img = reg.transform(wsp,
                            img,
                            trans=wsp.corrected.total_warp,
                            ref=wsp.preproc.aslspace,
                            premat=linear_mat)
    else:
        img = reg.transform(wsp,
                            img,
                            trans=linear_mat,
                            ref=wsp.preproc.aslspace)

    if wsp.corrected.jacobian is not None:
        wsp.log.write(
            " - Correcting for local volume scaling using Jacobian\n")
        jdata = wsp.corrected.jacobian.data
        if img.data.ndim == 4:
            # Required to make broadcasting work
            jdata = jdata[..., np.newaxis]
        img = Image(img.data * jdata, header=img.header)

    if wsp.senscorr is not None:
        wsp.log.write(" - Applying sensitivity correction\n")
        sens_data = reg.change_space(wsp, wsp.senscorr.sensitivity, img).data
        if img.ndim == 4:
            sens_data = sens_data[..., np.newaxis]
        img = Image(img.data / sens_data, header=img.header)

    return img
Esempio n. 18
0
def test_fillSelection_2d():
    img = Image(np.random.randint(1, 65536, (60, 60, 1)))
    tfs = ft.partial(_test_fillSelection, img=img, canvas=2)
    run_with_orthopanel(tfs)

    img = Image(np.random.randint(1, 65536, (60, 1, 60)))
    tfs = ft.partial(_test_fillSelection, img=img, canvas=1)
    run_with_orthopanel(tfs)

    img = Image(np.random.randint(1, 65536, (1, 60, 60)))
    tfs = ft.partial(_test_fillSelection, img=img, canvas=0)
    run_with_orthopanel(tfs)
Esempio n. 19
0
def test_pvc_no_tissue():
    """
    Check that PVC correction fails if you do not infer the tissue component
    """
    d = np.random.rand(5, 5, 5, 6)
    img = AslImage(name="asldata", image=d, tis=[1.5], order="prt")
    wsp = Workspace(infertiss=False, inferbat=True)

    wsp.pgm = Image(np.random.rand(5, 5, 5))
    wsp.pwm = Image(np.random.rand(5, 5, 5))

    with pytest.raises(ValueError):
        basil.basil_steps(wsp, img)
Esempio n. 20
0
def test_bad_method():
    """
    Check we get an error on an invalid method
    """
    d = np.random.rand(5, 5, 5, 6)
    perf_img = Image(name="perfusion", image=d)

    d = np.random.rand(5, 5, 5, 6)
    calib_img = Image(name="calib", image=d)

    wsp = Workspace(calib=calib_img, calib_method="random")
    with pytest.raises(ValueError):
        calib.calibrate(wsp, perf_img)
Esempio n. 21
0
def test_resample_image_dim():
    with tempdir():
        img = Image(make_random_image('image.nii.gz', dims=(10, 10, 10)))

        resample_image.main('image resampled -d 0.5,0.5,0.5'.split())

        res = Image('resampled')
        expv2w = affine.concat(img.voxToWorldMat,
                               affine.scaleOffsetXform([0.5, 0.5, 0.5], 0))

        assert np.all(np.isclose(res.shape, (20, 20, 20)))
        assert np.all(np.isclose(res.pixdim, (0.5, 0.5, 0.5)))
        assert np.all(np.isclose(res.voxToWorldMat, expv2w))
Esempio n. 22
0
    def __init__(self, *args, **kwargs):
        """
        Constructor. 

        Can take same arguments as the fsl.data.image.Image constructor
        but also supports keyword ``param_names`` argument. This should
        be a list of parameter names which matches the size of the MVN
        """
        self.param_names = kwargs.get("param_names", None)
        Image.__init__(self, *args, **kwargs)
        self.nparams = self._get_num_params()
        if self.param_names is None:
            self.param_names = ["Parameter %i" % idx for idx in range(self.nparams)]
        elif len(self.param_names) != self.nparams:
            raise ValueError("MVN contains %i parameters, but %i parameter names were provided")
Esempio n. 23
0
def test_refregion_gain():
    """
    Modify calibration gain
    """
    GAIN = 3.4
    perf_img, calib_img = _get_imgs()

    ref_d = np.ones((5, 5, 5))
    ref_img = Image(name="refmask", image=ref_d)

    wsp = Workspace(calib=calib_img,
                    calib_method="refregion",
                    refmask=ref_img,
                    calib_aslreg=True,
                    tissref="wm",
                    calib_gain=GAIN)
    perf_calib = calib.calibrate(wsp, perf_img)
    calibrated_d = perf_calib.data

    m0_expected = _expected_m0(np.mean(calib_img.data),
                               1.0,
                               50,
                               0.82,
                               gain=GAIN)
    np.testing.assert_allclose(calibrated_d, perf_img.data / m0_expected)
Esempio n. 24
0
def test_image_save():
    """ 
    Test images are saved in the savedir
    """
    tempdir = tempfile.mkdtemp("_oxasl")
    try:
        wsp = Workspace(savedir=tempdir)
        img = Image(np.random.rand(5, 5, 5))
        wsp.testimg = img
        path = os.path.join(tempdir, "testimg.nii.gz")
        assert(os.path.isfile(path))
        otherimg = Image(path)
        assert(np.all(img.data == wsp.testimg.data))
        assert(np.all(img.data == otherimg.data))
    finally:
        shutil.rmtree(tempdir)
Esempio n. 25
0
def _test_newMask(ortho, overlayList, displayCtx):
    img = Image(np.random.randint(1, 65536, (20, 20, 20)))
    overlayList[:] = [img]
    idle.block(2.5)
    ortho.profile = 'edit'
    idle.block(2.5)

    profile = ortho.getCurrentProfile()

    profile.createMask()
    idle.block(2.5)
    assert len(overlayList) == 2
    mask = overlayList[1]
    assert mask.sameSpace(img)
    assert np.all(mask[:] == 0)
    overlayList.remove(mask)
    idle.block(2.5)

    profile.mode = 'sel'
    idle.block(2.5)
    ed = profile.editor(img)
    ed.getSelection().addToSelection(np.ones((4, 4, 4)), offset=(8, 8, 8))
    idle.block(2.5)
    profile.createMask()
    idle.block(2.5)
    assert len(overlayList) == 2
    mask = overlayList[1]
    assert mask.sameSpace(img)
    exp = np.zeros(mask.shape)
    exp[8:12, 8:12, 8:12] = 1
    assert np.all(mask[:] == exp)
    overlayList[:] = []
    idle.block(2.5)
Esempio n. 26
0
def get_ventricular_csf_mask(fslanatdir, interpolation=3):
    """
    Get a ventricular mask in T1 space.

    Register the ventricles mask from the harvardoxford-subcortical 
    2mm atlas to T1 space, using the T1_to_MNI_nonlin_coeff.nii.gz 
    in the provided fsl_anat directory.

    Parameters
    ----------
    fslanatdir: pathlib.Path
        Path to an fsl_anat output directory.
    interpolation: int
        Order of interpolation to use when performing registration.
        Default is 3.
    """
    # get ventricles mask from Harv-Ox
    atlases.rescanAtlases()
    harvox = atlases.loadAtlas('harvardoxford-subcortical', 
                                         resolution=2.0)
    vent_img = Image(
        harvox.data[:,:,:,2] + harvox.data[:,:,:,13], 
        header=harvox.header
    )
    vent_img = fslmaths(vent_img).thr(0.1).bin().ero().run(LOAD)

    # apply inv(T1->MNI) registration
    t1_brain = (fslanatdir/"T1_biascorr_brain.nii.gz").resolve(strict=True)
    struct2mni = (fslanatdir/"T1_to_MNI_nonlin_coeff.nii.gz").resolve(strict=True)
    mni2struct = invwarp(str(struct2mni), str(t1_brain), LOAD)['out']
    vent_t1_img = applywarp(vent_img, str(t1_brain), LOAD, warp=mni2struct)['out']
    vent_t1_img = fslmaths(vent_t1_img).thr(0.9).bin().run(LOAD)
    return vent_t1_img
Esempio n. 27
0
def _calc_slicedt(wsp, options):
    """
    Calculate the slicedt for basil given that we may be quantifying in
    a space other than the usual ASL space

    We do this by generating a slice time offset image and transforming it
    to quantification space. Since this could be rotated wrt to the asl data
    we may need to warn if the resulting image has significant slice time variation
    across X or Y axes
    """
    img_space = wsp.ifnone("image_space", "native")
    if img_space != "native":
        asldata = options["data"]
        _x, _y, z, _t = np.indices(
            list(asldata.data.shape[:3]) + [
                asldata.ntis,
            ])
        print(z.shape)
        tis_arr = np.array(
            asldata.tis) + (z.astype(np.float32) * options["slicedt"])
        print(tis_arr.shape)

        tis_img = Image(tis_arr, header=options["data"].header)
        wsp.tiimg = reg.change_space(wsp, tis_img,
                                     wsp.ifnone("image_space", "native"))

        #print(ztrans.data)
        print(wsp.tiimg.data.shape)
        del options["slicedt"]
        ti_idx = 1
        while "ti%i" % ti_idx in options:
            del options["ti%i" % ti_idx]
            ti_idx += 1

        options["tiimg"] = wsp.tiimg
Esempio n. 28
0
def _test_ComplexTimeSeries(panel, overlayList, displayCtx):
    displayCtx = panel.displayCtx
    data       = np.random.randint(1, 255, (10, 10, 10, 20)) + \
            1j * np.random.randint(1, 255, (10, 10, 10, 20))
    data = np.array(data, dtype=np.complex64)
    img = Image(data, xform=np.eye(4))
    overlayList.append(img)
    realYield(100)
    opts = displayCtx.getOpts(img)
    ts = panel.getDataSeries(img)
    displayCtx.location = opts.transformCoords((7, 8, 9), 'voxel', 'display')
    exp = img[7, 8, 9, :]

    xdata, ydata = ts.getData()
    assert np.all(xdata == np.arange(img.shape[3]))
    assert np.all(ydata == exp.real)

    ts.plotReal = False
    xdata, ydata = ts.getData()
    assert xdata is None
    assert ydata is None

    ts.plotImaginary = True
    ts.plotMagnitude = True
    ts.plotPhase = True
    its, mts, pts = ts.extraSeries()
    assert np.all(its.getData()[1] == exp.imag)

    expmag = np.sqrt(exp.real**2 + exp.imag**2)
    expphase = np.arctan2(exp.imag, exp.real)

    assert np.all(np.isclose(expmag, mts.getData()[1]))
    assert np.all(np.isclose(expphase, pts.getData()[1]))
Esempio n. 29
0
def _test_ComplexHistogramSeries(panel, overlayList, displayCtx):
    displayCtx = panel.displayCtx
    data       = np.random.randint(1, 255, (10, 10, 10)) + \
            1j * np.random.randint(1, 255, (10, 10, 10))
    data.flags.writeable = False
    data = np.array(data, dtype=np.complex64)
    img = Image(data, xform=np.eye(4))

    overlayList.append(img)
    realYield()
    hs = panel.getDataSeries(img)
    hs.plotReal = True
    hs.plotImaginary = True
    hs.plotMagnitude = True
    hs.plotPhase = True
    his, hms, hps = hs.extraSeries()

    real = data.real
    imag = data.imag
    mag = (real**2 + imag**2)**0.5
    phase = np.arctan2(imag, real)

    for hdata, hhs in zip([real, imag, mag, phase], [hs, his, hms, hps]):
        dmin, dmax = hdata.min(), hdata.max()
        drange = dmin, dmax + (dmax - dmin) / 10000
        nbins = hseries.autoBin(hdata, drange)
        hx, hy, _ = hseries.histogram(hdata, nbins, drange, drange)
        gotx, goty = hhs.getData()
        assert np.all(gotx == hx)
        assert np.all(goty == hy)
Esempio n. 30
0
def apply_sensitivity_correction(wsp, *imgs):
    """
    Apply sensitivity correction

    :param imgs: Sequence of Image objects

    :return: Tuple of corrected Image objects corresponding to input.
             If no sensitivity correction is defined, returns the same
             images as input.

    Optional workspace attributes
    -----------------------------

     - ``sensitivity``  : Sensitivity correction image
     - ``senscorr_off`` : If True, no correction will be applied even if ``sensitivity`` image exists
    """
    if wsp.senscorr is not None:
        wsp.log.write(" - Applying sensitivity correction\n")
        ret = []
        for img in imgs:
            ret.append(
                Image(img.data / wsp.senscorr.sensitivity.data,
                      header=img.header))
        return tuple(ret)
    else:
        return tuple(imgs)