Ejemplo n.º 1
0
def test_run():
    ar1_fname = 'ar1_out.nii'
    funcim = load_image(funcfile)
    fmriims = FmriImageList.from_image(funcim, volume_start_times=2.)
    one_vol = fmriims[0]
    # Formula - with an intercept
    t = Term('t')
    f = Formula([t, t**2, t**3, 1])
    # Design matrix and contrasts
    time_vector = make_recarray(fmriims.volume_start_times, 't')
    con_defs = dict(c=t, c2=t+t**2)
    desmtx, cmatrices = f.design(time_vector, contrasts=con_defs)

    # Run with Image and ImageList
    for inp_img in (rollimg(funcim, 't'), fmriims):
        with InTemporaryDirectory():
            # Run OLS model
            outputs = []
            outputs.append(model.output_AR1(ar1_fname, fmriims))
            outputs.append(model.output_resid('resid_OLS_out.nii', fmriims))
            ols = model.OLS(fmriims, f, outputs)
            ols.execute()
            # Run AR1 model
            outputs = []
            outputs.append(
                model.output_T('T_out.nii', cmatrices['c'], fmriims))
            outputs.append(
                model.output_F('F_out.nii', cmatrices['c2'], fmriims))
            outputs.append(
                model.output_resid('resid_AR_out.nii', fmriims))
            rho = load_image(ar1_fname)
            ar = model.AR1(fmriims, f, rho, outputs)
            ar.execute()
            f_img = load_image('F_out.nii')
            assert_equal(f_img.shape, one_vol.shape)
            f_data = f_img.get_data()
            assert_true(np.all((f_data>=0) & (f_data<30)))
            resid_img = load_image('resid_AR_out.nii')
            assert_equal(resid_img.shape, funcim.shape)
            assert_array_almost_equal(np.mean(resid_img.get_data()), 0, 3)
            e_img = load_image('T_out_effect.nii')
            sd_img = load_image('T_out_sd.nii')
            t_img = load_image('T_out_t.nii')
            t_data = t_img.get_data()
            assert_array_almost_equal(t_data,
                                      e_img.get_data() / sd_img.get_data())
            assert_true(np.all(np.abs(t_data) < 6))
            # Need to delete to help windows delete temporary files
            del rho, resid_img, f_img, e_img, sd_img, t_img, f_data, t_data
Ejemplo n.º 2
0
def test_run():
    ar1_fname = 'ar1_out.nii'
    funcim = load_image(funcfile)
    fmriims = FmriImageList.from_image(funcim, volume_start_times=2.)
    one_vol = fmriims[0]
    # Formula - with an intercept
    t = Term('t')
    f = Formula([t, t**2, t**3, 1])
    # Design matrix and contrasts
    time_vector = make_recarray(fmriims.volume_start_times, 't')
    con_defs = dict(c=t, c2=t + t**2)
    desmtx, cmatrices = f.design(time_vector, contrasts=con_defs)

    # Run with Image and ImageList
    for inp_img in (rollimg(funcim, 't'), fmriims):
        with InTemporaryDirectory():
            # Run OLS model
            outputs = []
            outputs.append(model.output_AR1(ar1_fname, fmriims))
            outputs.append(model.output_resid('resid_OLS_out.nii', fmriims))
            ols = model.OLS(fmriims, f, outputs)
            ols.execute()
            # Run AR1 model
            outputs = []
            outputs.append(model.output_T('T_out.nii', cmatrices['c'],
                                          fmriims))
            outputs.append(
                model.output_F('F_out.nii', cmatrices['c2'], fmriims))
            outputs.append(model.output_resid('resid_AR_out.nii', fmriims))
            rho = load_image(ar1_fname)
            ar = model.AR1(fmriims, f, rho, outputs)
            ar.execute()
            f_img = load_image('F_out.nii')
            assert_equal(f_img.shape, one_vol.shape)
            f_data = f_img.get_data()
            assert_true(np.all((f_data >= 0) & (f_data < 30)))
            resid_img = load_image('resid_AR_out.nii')
            assert_equal(resid_img.shape, funcim.shape)
            assert_array_almost_equal(np.mean(resid_img.get_data()), 0, 3)
            e_img = load_image('T_out_effect.nii')
            sd_img = load_image('T_out_sd.nii')
            t_img = load_image('T_out_t.nii')
            t_data = t_img.get_data()
            assert_array_almost_equal(t_data,
                                      e_img.get_data() / sd_img.get_data())
            assert_true(np.all(np.abs(t_data) < 6))
            # Need to delete to help windows delete temporary files
            del rho, resid_img, f_img, e_img, sd_img, t_img, f_data, t_data
Ejemplo n.º 3
0
def run_model(subj, run):
    """
    Single subject fitting of FIAC model
    """
    #----------------------------------------------------------------------
    # Set initial parameters of the FIAC dataset
    #----------------------------------------------------------------------
    # Number of volumes in the fMRI data
    nvol = 121
    # The TR of the experiment
    TR = 2.5
    # The time of the first volume
    Tstart = 0.0
    # The array of times corresponding to each volume in the fMRI data
    volume_times = np.arange(nvol) * TR + Tstart
    # This recarray of times has one column named 't'.  It is used in the
    # function design.event_design to create the design matrices.
    volume_times_rec = make_recarray(volume_times, 't')
    # Get a path description dictionary that contains all the path data relevant
    # to this subject/run
    path_info = futil.path_info_run(subj,run)

    #----------------------------------------------------------------------
    # Experimental design
    #----------------------------------------------------------------------

    # Load the experimental description from disk.  We have utilities in futil
    # that reformat the original FIAC-supplied format into something where the
    # factorial structure of the design is more explicit.  This has already
    # been run once, and get_experiment_initial() will simply load the
    # newly-formatted design description files (.csv) into record arrays.
    experiment = futil.get_experiment(path_info)

    # Create design matrices for the "initial" and "experiment" factors, saving
    # the default contrasts.

    # The function event_design will create design matrices, which in the case
    # of "experiment" will have num_columns = (# levels of speaker) * (# levels
    # of sentence) * len(delay.spectral) = 2 * 2 * 2 = 8. For "initial", there
    # will be (# levels of initial) * len([hrf.glover]) = 1 * 1 = 1.

    # Here, delay.spectral is a sequence of 2 symbolic HRFs that are described
    # in:
    #
    # Liao, C.H., Worsley, K.J., Poline, J-B., Aston, J.A.D., Duncan, G.H.,
    #    Evans, A.C. (2002). \'Estimating the delay of the response in fMRI
    #    data.\' NeuroImage, 16:593-606.

    # The contrast definitions in ``cons_exper`` are a dictionary with keys
    # ['constant_0', 'constant_1', 'speaker_0', 'speaker_1', 'sentence_0',
    # 'sentence_1', 'sentence:speaker_0', 'sentence:speaker_1'] representing the
    # four default contrasts: constant, main effects + interactions, each
    # convolved with 2 HRFs in delay.spectral. For example, sentence:speaker_0
    # is the interaction of sentence and speaker convolved with the first (=0)
    # of the two HRF basis functions, and sentence:speaker_1 is the interaction
    # convolved with the second (=1) of the basis functions.

    # XXX use the hrf __repr__ for naming contrasts
    X_exper, cons_exper = design.block_design(experiment, volume_times_rec,
                                              hrfs=delay.spectral,
                                              level_contrasts=True)

    # In addition to factors, there is typically a "drift" term. In this case,
    # the drift is a natural cubic spline with a not at the midpoint
    # (volume_times.mean())
    vt = volume_times # shorthand
    drift = np.array( [vt**i for i in range(4)] +
                      [(vt-vt.mean())**3 * (np.greater(vt, vt.mean()))] )
    for i in range(drift.shape[0]):
        drift[i] /= drift[i].max()

    # We transpose the drift so that its shape is (nvol,5) so that it will have
    # the same number of rows as X_exper.
    drift = drift.T

    # There are helper functions to create these drifts: design.fourier_basis,
    # design.natural_spline.  Therefore, the above is equivalent (except for
    # the normalization by max for numerical stability) to
    #
    # >>> drift = design.natural_spline(t, [volume_times.mean()])

    # Stack all the designs, keeping the new contrasts which has the same keys
    # as cons_exper, but its values are arrays with 15 columns, with the
    # non-zero entries matching the columns of X corresponding to X_exper
    X, cons = design.stack_designs((X_exper, cons_exper),
                                   (drift, {}))

    # Sanity check: delete any non-estimable contrasts
    for k in cons.keys():
        if not isestimable(cons[k], X):
            del(cons[k])
            warnings.warn("contrast %s not estimable for this run" % k)

    # The default contrasts are all t-statistics.  We may want to output
    # F-statistics for 'speaker', 'sentence', 'speaker:sentence' based on the
    # two coefficients, one for each HRF in delay.spectral

    # We reproduce the same constrasts as in the data base
    # outputting an F using both HRFs, as well as the
    # t using only the first HRF

    for obj1, obj2 in [('face', 'scrambled'),
                       ('house', 'scrambled'),
                       ('chair', 'scrambled'),
                       ('face', 'house')]:
        cons['%s_vs_%s_F' % (obj1, obj2)] = \
            np.vstack([cons['object_%s_0' % obj1] - 
                       cons['object_%s_0' % obj2],
                       cons['object_%s_1' % obj1] - 
                       cons['object_%s_1' % obj2]])


        cons['%s_vs_%s_t' % (obj1, obj2)] = (cons['object_%s_0' % obj1] - 
                                             cons['object_%s_0' % obj2])

    #----------------------------------------------------------------------
    # Data loading
    #----------------------------------------------------------------------

    # Load in the fMRI data, saving it as an array.  It is transposed to have
    # time as the first dimension, i.e. fmri[t] gives the t-th volume.
    fmri_im = futil.get_fmri(path_info) # an Image
    fmri_im = rollimg(fmri_im, 't')
    fmri = fmri_im.get_data() # now, it's an ndarray

    nvol, volshape = fmri.shape[0], fmri.shape[1:]
    nx, sliceshape = volshape[0], volshape[1:]

    #----------------------------------------------------------------------
    # Model fit
    #----------------------------------------------------------------------

    # The model is a two-stage model, the first stage being an OLS (ordinary
    # least squares) fit, whose residuals are used to estimate an AR(1)
    # parameter for each voxel.
    m = OLSModel(X)
    ar1 = np.zeros(volshape)

    # Fit the model, storing an estimate of an AR(1) parameter at each voxel
    for s in range(nx):
        d = np.array(fmri[:,s])
        flatd = d.reshape((d.shape[0], -1))
        result = m.fit(flatd)
        ar1[s] = ((result.resid[1:] * result.resid[:-1]).sum(0) /
                  (result.resid**2).sum(0)).reshape(sliceshape)

    # We round ar1 to nearest one-hundredth and group voxels by their rounded
    # ar1 value, fitting an AR(1) model to each batch of voxels.

    # XXX smooth here?
    # ar1 = smooth(ar1, 8.0)
    ar1 *= 100
    ar1 = ar1.astype(np.int) / 100.

    # We split the contrasts into F-tests and t-tests.
    # XXX helper function should do this
    fcons = {}; tcons = {}
    for n, v in cons.items():
        v = np.squeeze(v)
        if v.ndim == 1:
            tcons[n] = v
        else:
            fcons[n] = v

    # Setup a dictionary to hold all the output
    # XXX ideally these would be memmap'ed Image instances
    output = {}
    for n in tcons:
        tempdict = {}
        for v in ['sd', 't', 'effect']:
            tempdict[v] = np.memmap(NamedTemporaryFile(prefix='%s%s.nii'
                                    % (n,v)), dtype=np.float,
                                    shape=volshape, mode='w+')
        output[n] = tempdict

    for n in fcons:
        output[n] = np.memmap(NamedTemporaryFile(prefix='%s%s.nii'
                                    % (n,v)), dtype=np.float,
                                    shape=volshape, mode='w+')

    # Loop over the unique values of ar1
    for val in np.unique(ar1):
        armask = np.equal(ar1, val)
        m = ARModel(X, val)
        d = fmri[:,armask]
        results = m.fit(d)

        # Output the results for each contrast
        for n in tcons:
            resT = results.Tcontrast(tcons[n])
            output[n]['sd'][armask] = resT.sd
            output[n]['t'][armask] = resT.t
            output[n]['effect'][armask] = resT.effect
        for n in fcons:
            output[n][armask] = results.Fcontrast(fcons[n]).F

    # Dump output to disk
    odir = futil.output_dir(path_info,tcons,fcons)
    # The coordmap for a single volume in the time series
    vol0_map = fmri_im[0].coordmap
    for n in tcons:
        for v in ['t', 'sd', 'effect']:
            im = Image(output[n][v], vol0_map)
            save_image(im, pjoin(odir, n, '%s.nii' % v))
    for n in fcons:
        im = Image(output[n], vol0_map)
        save_image(im, pjoin(odir, n, "F.nii"))
Ejemplo n.º 4
0
def run_model(subj, run):
    """
    Single subject fitting of OpenfMRI ds105 model
    """
    #----------------------------------------------------------------------
    # Set initial parameters of the OpenfMRI ds105 dataset
    #----------------------------------------------------------------------
    # Number of volumes in the fMRI data
    nvol = 121
    # The TR of the experiment
    TR = 2.5
    # The time of the first volume
    Tstart = 0.0
    # The array of times corresponding to each volume in the fMRI data
    volume_times = np.arange(nvol) * TR + Tstart
    # This recarray of times has one column named 't'.  It is used in the
    # function design.event_design to create the design matrices.
    volume_times_rec = make_recarray(volume_times, 't')
    # Get a path description dictionary that contains all the path data relevant
    # to this subject/run
    path_info = futil.path_info_run(subj, run)

    #----------------------------------------------------------------------
    # Experimental design
    #----------------------------------------------------------------------

    # Load the experimental description from disk.  We have utilities in futil
    # that reformat the original OpenfMRI ds105-supplied format into something
    # where the factorial structure of the design is more explicit.  This has
    # already been run once, and get_experiment_initial() will simply load the
    # newly-formatted design description files (.csv) into record arrays.
    experiment = futil.get_experiment(path_info)

    # Create design matrices for the "initial" and "experiment" factors, saving
    # the default contrasts.

    # The function event_design will create design matrices, which in the case
    # of "experiment" will have num_columns = (# levels of speaker) * (# levels
    # of sentence) * len(delay.spectral) = 2 * 2 * 2 = 8. For "initial", there
    # will be (# levels of initial) * len([hrf.glover]) = 1 * 1 = 1.

    # Here, delay.spectral is a sequence of 2 symbolic HRFs that are described
    # in:
    #
    # Liao, C.H., Worsley, K.J., Poline, J-B., Aston, J.A.D., Duncan, G.H.,
    #    Evans, A.C. (2002). \'Estimating the delay of the response in fMRI
    #    data.\' NeuroImage, 16:593-606.

    # The contrast definitions in ``cons_exper`` are a dictionary with keys
    # ['constant_0', 'constant_1', 'speaker_0', 'speaker_1', 'sentence_0',
    # 'sentence_1', 'sentence:speaker_0', 'sentence:speaker_1'] representing the
    # four default contrasts: constant, main effects + interactions, each
    # convolved with 2 HRFs in delay.spectral. For example, sentence:speaker_0
    # is the interaction of sentence and speaker convolved with the first (=0)
    # of the two HRF basis functions, and sentence:speaker_1 is the interaction
    # convolved with the second (=1) of the basis functions.

    # XXX use the hrf __repr__ for naming contrasts
    X_exper, cons_exper = design.block_design(experiment,
                                              volume_times_rec,
                                              hrfs=delay.spectral,
                                              level_contrasts=True)

    # In addition to factors, there is typically a "drift" term. In this case,
    # the drift is a natural cubic spline with a not at the midpoint
    # (volume_times.mean())
    vt = volume_times  # shorthand
    drift = np.array([vt**i for i in range(4)] + [(vt - vt.mean())**3 *
                                                  (np.greater(vt, vt.mean()))])
    for i in range(drift.shape[0]):
        drift[i] /= drift[i].max()

    # We transpose the drift so that its shape is (nvol,5) so that it will have
    # the same number of rows as X_exper.
    drift = drift.T

    # There are helper functions to create these drifts: design.fourier_basis,
    # design.natural_spline.  Therefore, the above is equivalent (except for
    # the normalization by max for numerical stability) to
    #
    # >>> drift = design.natural_spline(t, [volume_times.mean()])

    # Stack all the designs, keeping the new contrasts which has the same keys
    # as cons_exper, but its values are arrays with 15 columns, with the
    # non-zero entries matching the columns of X corresponding to X_exper
    X, cons = design.stack_designs((X_exper, cons_exper), (drift, {}))

    # Sanity check: delete any non-estimable contrasts
    for k in cons.keys():
        if not isestimable(cons[k], X):
            del (cons[k])
            warnings.warn("contrast %s not estimable for this run" % k)

    # The default contrasts are all t-statistics.  We may want to output
    # F-statistics for 'speaker', 'sentence', 'speaker:sentence' based on the
    # two coefficients, one for each HRF in delay.spectral

    # We reproduce the same constrasts as in the data base
    # outputting an F using both HRFs, as well as the
    # t using only the first HRF

    for obj1, obj2 in [('face', 'scrambled'), ('house', 'scrambled'),
                       ('chair', 'scrambled'), ('face', 'house')]:
        cons['%s_vs_%s_F' % (obj1, obj2)] = \
            np.vstack([cons['object_%s_0' % obj1] -
                       cons['object_%s_0' % obj2],
                       cons['object_%s_1' % obj1] -
                       cons['object_%s_1' % obj2]])

        cons['%s_vs_%s_t' % (obj1, obj2)] = (cons['object_%s_0' % obj1] -
                                             cons['object_%s_0' % obj2])

    #----------------------------------------------------------------------
    # Data loading
    #----------------------------------------------------------------------

    # Load in the fMRI data, saving it as an array.  It is transposed to have
    # time as the first dimension, i.e. fmri[t] gives the t-th volume.
    fmri_im = futil.get_fmri(path_info)  # an Image
    fmri_im = rollimg(fmri_im, 't')
    fmri = fmri_im.get_data()  # now, it's an ndarray

    nvol, volshape = fmri.shape[0], fmri.shape[1:]
    nx, sliceshape = volshape[0], volshape[1:]

    #----------------------------------------------------------------------
    # Model fit
    #----------------------------------------------------------------------

    # The model is a two-stage model, the first stage being an OLS (ordinary
    # least squares) fit, whose residuals are used to estimate an AR(1)
    # parameter for each voxel.
    m = OLSModel(X)
    ar1 = np.zeros(volshape)

    # Fit the model, storing an estimate of an AR(1) parameter at each voxel
    for s in range(nx):
        d = np.array(fmri[:, s])
        flatd = d.reshape((d.shape[0], -1))
        result = m.fit(flatd)
        ar1[s] = ((result.resid[1:] * result.resid[:-1]).sum(0) /
                  (result.resid**2).sum(0)).reshape(sliceshape)

    # We round ar1 to nearest one-hundredth and group voxels by their rounded
    # ar1 value, fitting an AR(1) model to each batch of voxels.

    # XXX smooth here?
    # ar1 = smooth(ar1, 8.0)
    ar1 *= 100
    ar1 = ar1.astype(np.int) / 100.

    # We split the contrasts into F-tests and t-tests.
    # XXX helper function should do this
    fcons = {}
    tcons = {}
    for n, v in cons.items():
        v = np.squeeze(v)
        if v.ndim == 1:
            tcons[n] = v
        else:
            fcons[n] = v

    # Setup a dictionary to hold all the output
    # XXX ideally these would be memmap'ed Image instances
    output = {}
    for n in tcons:
        tempdict = {}
        for v in ['sd', 't', 'effect']:
            tempdict[v] = np.memmap(NamedTemporaryFile(prefix='%s%s.nii' %
                                                       (n, v)),
                                    dtype=np.float,
                                    shape=volshape,
                                    mode='w+')
        output[n] = tempdict

    for n in fcons:
        output[n] = np.memmap(NamedTemporaryFile(prefix='%s%s.nii' % (n, v)),
                              dtype=np.float,
                              shape=volshape,
                              mode='w+')

    # Loop over the unique values of ar1
    for val in np.unique(ar1):
        armask = np.equal(ar1, val)
        m = ARModel(X, val)
        d = fmri[:, armask]
        results = m.fit(d)

        # Output the results for each contrast
        for n in tcons:
            resT = results.Tcontrast(tcons[n])
            output[n]['sd'][armask] = resT.sd
            output[n]['t'][armask] = resT.t
            output[n]['effect'][armask] = resT.effect
        for n in fcons:
            output[n][armask] = results.Fcontrast(fcons[n]).F

    # Dump output to disk
    odir = futil.output_dir(path_info, tcons, fcons)
    # The coordmap for a single volume in the time series
    vol0_map = fmri_im[0].coordmap
    for n in tcons:
        for v in ['t', 'sd', 'effect']:
            im = Image(output[n][v], vol0_map)
            save_image(im, pjoin(odir, n, '%s.nii' % v))
    for n in fcons:
        im = Image(output[n], vol0_map)
        save_image(im, pjoin(odir, n, "F.nii"))
Ejemplo n.º 5
0

def setup():
    # Suppress warnings during tests to reduce noise
    warnings.simplefilter("ignore")


def teardown():
    # Clear list of warning filters
    warnings.resetwarnings()


# Module globals
FIMG = load_image(funcfile)
# Put time on first axis
FIMG = rollimg(FIMG, 't')
FDATA = FIMG.get_data()
FIL = FmriImageList.from_image(FIMG)

# I think it makes more sense to use FDATA instead of FIL for GLM
# purposes -- reduces some noticeable overhead in creating the
# array from FmriImageList

# create a design matrix, model and contrast matrix
DESIGN = noise((FDATA.shape[0], 3))
MODEL = OLSModel(DESIGN)
CMATRIX = np.array([[1, 0, 0], [0, 1, 0]])


# two prototypical functions in a GLM analysis
def fit(input):
Ejemplo n.º 6
0

def setup():
    # Suppress warnings during tests to reduce noise
    warnings.simplefilter("ignore")


def teardown():
    # Clear list of warning filters
    warnings.resetwarnings()


# Module globals
FIMG = load_image(funcfile)
# Put time on first axis
FIMG = rollimg(FIMG, 't')
FDATA = FIMG.get_data()
FIL = FmriImageList.from_image(FIMG)

# I think it makes more sense to use FDATA instead of FIL for GLM
# purposes -- reduces some noticeable overhead in creating the
# array from FmriImageList

# create a design matrix, model and contrast matrix
DESIGN = noise((FDATA.shape[0],3))
MODEL = OLSModel(DESIGN)
CMATRIX = np.array([[1,0,0],[0,1,0]])

# two prototypical functions in a GLM analysis
def fit(input):
    return MODEL.fit(input).resid