Exemple #1
0
def test_sfm_stick():
    fdata, fbvals, fbvecs = dpd.get_fnames()
    data = load_nifti_data(fdata)
    gtab = grad.gradient_table(fbvals, fbvecs)
    sfmodel = sfm.SparseFascicleModel(gtab,
                                      solver='NNLS',
                                      response=[0.001, 0, 0])
    sffit1 = sfmodel.fit(data[0, 0, 0])
    sphere = dpd.get_sphere()
    sffit1.odf(sphere)
    sffit1.predict(gtab)

    SNR = 1000
    S0 = 100
    mevals = np.array(([0.001, 0, 0], [0.001, 0, 0]))
    angles = [(0, 0), (60, 0)]
    S, sticks = sims.multi_tensor(gtab,
                                  mevals,
                                  S0,
                                  angles=angles,
                                  fractions=[50, 50],
                                  snr=SNR)

    sfmodel = sfm.SparseFascicleModel(gtab,
                                      solver='NNLS',
                                      response=[0.001, 0, 0])
    sffit = sfmodel.fit(S)
    pred = sffit.predict()
    npt.assert_(xval.coeff_of_determination(pred, S) > 96)
def test_predict():
    SNR = 1000
    S0 = 100
    _, fbvals, fbvecs = dpd.get_data('small_64D')
    bvals = np.load(fbvals)
    bvecs = np.load(fbvecs)
    gtab = grad.gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]))
    angles = [(0, 0), (60, 0)]
    S, sticks = sims.multi_tensor(gtab,
                                  mevals,
                                  S0,
                                  angles=angles,
                                  fractions=[10, 90],
                                  snr=SNR)

    sfmodel = sfm.SparseFascicleModel(gtab, response=[0.0015, 0.0003, 0.0003])
    sffit = sfmodel.fit(S)
    pred = sffit.predict()
    npt.assert_(xval.coeff_of_determination(pred, S) > 97)

    # Should be possible to predict using a different gtab:
    new_gtab = grad.gradient_table(bvals[::2], bvecs[::2])
    new_pred = sffit.predict(new_gtab)
    npt.assert_(xval.coeff_of_determination(new_pred, S[::2]) > 97)
Exemple #3
0
def test_sfm():
    fdata, fbvals, fbvecs = dpd.get_fnames()
    data = load_nifti_data(fdata)
    gtab = grad.gradient_table(fbvals, fbvecs)
    for iso in [sfm.ExponentialIsotropicModel, None]:
        sfmodel = sfm.SparseFascicleModel(gtab, isotropic=iso)
        sffit1 = sfmodel.fit(data[0, 0, 0])
        sphere = dpd.get_sphere()
        odf1 = sffit1.odf(sphere)
        pred1 = sffit1.predict(gtab)
        mask = np.ones(data.shape[:-1])
        sffit2 = sfmodel.fit(data, mask)
        pred2 = sffit2.predict(gtab)
        odf2 = sffit2.odf(sphere)
        sffit3 = sfmodel.fit(data)
        pred3 = sffit3.predict(gtab)
        odf3 = sffit3.odf(sphere)
        npt.assert_almost_equal(pred3, pred2, decimal=2)
        npt.assert_almost_equal(pred3[0, 0, 0], pred1, decimal=2)
        npt.assert_almost_equal(odf3[0, 0, 0], odf1, decimal=2)
        npt.assert_almost_equal(odf3[0, 0, 0], odf2[0, 0, 0], decimal=2)
        # Fit zeros and you will get back zeros
        npt.assert_almost_equal(
            sfmodel.fit(np.zeros(data[0, 0, 0].shape)).beta,
            np.zeros(sfmodel.design_matrix[0].shape[-1]))
Exemple #4
0
def test_exponential_iso():
    fdata, fbvals, fbvecs = dpd.get_fnames()
    data_dti = nib.load(fdata).get_data()
    gtab_dti = grad.gradient_table(fbvals, fbvecs)
    data_multi, gtab_multi = dpd.dsi_deconv_voxels()

    for data, gtab in zip([data_dti, data_multi], [gtab_dti, gtab_multi]):
        sfmodel = sfm.SparseFascicleModel(
                  gtab, isotropic=sfm.ExponentialIsotropicModel)

        sffit1 = sfmodel.fit(data[0, 0, 0])
        sphere = dpd.get_sphere()
        sffit1.odf(sphere)
        sffit1.predict(gtab)

        SNR = 1000
        S0 = 100
        mevals = np.array(([0.0015, 0.0005, 0.0005],
                           [0.0015, 0.0005, 0.0005]))
        angles = [(0, 0), (60, 0)]
        S, sticks = sims.multi_tensor(gtab, mevals, S0, angles=angles,
                                      fractions=[50, 50], snr=SNR)
        sffit = sfmodel.fit(S)
        pred = sffit.predict()
        npt.assert_(xval.coeff_of_determination(pred, S) > 96)
Exemple #5
0
def test_design_matrix():
    data, gtab = dpd.dsi_voxels()
    sphere = dpd.get_sphere()
    # Make it with NNLS, so that it gets tested regardless of sklearn
    sparse_fascicle_model = sfm.SparseFascicleModel(gtab, sphere,
                                                    solver='NNLS')
    npt.assert_equal(sparse_fascicle_model.design_matrix.shape,
                     (np.sum(~gtab.b0s_mask), sphere.vertices.shape[0]))
Exemple #6
0
def test_sfm_background():
    fdata, fbvals, fbvecs = dpd.get_fnames()
    data = load_nifti_data(fdata)
    gtab = grad.gradient_table(fbvals, fbvecs)
    to_fit = data[0, 0, 0]
    to_fit[gtab.b0s_mask] = 0
    sfmodel = sfm.SparseFascicleModel(gtab, solver='NNLS')
    sffit = sfmodel.fit(to_fit)
    npt.assert_equal(sffit.beta, np.zeros_like(sffit.beta))
Exemple #7
0
def sfm_mod_est(gtab, data, B0_mask, BACKEND='loky'):
    """
    Estimate a Sparse Fascicle Model (SFM) from dwi data.

    Parameters
    ----------
    gtab : Obj
        DiPy object storing diffusion gradient information.
    data : array
        4D numpy array of diffusion image data.
    B0_mask : str
        File path to B0 brain mask.

    Returns
    -------
    sf_mod : ndarray
        Coefficients of the sfm reconstruction.
    model : obj
        Fitted sf model.

    References
    ----------
    .. [1] Ariel Rokem, Jason D. Yeatman, Franco Pestilli, Kendrick
      N. Kay, Aviv Mezer, Stefan van der Walt, Brian A. Wandell
      (2015). Evaluating the accuracy of diffusion MRI models in white
      matter. PLoS ONE 10(4): e0123272. doi:10.1371/journal.pone.0123272
    .. [2] Ariel Rokem, Kimberly L. Chan, Jason D. Yeatman, Franco
      Pestilli,  Brian A. Wandell (2014). Evaluating the accuracy of diffusion
      models at multiple b-values with cross-validation. ISMRM 2014.

    """
    from dipy.data import get_sphere
    import dipy.reconst.sfm as sfm
    from pynets.core.utils import load_runconfig

    sphere = get_sphere("repulsion724")
    print("Reconstructing using SFM...")

    hardcoded_params = load_runconfig()
    nthreads = hardcoded_params["omp_threads"][0]

    model = sfm.SparseFascicleModel(gtab,
                                    sphere=sphere,
                                    l1_ratio=0.5,
                                    alpha=0.001)

    sf_mod = model.fit(data,
                       mask=np.nan_to_num(np.asarray(
                           nib.load(B0_mask).dataobj)).astype("bool"),
                       num_processes=nthreads,
                       parallel_backend=BACKEND)
    sf_odf = sf_mod.odf(sphere)
    sf_odf = np.clip(sf_odf, 0, np.max(sf_odf, -1)[..., None])
    return sf_odf.astype("float32"), model
Exemple #8
0
def fit_data(data, bvals, bvecs, model_type='3D-SHORE', calculate_peak_image=False):
    """ Fits the defined model to the input dMRI and returns an MITK compliant ODF image.
    """

    # create dipy Sphere
    sphere = get_mitk_sphere()
    odf = None
    model = None
    gtab = gradient_table(bvals, bvecs)

    # fit selected model
    if model_type == '3D-SHORE':
        print('Fitting 3D-SHORE')
        radial_order = 6
        zeta = 700
        lambdaN = 1e-8
        lambdaL = 1e-8
        model = ShoreModel(gtab, radial_order=radial_order, zeta=zeta, lambdaN=lambdaN, lambdaL=lambdaL)
        asmfit = model.fit(data)
        odf = asmfit.odf(sphere)
    elif model_type == 'CSA-QBALL':
        print('Fitting CSA-QBALL')
        model = CsaOdfModel(gtab, 4)
        odf = model.fit(data).odf(sphere)
        odf = np.clip(odf, 0, np.max(odf, -1)[..., None])
    elif model_type == 'SFM':
        print('Fitting SFM')
        response, ratio = auto_response(gtab, data, roi_radius=10, fa_thr=0.7)
        model = sfm.SparseFascicleModel(gtab, sphere=sphere,
                                        l1_ratio=0.5, alpha=0.001,
                                        response=response[0])
        odf = model.fit(data).odf(sphere)
    elif model_type == 'CSD':
        print('Fitting CSD')
        response, ratio = auto_response(gtab, data, roi_radius=10, fa_thr=0.7)
        model = ConstrainedSphericalDeconvModel(gtab, response, sh_order=6)
        odf = model.fit(data).odf(sphere)
    else:
        raise ValueError('Model type not supported. Available models: 3D-SHORE, CSA-QBALL, SFM, CSD')

    print('Preparing ODF image')
    # swap axes to obtain MITK compliant format.
    # odf = odf.swapaxes(3, 2)
    # odf = odf.swapaxes(2, 1)
    # odf = odf.swapaxes(1, 0)

    odf_image = sitk.Image([data.shape[2], data.shape[1], data.shape[0]], sitk.sitkVectorFloat32, len(sphere.vertices))
    for x in range(data.shape[2]):
        for y in range(data.shape[1]):
            for z in range(data.shape[0]):
                odf_image.SetPixel(x,y,z, odf[z,y,x,:])

    # if not calculate_peak_image:
    return odf_image, None
Exemple #9
0
def sfm_mod_est(gtab, data, B0_mask):
    """
    Estimate a Sparse Fascicle Model (SFM) from dwi data.

    Parameters
    ----------
    gtab : Obj
        DiPy object storing diffusion gradient information.
    data : array
        4D numpy array of diffusion image data.
    B0_mask : str
        File path to B0 brain mask.

    Returns
    -------
    sf_mod : ndarray
        Coefficients of the sfm reconstruction.
    model : obj
        Fitted sf model.

    References
    ----------
    .. [1] Ariel Rokem, Jason D. Yeatman, Franco Pestilli, Kendrick
      N. Kay, Aviv Mezer, Stefan van der Walt, Brian A. Wandell
      (2015). Evaluating the accuracy of diffusion MRI models in white
      matter. PLoS ONE 10(4): e0123272. doi:10.1371/journal.pone.0123272
    .. [2] Ariel Rokem, Kimberly L. Chan, Jason D. Yeatman, Franco
      Pestilli,  Brian A. Wandell (2014). Evaluating the accuracy of diffusion
      models at multiple b-values with cross-validation. ISMRM 2014.

    """
    from dipy.data import get_sphere
    import dipy.reconst.sfm as sfm

    sphere = get_sphere("repulsion724")
    print("Fitting SF model...")
    B0_mask_data = np.nan_to_num(np.asarray(
        nib.load(B0_mask).dataobj)).astype("bool")
    print("Reconstructing...")
    model = sfm.SparseFascicleModel(gtab,
                                    sphere=sphere,
                                    l1_ratio=0.5,
                                    alpha=0.001)
    sf_mod = model.fit(data, mask=B0_mask_data)
    sf_odf = sf_mod.odf(sphere)

    del B0_mask_data
    return sf_odf, model
Exemple #10
0
def test_exponential_iso():
    fdata, fbvals, fbvecs = dpd.get_fnames()
    data_dti = load_nifti_data(fdata)
    gtab_dti = grad.gradient_table(fbvals, fbvecs)
    data_multi, gtab_multi = dpd.dsi_deconv_voxels()

    for data, gtab in zip([data_dti, data_multi], [gtab_dti, gtab_multi]):
        sfmodel = sfm.SparseFascicleModel(
            gtab, isotropic=sfm.ExponentialIsotropicModel)

        sffit1 = sfmodel.fit(data[0, 0, 0])
        sphere = dpd.get_sphere()
        odf = sffit1.odf(sphere)
        pred = sffit1.predict(gtab)
        npt.assert_equal(pred.shape, data[0, 0, 0].shape)
        npt.assert_equal(odf.shape,
                         data[0, 0, 0].shape[:-1] + (sphere.x.shape[0], ))

        sffit2 = sfmodel.fit(data)
        sphere = dpd.get_sphere()
        odf = sffit2.odf(sphere)
        pred = sffit2.predict(gtab)
        npt.assert_equal(pred.shape, data.shape)
        npt.assert_equal(odf.shape, data.shape[:-1] + (sphere.x.shape[0], ))

        mask = np.zeros(data.shape[:3])
        mask[2:5, 2:5, :] = 1
        sffit3 = sfmodel.fit(data, mask=mask)
        sphere = dpd.get_sphere()
        odf = sffit3.odf(sphere)
        pred = sffit3.predict(gtab)
        npt.assert_equal(pred.shape, data.shape)
        npt.assert_equal(odf.shape, data.shape[:-1] + (sphere.x.shape[0], ))

        SNR = 1000
        S0 = 100
        mevals = np.array(([0.0015, 0.0005, 0.0005], [0.0015, 0.0005, 0.0005]))
        angles = [(0, 0), (60, 0)]
        S, sticks = sims.multi_tensor(gtab,
                                      mevals,
                                      S0,
                                      angles=angles,
                                      fractions=[50, 50],
                                      snr=SNR)
        sffit = sfmodel.fit(S)
        pred = sffit.predict()
        npt.assert_(xval.coeff_of_determination(pred, S) > 96)
Exemple #11
0
def test_sfm_sklearnlinearsolver():
    class SillySolver(opt.SKLearnLinearSolver):
        def fit(self, X, y):
            self.coef_ = np.ones(X.shape[-1])

    class EvenSillierSolver(object):
        def fit(self, X, y):
            self.coef_ = np.ones(X.shape[-1])

    fdata, fbvals, fbvecs = dpd.get_fnames()
    gtab = grad.gradient_table(fbvals, fbvecs)
    sfmodel = sfm.SparseFascicleModel(gtab, solver=SillySolver())

    npt.assert_(isinstance(sfmodel.solver, SillySolver))
    npt.assert_raises(ValueError,
                      sfm.SparseFascicleModel,
                      gtab,
                      solver=EvenSillierSolver())
Exemple #12
0
from dipy.reconst.csdeconv import auto_response
response, ratio = auto_response(gtab, data, roi_radius=10, fa_thr=0.7)


"""
We initialize an SFM model object, using this response function and using the
default sphere (362  vertices, symmetrically distributed on the surface of the
sphere):
"""

from dipy.data import get_sphere
sphere = get_sphere()
from dipy.reconst import sfm
sf_model = sfm.SparseFascicleModel(gtab, sphere=sphere,
                                   l1_ratio=0.5, alpha=0.001,
                                   response=response[0])

"""
We fit this model to the data in each voxel in the white-matter mask, so that
we can use these directions in tracking:
"""

from dipy.direction.peaks import peaks_from_model

pnm = peaks_from_model(sf_model, data, sphere,
                       relative_peak_threshold=.5,
                       min_separation_angle=25,
                       mask=white_matter,
                       parallel=True
                       )
Exemple #13
0
def test_predict():
    SNR = 1000
    S0 = 100
    _, fbvals, fbvecs = dpd.get_fnames('small_64D')
    bvals, bvecs = read_bvals_bvecs(fbvals, fbvecs)
    gtab = grad.gradient_table(bvals, bvecs)
    mevals = np.array(([0.0015, 0.0003, 0.0003], [0.0015, 0.0003, 0.0003]))
    angles = [(0, 0), (60, 0)]
    S, sticks = sims.multi_tensor(gtab,
                                  mevals,
                                  S0,
                                  angles=angles,
                                  fractions=[10, 90],
                                  snr=SNR)

    sfmodel = sfm.SparseFascicleModel(gtab, response=[0.0015, 0.0003, 0.0003])
    sffit = sfmodel.fit(S)
    pred = sffit.predict()
    npt.assert_(xval.coeff_of_determination(pred, S) > 97)

    # Should be possible to predict using a different gtab:
    new_gtab = grad.gradient_table(bvals[::2], bvecs[::2])
    new_pred = sffit.predict(new_gtab)
    npt.assert_(xval.coeff_of_determination(new_pred, S[::2]) > 97)

    # Should be possible to predict for a single direction:
    with warnings.catch_warnings():
        warnings.simplefilter("ignore", category=UserWarning)
        new_gtab = grad.gradient_table(bvals[1][None], bvecs[1][None, :])
    new_pred = sffit.predict(new_gtab)

    # Fitting and predicting with a volume of data:
    fdata, fbval, fbvec = dpd.get_fnames('small_25')
    gtab = grad.gradient_table(fbval, fbvec)
    data = load_nifti_data(fdata)
    sfmodel = sfm.SparseFascicleModel(gtab, response=[0.0015, 0.0003, 0.0003])
    sffit = sfmodel.fit(data)
    pred = sffit.predict()

    # Should be possible to predict using a different gtab:
    new_gtab = grad.gradient_table(bvals[::2], bvecs[::2])
    new_pred = sffit.predict(new_gtab)
    npt.assert_equal(
        new_pred.shape,
        data.shape[:-1] + bvals[::2].shape,
    )

    # Should be possible to predict for a single direction:
    with warnings.catch_warnings():
        warnings.simplefilter("ignore", category=UserWarning)
        new_gtab = grad.gradient_table(bvals[1][None], bvecs[1][None, :])
    new_pred = sffit.predict(new_gtab)
    npt.assert_equal(new_pred.shape, data.shape[:-1])

    # Fitting and predicting with masked data:
    mask = np.zeros(data.shape[:3])
    mask[2:5, 2:5, :] = 1
    sffit = sfmodel.fit(data, mask=mask)
    pred = sffit.predict()
    npt.assert_equal(pred.shape, data.shape)

    # Should be possible to predict using a different gtab:
    new_gtab = grad.gradient_table(bvals[::2], bvecs[::2])
    new_pred = sffit.predict(new_gtab)
    npt.assert_equal(
        new_pred.shape,
        data.shape[:-1] + bvals[::2].shape,
    )
    npt.assert_equal(new_pred[0, 0, 0], 0)

    # Should be possible to predict for a single direction:
    with warnings.catch_warnings():
        warnings.simplefilter("ignore", category=UserWarning)
        new_gtab = grad.gradient_table(bvals[1][None], bvecs[1][None, :])
    new_pred = sffit.predict(new_gtab)
    npt.assert_equal(new_pred.shape, data.shape[:-1])
    npt.assert_equal(new_pred[0, 0, 0], 0)
Exemple #14
0
    # Load the data:
    img = nib.load(op.join('/input', str(fdata)))
    gtab = grad.gradient_table(op.join('/input', str(fbval)),
                               op.join('/input', str(fbvec)))
    data = img.get_data()
    affine = img.get_affine()

    # Get the optional mask param:
    fmask = metadata.get('fmask', None)
    if fmask is None:
        mask = None
    else:
        mask = nib.load(op.join('/input', fmask)).get_data().astype(bool)

    # Fit the model:
    sfmodel = sfm.SparseFascicleModel(gtab)
    sffit = sfmodel.fit(data, mask=mask)

    # The output will all have the same basic name as the data file-name:
    root = op.join("/output",
                   op.splitext(op.splitext(op.split(fdata)[-1])[0])[0])

    # Save to files:
    dpsave(nib.Nifti1Image(sffit.beta, affine), root + '_SFM_params.nii.gz')
    sf_fa = calc_fa(sffit.beta, sffit.iso)
    dpsave(nib.Nifti1Image(sf_fa, affine), root + '_SFM_FA.nii.gz')
    sphere = dpd.get_sphere()
    sf_di = calc_di(sffit.beta, sphere, mask=mask)
    dpsave(nib.Nifti1Image(sf_di, affine), root + '_SFM_DI.nii.gz')
Exemple #15
0
f_acc = np.zeros((len(par_vec), 2))

Mose_CM_matrix = np.zeros((6, 6, len(par_vec)))
img_mos_mf = np.zeros((sx, sy, sz))
img_mos_mf_matrix = np.zeros((sx, sy, sz, len(par_vec)))

sphere = dpd.get_sphere()

for i_par in tqdm(range(len(par_vec)), ascii=True):

    par = par_vec[i_par]

    sf_model = sfm.SparseFascicleModel(gtab_test,
                                       sphere=sphere,
                                       l1_ratio=0.5,
                                       alpha=par,
                                       response=response[0])
    '''sf_fit = sf_model.fit( hardi_d_img_test_np, mask )
    sf_odf = sf_fit.odf(sphere)'''

    sf_peaks = dpp.peaks_from_model(sf_model,
                                    hardi_d_img_test_np,
                                    sphere,
                                    relative_peak_threshold=0.5,
                                    min_separation_angle=30,
                                    return_sh=False)

    peak_vals = sf_peaks.peak_values
    peak_dirs = sf_peaks.peak_dirs
            for k in range(pmf.shape[2]):
                if fodf_pred_sum[i, j, k] > 0:
                    pmf[i, j, k, :] /= fodf_pred_sum[i, j, k]

    pmf_dipy = pmf.copy()
    print('Finished estimating FODF with DIPY, time elapsed (minutes): ' +
          str(int((time.time() - t1) / 60)))

    del fodf_dipy, pmf

    print('Estimating FODF with sfm')
    t1 = time.time()

    sf_model = sfm.SparseFascicleModel(gtab_0_1000,
                                       sphere=sphere_fod,
                                       l1_ratio=0.5,
                                       alpha=0.001,
                                       response=response_0_1000[0])

    sf_fit = sf_model.fit(d_img_0_1000, mask=mask)  # mask

    odf_sfm = sf_fit.odf(sphere_fod)

    if save_fodf:
        h5f = h5py.File(dav_dir + 'odf_sfm.h5', 'w')
        h5f['odf_sfm'] = odf_sfm
        h5f.close()
    '''
    h5f = h5py.File( dav_dir + 'odf_sfm.h5', 'r')
    odf_sfm = h5f['odf_sfm'][:]
    h5f.close()
Exemple #17
0
def sfm_tracking(name=None,
                 data_path=None,
                 output_path='.',
                 Threshold=.20,
                 data_list=None,
                 return_streamlines=False,
                 save_track=True,
                 seed='.',
                 minus_ROI_mask='.',
                 one_node=False,
                 two_node=False):

    time0 = time.time()
    print("begin loading data, time:", time.time() - time0)

    if data_list == None:
        data, affine, img, labels, gtab, head_mask = get_data(name, data_path)
    else:
        data = data_list['DWI']
        affine = data_list['affine']
        img = data_list['img']
        labels = data_list['labels']
        gtab = data_list['gtab']
        head_mask = data_list['head_mask']

    if type(seed) != str:
        seed_mask = seed
    else:
        seed_mask = (labels == 2) * (head_mask == 1)

    white_matter = (labels == 2) * (head_mask == 1)
    seeds = utils.seeds_from_mask(seed_mask, affine, density=1)

    print('begin reconstruction, time:', time.time() - time0)

    from dipy.reconst.csdeconv import auto_response_ssst
    from dipy.reconst.shm import CsaOdfModel
    from dipy.data import default_sphere
    from dipy.direction import peaks_from_model

    response, ratio = auto_response_ssst(gtab, data, roi_radii=10, fa_thr=0.7)

    sphere = get_sphere()
    sf_model = sfm.SparseFascicleModel(gtab,
                                       sphere=sphere,
                                       l1_ratio=0.5,
                                       alpha=0.001,
                                       response=response[0])

    pnm = peaks_from_model(sf_model,
                           data,
                           sphere,
                           relative_peak_threshold=.5,
                           min_separation_angle=25,
                           mask=white_matter,
                           parallel=True)

    stopping_criterion = ThresholdStoppingCriterion(pnm.gfa, Threshold)
    #seeds = utils.seeds_from_mask(white_matter, affine, density=1)

    print('begin tracking, time:', time.time() - time0)

    streamline_generator = LocalTracking(pnm,
                                         stopping_criterion,
                                         seeds,
                                         affine,
                                         step_size=.5)
    streamlines = Streamlines(streamline_generator)

    print('begin saving, time:', time.time() - time0)

    from dipy.io.stateful_tractogram import Space, StatefulTractogram
    from dipy.io.streamline import save_trk

    if save_track:

        sft = StatefulTractogram(streamlines, img, Space.RASMM)

        if one_node or two_node:
            sft.to_vox()
            streamlines = reduct_seed_ROI(sft.streamlines, seed_mask, one_node,
                                          two_node)

            if type(minus_ROI_mask) != str:
                streamlines = minus_ROI(streamlines=streamlines,
                                        ROI=minus_ROI_mask)

            sft = StatefulTractogram(streamlines, img, Space.VOX)
            sft._vox_to_rasmm()

        output = output_path + '/tractogram_sfm_' + name + '.trk'
        save_trk(sft, output, streamlines)

    if return_streamlines:
        return streamlines