Esempio n. 1
0
def test_fast():
    with asrt.disabled(), run.dryrun(), mockFSLDIR(bin=('fast', )) as fsldir:

        cmd = op.join(fsldir, 'bin', 'fast')

        result = fw.fast('input', 'myseg', n_classes=3)
        expected = [cmd, '--out=myseg', '--class=3', 'input']

        assert result.stdout[0] == ' '.join(expected)

        result = fw.fast(('in1', 'in2', 'in3'), 'myseg', n_classes=3)
        expected = [cmd, '--out=myseg', '--class=3', 'in1', 'in2', 'in3']
        assert result.stdout[0] == ' '.join(expected)

        result = fw.fast(('in1', 'in2', 'in3'),
                         'myseg',
                         n_classes=3,
                         verbose=True)
        expected = [
            cmd, '--out=myseg', '--class=3', '--verbose', 'in1', 'in2', 'in3'
        ]
        assert result.stdout[0] == ' '.join(expected)

        result = fw.fast(('in1', 'in2', 'in3'),
                         'myseg',
                         n_classes=3,
                         a='reg.mat',
                         A=('csf', 'gm', 'wm'),
                         Prior=True)
        expected = [
            cmd, '--out=myseg', '--class=3', '-a', 'reg.mat', '-A', 'csf',
            'gm', 'wm', '--Prior', 'in1', 'in2', 'in3'
        ]
        assert result.stdout[0] == ' '.join(expected)
Esempio n. 2
0
def test_fast():
    with asrt.disabled(), run.dryrun(), mockFSLDIR(bin=('fast', )) as fsldir:

        cmd = op.join(fsldir, 'bin', 'fast')

        result = fw.fast('input', 'myseg', n_classes=3)
        expected = [cmd, '-v', '--out=myseg', '--class=3', 'input']

        assert result.stdout[0] == ' '.join(expected)

        result = fw.fast(('in1', 'in2', 'in3'), 'myseg', n_classes=3)
        expected = [cmd, '-v', '--out=myseg', '--class=3', 'in1', 'in2', 'in3']

        assert result.stdout[0] == ' '.join(expected)
Esempio n. 3
0
def bias_estimation_calib(calib_name):
    """
    Estimate the bias field from a calibration image using FAST.

    Parameters
    ----------
    calib_name: pathlib.Path
        Path to the calibration image from which to estimate the 
        bias field.
    
    Returns
    -------
    bias_field: Nifti1Image
    """
    # perform brain extraction using BET
    betted_m0 = bet(str(calib_name), LOAD, g=0.2, f=0.2, m=True)
    # run FAST on BET-ed calibration image
    fast_results = fast(betted_m0["output"],
                        out=LOAD,
                        type=3,
                        b=True,
                        nopve=True)
    # extract and return bias field
    bias_field = fast_results["out_bias"]
    return bias_field
Esempio n. 4
0
def segment(wsp):
    """
    Segment the structural image
    """
    init(wsp)
    if None in (wsp.structural.wm_seg, wsp.structural.gm_seg, wsp.structural.csf_seg):
        init(wsp)
        page = wsp.report.page("seg")
        page.heading("Segmentation of structural image")

        wsp.log.write("\nGetting structural segmentation\n")
        if wsp.fslanat:
            wsp.log.write(" - Using FSL_ANAT output\n")
            page.text("Segmentation taken from FSL_ANAT output at ``%s``" % wsp.fslanat)
            wsp.structural.csf_pv = Image(os.path.join(wsp.fslanat, "T1_fast_pve_0"))
            wsp.structural.gm_pv = Image(os.path.join(wsp.fslanat, "T1_fast_pve_1"))
            wsp.structural.wm_pv = Image(os.path.join(wsp.fslanat, "T1_fast_pve_2"))

            try:
                wsp.structural.bias = Image(os.path.join(wsp.fslanat, "T1_fast_bias"))
                wsp.log.write(" - Bias field extracted sucessfully\n")
            except PathError:
                wsp.log.write(" - No bias field found")
        elif wsp.fastsrc:
            # FIXME should be possible to implement this
            raise NotImplementedError("Specifying FAST output directory")
            #img = os.path.split(wsp.fastsrc)[1]
            #wsp.structural.csf_pv = os.path.join(wsp.fastsrc, "%s_pve_0" % img)
            #wsp.structural.gm_pv = os.path.join(wsp.fastsrc, "%s_pve_1" % img)
            #wsp.structural.wm_pv = os.path.join(wsp.fastsrc, "%s_pve_2" % img)
        elif wsp.structural.struc:
            wsp.log.write(" - Running FAST\n")
            page.text("FAST run to segment structural image")
            fast_result = fsl.fast(wsp.structural.brain, out=fsl.LOAD, log=wsp.fsllog)
            wsp.structural.csf_pv = fast_result["out_pve_0"]
            wsp.structural.gm_pv = fast_result["out_pve_1"]
            wsp.structural.wm_pv = fast_result["out_pve_2"]
            #wsp.bias_struc = fast_result["fast_bias"]
        else:
            raise ValueError("No structural data provided - cannot segment")

        wsp.structural.csf_seg = Image((wsp.structural.csf_pv.data > 0.5).astype(np.int), header=wsp.structural.struc.header)
        wsp.structural.gm_seg = Image((wsp.structural.gm_pv.data > 0.5).astype(np.int), header=wsp.structural.struc.header)
        wsp.structural.wm_seg = Image((wsp.structural.wm_pv.data > 0.5).astype(np.int), header=wsp.structural.struc.header)

        page.heading("Segmentation image", level=1)
        page.text("CSF partial volume")
        page.image("csf_pv", LightboxImage(wsp.structural.csf_pv, bgimage=wsp.structural.brain))
        page.text("Grey matter partial volume")
        page.image("gm_pv", LightboxImage(wsp.structural.gm_pv, bgimage=wsp.structural.brain))
        page.text("White matter partial volume")
        page.image("wm_pv", LightboxImage(wsp.structural.wm_pv, bgimage=wsp.structural.brain))
Esempio n. 5
0
def segment(wsp):
    """
    Segment the structural image
    """
    # Can override segmentation from user-specified maps
    wsp.structural.wm_seg = wsp.wm_seg
    wsp.structural.gm_seg = wsp.gm_seg
    wsp.structural.csf_seg = wsp.csf_seg

    if None in (wsp.structural.wm_seg, wsp.structural.gm_seg,
                wsp.structural.csf_seg):
        page = wsp.report.page("seg")
        page.heading("Segmentation of structural image")

        wsp.log.write("\nGetting structural segmentation\n")
        if wsp.fslanat:
            wsp.log.write(" - Using FSL_ANAT output from %s\n" % wsp.fslanat)
            page.text("Segmentation taken from FSL_ANAT output at ``%s``" %
                      wsp.fslanat)
            wsp.structural.csf_pv = Image(
                os.path.join(wsp.fslanat, "T1_fast_pve_0"))
            wsp.structural.gm_pv = Image(
                os.path.join(wsp.fslanat, "T1_fast_pve_1"))
            wsp.structural.wm_pv = Image(
                os.path.join(wsp.fslanat, "T1_fast_pve_2"))

            try:
                wsp.structural.bias = Image(
                    os.path.join(wsp.fslanat, "T1_fast_bias"))
                wsp.log.write(" - Bias field extracted sucessfully\n")
            except PathError:
                wsp.log.write(" - No bias field found")
        elif wsp.fastsrc:
            wsp.log.write(" - Using FAST output from %s\n" % wsp.fastsrc)
            page.text("Segmentation taken from FAST output at ``%s``" %
                      wsp.fastsrc)
            wsp.structural.csf_pv = Image("%s_pve_0" % wsp.fastsrc)
            wsp.structural.gm_pv = Image("%s_pve_1" % wsp.fastsrc)
            wsp.structural.wm_pv = Image("%s_pve_2" % wsp.fastsrc)
        elif wsp.structural.struc:
            wsp.log.write(" - Running FAST\n")
            page.text("FAST run to segment structural image")
            fast_result = fsl.fast(wsp.structural.brain,
                                   out=fsl.LOAD,
                                   log=wsp.fsllog)
            wsp.structural.csf_pv = fast_result["out_pve_0"]
            wsp.structural.gm_pv = fast_result["out_pve_1"]
            wsp.structural.wm_pv = fast_result["out_pve_2"]
            #wsp.bias_struc = fast_result["fast_bias"]
        else:
            raise ValueError("No structural data provided - cannot segment")

        if wsp.structural.csf_seg is not None:
            wsp.structural.csf_seg = Image(
                (wsp.structural.csf_pv.data > 0.5).astype(np.int),
                header=wsp.structural.struc.header)
        if wsp.structural.gm_seg is not None:
            wsp.structural.gm_seg = Image(
                (wsp.structural.gm_pv.data > 0.5).astype(np.int),
                header=wsp.structural.struc.header)
        if wsp.structural.wm_seg is not None:
            wsp.structural.wm_seg = Image(
                (wsp.structural.wm_pv.data > 0.5).astype(np.int),
                header=wsp.structural.struc.header)

        page.heading("Segmentation image", level=1)
        page.text("CSF partial volume")
        page.image(
            "csf_pv",
            LightboxImage(wsp.structural.csf_pv, bgimage=wsp.structural.brain))
        page.text("Grey matter partial volume")
        page.image(
            "gm_pv",
            LightboxImage(wsp.structural.gm_pv, bgimage=wsp.structural.brain))
        page.text("White matter partial volume")
        page.image(
            "wm_pv",
            LightboxImage(wsp.structural.wm_pv, bgimage=wsp.structural.brain))
Esempio n. 6
0
def correct_M0(subject_dir, mt_factors):
    """
    Correct the M0 images for a particular subject whose data 
    is stored in `subject_dir`. The corrections to be 
    performed include:
        - Bias-field correction
        - Magnetisation Transfer correction
    
    Inputs
        - `subject_dir` = pathlib.Path object specifying the 
            subject's base directory
        - `mt_factors` = pathlib.Path object specifying the 
            location of empirically estimated MT correction 
            scaling factors
    """
    # load json containing info on where files are stored
    json_dict = load_json(subject_dir)

    # do for both m0 images for the subject, calib0 and calib1
    calib_names = [json_dict['calib0_img'], json_dict['calib1_img']]
    for calib_name in calib_names:
        # get calib_dir and other info
        calib_path = Path(calib_name)
        calib_dir = calib_path.parent
        calib_name_stem = calib_path.stem.split('.')[0]

        # run BET on m0 image
        betted_m0 = bet(calib_name, LOAD)

        # create directories to store results
        fast_dir = calib_dir / 'FAST'
        biascorr_dir = calib_dir / 'BiasCorr'
        mtcorr_dir = calib_dir / 'MTCorr'
        create_dirs([fast_dir, biascorr_dir, mtcorr_dir])

        # estimate bias field on brain-extracted m0 image
        # run FAST, storing results in directory
        fast_base = fast_dir / calib_name_stem
        fast(
            betted_m0['output'],  # output of bet
            out=str(fast_base),
            type=3,  # image type, 3=PD image
            b=True,  # output estimated bias field
            nopve=True  # don't need pv estimates
        )
        bias_name = fast_dir / f'{calib_name_stem}_bias.nii.gz'

        # apply bias field to original m0 image (i.e. not BETted)
        biascorr_name = biascorr_dir / f'{calib_name_stem}_restore.nii.gz'
        fslmaths(calib_name).div(str(bias_name)).run(str(biascorr_name))

        # apply mt_factors to bias-corrected m0 image
        mtcorr_name = mtcorr_dir / f'{calib_name_stem}_mtcorr.nii.gz'
        fslmaths(str(biascorr_name)).mul(str(mt_factors)).run(str(mtcorr_name))

        # add locations of above files to the json
        important_names = {
            f'{calib_name_stem}_bias': str(bias_name),
            f'{calib_name_stem}_bc': str(biascorr_name),
            f'{calib_name_stem}_mc': str(mtcorr_name)
        }
        update_json(important_names, json_dict)
Esempio n. 7
0
def setup_mtestimation(subject_dir, rois=[
    'wm',
]):
    """
    Perform the initial processing needed for estimation of the 
    MT Effect. This includes:
    - Creating sub-directories for storing the results
    - Finding T1 and mbPCASL directories and scans
    - Split mbPCASL sequence into its constituent components
    - Run fsl_anat
    - Create a json to keep track of important files and 
        directories
    """
    # get subject name
    subject_name = subject_dir.parts[-1]
    print(subject_name)

    # create results directories
    asl_dir = subject_dir / 'ASL'
    calib0_dir = asl_dir / 'Calib/Calib0'
    calib1_dir = asl_dir / 'Calib/Calib1'
    create_dirs([asl_dir, calib0_dir, calib1_dir])

    # obtain calibration images from ASL sequence
    mbpcasl_dir = list(
        (subject_dir / f'{subject_name}_V1_B/scans').glob('**/*mbPCASLhr'))[0]
    mbpcasl = mbpcasl_dir / f'resources/NIFTI/files/{subject_name}_V1_B_mbPCASLhr_PA.nii.gz'
    calib0_name = calib0_dir / 'calib0.nii.gz'
    calib1_name = calib1_dir / 'calib1.nii.gz'
    fslroi(str(mbpcasl), calib0_name, 88, 1)
    fslroi(str(mbpcasl), calib1_name, 89, 1)

    # initialise dict
    json_name = asl_dir / 'ASL.json'
    important_dict = {
        "calib_dir": str(calib0_dir.parent),
        "calib0_dir": str(calib0_dir),
        "calib1_dir": str(calib1_dir),
        "calib0_img": str(calib0_name),
        "calib1_img": str(calib1_dir),
        "json_name": str(json_name)
    }

    # structural directory
    t1_dir = list(
        (subject_dir / f'{subject_name}_V1_A/scans').glob('**/*T1w'))[0]
    struc_dir = t1_dir / 'resources/NIFTI/files'
    struc_name = list(struc_dir.glob(f'**/{subject_name}_*.nii.gz'))[0]
    fsl_anat_dir = struc_dir / 'ASL/struc'
    calib0struct_dir = struc_dir / 'ASL/Calib/Calib0'
    calib1struct_dir = struc_dir / 'ASL/Calib/Calib1'
    create_dirs([calib0struct_dir, calib1struct_dir])

    # run fsl_anat
    fsl_anat(str(struc_name),
             str(fsl_anat_dir),
             clobber=True,
             nosubcortseg=True)
    fsl_anat_dir = fsl_anat_dir.parent / f'{fsl_anat_dir.stem}.anat'
    t1_name = fsl_anat_dir / 'T1_biascorr.nii.gz'
    t1_brain_name = fsl_anat_dir / 'T1_biascorr_brain.nii.gz'

    # get ventricles mask if csf
    if 'csf' in rois:
        # initialise atlas list
        atlases.rescanAtlases()
        harv_ox_prob_2mm = atlases.loadAtlas('harvardoxford-subcortical',
                                             resolution=2.0)
        vent_img = Image(harv_ox_prob_2mm.data[:, :, :, 2] +
                         harv_ox_prob_2mm.data[:, :, :, 13],
                         header=harv_ox_prob_2mm.header)
        vent_img = fslmaths(vent_img).thr(0.1).bin().ero().run(LOAD)
        # we already have registration from T1 to MNI
        struc2mni_warp = fsl_anat_dir / 'MNI_to_T1_nonlin_field.nii.gz'
        # apply warp to ventricles image
        vent_t1_name = fsl_anat_dir / 'ventricles_mask.nii.gz'
        applywarp(vent_img,
                  str(t1_brain_name),
                  str(vent_t1_name),
                  warp=str(struc2mni_warp))
        # re-threshold
        vent_t1 = fslmaths(str(vent_t1_name)).thr(
            PVE_THRESHOLDS['csf']).bin().run(LOAD)
        # mask pve estimate by ventricles mask
        fslmaths(str(fsl_anat_dir / PVE_NAMES['csf'])).mas(vent_t1).run(
            str(vent_t1_name))

    # bias-field correction
    for calib_name in (calib0_name, calib1_name):
        calib_name_stem = calib_name.stem.split('.')[0]
        # run bet
        betted_m0 = bet(str(calib_name), LOAD)
        # create directories to save results
        fast_dir = calib_name.parent / 'FAST'
        biascorr_dir = calib_name.parent / 'BiasCorr'
        create_dirs([fast_dir, biascorr_dir])
        # run FAST on brain-extracted m0 image
        fast_base = fast_dir / calib_name_stem
        fast(betted_m0['output'],
             out=str(fast_base),
             type=3,
             b=True,
             nopve=True)
        bias_name = fast_dir / f'{calib_name_stem}_bias.nii.gz'
        # apply bias field to original m0 image (i.e. not BETted)
        biascorr_name = biascorr_dir / f'{calib_name_stem}_restore.nii.gz'
        fslmaths(str(calib_name)).div(str(bias_name)).run(str(biascorr_name))
        # obtain registration from structural to calibration image
        mask_dir = biascorr_name.parent / 'masks'
        create_dirs([
            mask_dir,
        ])
        cmd = [
            'asl_reg', f'-i {biascorr_name}', f'-s {t1_name}',
            f'--sbet {t1_brain_name}', f'-o {mask_dir}'
        ]
        subprocess.run(" ".join(cmd), shell=True)
        # apply transformation to the pve map
        for tissue in rois:
            roi_dir = mask_dir / tissue
            create_dirs([
                roi_dir,
            ])
            if tissue == 'combined':
                # check that gm and wm pves already exist
                gm_pve = mask_dir / 'gm/pve_gm.nii.gz'
                wm_pve = mask_dir / 'wm/pve_wm.nii.gz'
                if not (gm_pve.exists() and wm_pve.exists()):
                    raise Exception("WM and GM PVEs don't exist.")
                gm_mask_name = roi_dir / 'gm_mask.nii.gz'
                wm_mask_name = roi_dir / 'wm_mask.nii.gz'
                fslmaths(str(gm_pve)).thr(PVE_THRESHOLDS[tissue]).bin().run(
                    str(gm_mask_name))
                fslmaths(str(wm_pve)).thr(PVE_THRESHOLDS[tissue]).bin().run(
                    str(wm_mask_name))
                gm_masked_name = roi_dir / f'{calib_name_stem}_gm_masked'
                wm_masked_name = roi_dir / f'{calib_name_stem}_wm_masked'
                fslmaths(str(biascorr_name)).mul(str(gm_mask_name)).run(
                    str(gm_masked_name))
                fslmaths(str(biascorr_name)).mul(str(wm_mask_name)).run(
                    str(wm_masked_name))
                # update dictionary
                new_dict = {
                    f'{calib_name_stem}_{tissue}_masked':
                    [str(gm_masked_name),
                     str(wm_masked_name)]
                }
            else:
                if tissue == 'csf':
                    pve_struct_name = vent_t1_name
                else:
                    pve_struct_name = fsl_anat_dir / PVE_NAMES[tissue]
                pve_asl_name = roi_dir / f'pve_{tissue}.nii.gz'
                struct2asl_name = mask_dir / 'struct2asl.mat'
                applyxfm(str(pve_struct_name), str(biascorr_name),
                         str(struct2asl_name), str(pve_asl_name))
                # threshold and binarise the ASL-space pve map
                mask_name = roi_dir / f'{tissue}_mask.nii.gz'
                fslmaths(str(pve_asl_name)).thr(
                    PVE_THRESHOLDS[tissue]).bin().run(str(mask_name))
                # apply the mask to the calibration image
                masked_name = mask_dir / f'{tissue}_masked.nii.gz'
                fslmaths(str(biascorr_name)).mul(str(mask_name)).run(
                    str(masked_name))
                # update dictionary
                new_dict = {
                    f'{calib_name_stem}_{tissue}_masked': str(masked_name)
                }
            important_dict.update(new_dict)

    # save json
    with open(json_name, 'w') as fp:
        json.dump(important_dict, fp, sort_keys=True, indent=4)
    return (subject_dir, 0)