def test_noresample_stimulus(): # stimulus features viewing_distance = 38 screen_width = 25 thetas = np.arange(0,360,90) num_blank_steps = 0 num_bar_steps = 30 ecc = 12 tr_length = 1.0 frames_per_tr = 1.0 scale_factor = 1.0 pixels_across = 100 pixels_down = 100 dtype = ctypes.c_int16 Ns = 3 voxel_index = (1,2,3) auto_fit = True verbose = 1 # create the sweeping bar stimulus in memory bar = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc) # create an instance of the Stimulus class stimulus = VisualStimulus(bar, viewing_distance, screen_width, scale_factor, tr_length, dtype) # stimulus npt.assert_equal(stimulus.stim_arr.shape[0:2],stimulus.stim_arr0.shape[0:2]) npt.assert_equal(stimulus.deg_x.shape,stimulus.deg_x0.shape) npt.assert_equal(stimulus.deg_y.shape,stimulus.deg_y0.shape)
def generate_stimulus(bars): tr_length = 1.0 scale_factor = 1.0 dtype = c_int16 stimulus = VisualStimulus(bars, VIEWING_DISTANCE, SCREEN_WIDTH, scale_factor, tr_length, dtype) return stimulus
def __init__(self, dm, viewing_distance, screen_width, tr_dm): self.stimulus = VisualStimulus(stim_arr=dm, viewing_distance=viewing_distance, screen_width=screen_width, scale_factor=1, tr_length=tr_dm, dtype=np.short) self.model_func = OGModel.GaussianModel(stimulus=self.stimulus, hrf_model=utils.spm_hrf) self.model_func.hrf_delay = 0 self.predictions = None
def test_resurrect_model(): # stimulus features viewing_distance = 38 screen_width = 25 thetas = np.arange(0,360,90) thetas = np.insert(thetas,0,-1) thetas = np.append(thetas,-1) num_blank_steps = 20 num_bar_steps = 20 ecc = 10 tr_length = 1.5 frames_per_tr = 1.0 scale_factor = 0.50 pixels_across = 100 pixels_down = 100 dtype = ctypes.c_int16 # create the sweeping bar stimulus in memory bar = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc, clip=0.01) # create an instance of the Stimulus class stimulus = VisualStimulus(bar, viewing_distance, screen_width, scale_factor, tr_length, dtype) # set cache grids x_grid = utils.grid_slice(-10, 10, 5) y_grid = utils.grid_slice(-10, 10, 5) s_grid = utils.grid_slice(0.55,5.25, 5) grids = (x_grid, y_grid, s_grid,) # initialize the gaussian model model = og.GaussianModel(stimulus, utils.spm_hrf) model.hrf_delay = 0 model.mask_size = 5 # seed rng np.random.seed(4932) # cache the model cache = model.cache_model(grids, ncpus=3) # resurrect cached model cached_model_path = '/tmp/og_cached_model.pkl' model = og.GaussianModel(stimulus, utils.double_gamma_hrf, cached_model_path=cached_model_path) model.hrf_delay = 0 model.mask_size = 5 # make sure the same nt.assert_true(np.sum([c[0] for c in cache] - model.cached_model_timeseries) == 0) nt.assert_true(np.sum([c[1] for c in cache] - model.cached_model_parameters) == 0)
def test_cache_model_Ns(): # stimulus features viewing_distance = 38 screen_width = 25 thetas = np.arange(0,360,90) thetas = np.insert(thetas,0,-1) thetas = np.append(thetas,-1) num_blank_steps = 20 num_bar_steps = 20 ecc = 10 tr_length = 1.5 frames_per_tr = 1.0 scale_factor = 0.50 pixels_across = 100 pixels_down = 100 dtype = ctypes.c_int16 Ns = 5 # create the sweeping bar stimulus in memory bar = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc, clip=0.01) # create an instance of the Stimulus class stimulus = VisualStimulus(bar, viewing_distance, screen_width, scale_factor, tr_length, dtype) # initialize the gaussian model model = og.GaussianModel(stimulus, utils.spm_hrf) model.hrf_delay = 0 model.mask_size = 5 # set cache grids x_grid = (-10, 10) y_grid = (-10, 10) s_grid = (0.55,5.25) grids = (x_grid, y_grid, s_grid,) # seed rng np.random.seed(4932) # cache the pRF model cache = model.cache_model(grids, Ns=Ns, ncpus=3) # save it out pickle.dump(cache, open('/tmp/og_cached_model.pkl','wb')) # make sure its the right size cached_model = pickle.load(open('/tmp/og_cached_model.pkl','rb')) nt.assert_equal(np.sum([c[0] for c in cache]),np.sum([c[0] for c in cached_model]))
def __init__(self, data, fit_model, visual_design, screen_distance, screen_width, scale_factor, tr, bound_grids, grid_steps, bound_fits, n_jobs, hrf, sg_filter_window_length=210, sg_filter_polyorder=3, sg_filter_deriv=0, nr_TRs=103): # immediately convert nans to nums self.data = np.nan_to_num(data) self.data_var = self.data.var(axis=-1) self.n_units = self.data.shape[0] self.n_timepoints = self.data.shape[1] self.hrf = hrf self.nr_TRs = nr_TRs self.stimulus = VisualStimulus(stim_arr=visual_design, viewing_distance=screen_distance, screen_width=screen_width, scale_factor=scale_factor, tr_length=tr, dtype=np.short) #assert self.n_timepoints == self.stimulus.run_length, \ # "Data and design matrix do not have the same nr of timepoints, %i vs %i!"%(self.n_timepoints, self.stimulus.run_length) if fit_model == 'gauss': self.model_func = GaussianModel(stimulus=self.stimulus, hrf=self.hrf, nr_TRs=self.nr_TRs) self.model_func.hrf_delay = 0 self.predictions = None self.fit_model = fit_model self.bound_grids = bound_grids self.grid_steps = grid_steps self.bound_fits = bound_fits self.n_jobs = n_jobs
def fit_voxel(tup): (ii, vx, js) = tup stdat = js['Stimulus'] if pimms.is_list(stdat): stdat = stdat[0] height = stdat['fieldofviewVert'] width = stdat['fieldofviewHorz'] ### STIMULUS # First get a viewing distance and screen size dist = 100 # 100 cm is arbitrary stim_width = 2 * dist * np.tan(np.pi/180 * width/2) stimulus = VisualStimulus(stim, dist, stim_width, 1.0, float(js['TR']), ctypes.c_int16) if fixed_hrf is not False: model = og_nohrf.GaussianModel(stimulus, utils.double_gamma_hrf) model.hrf_delay = fixed_hrf else: model = og.GaussianModel(stimulus, utils.double_gamma_hrf) ### FIT ## define search grids # these define min and max of the edge of the initial brute-force search. x_grid = (-width/2,width/2) y_grid = (-height/2,height/2) s_grid = (1/stimulus.ppd + 0.25, 5.25) h_grid = (-1.0, 1.0) ## define search bounds # these define the boundaries of the final gradient-descent search. x_bound = (-width, width) y_bound = (-height, height) s_bound = (1/stimulus.ppd, 12.0) # smallest sigma is a pixel b_bound = (1e-8,None) u_bound = (None,None) h_bound = (-3.0,3.0) ## package the grids and bounds if fixed_hrf is not False: grids = (x_grid, y_grid, s_grid) bounds = (x_bound, y_bound, s_bound, b_bound, u_bound,) else: grids = (x_grid, y_grid, s_grid, h_grid) bounds = (x_bound, y_bound, s_bound, h_bound, b_bound, u_bound,) ## fit the response # auto_fit = True fits the model on assignment # verbose = 0 is silent # verbose = 1 is a single print # verbose = 2 is very verbose if fixed_hrf is not False: fit = og_nohrf.GaussianFit(model, vx, grids, bounds, Ns=Ns, voxel_index=(ii, 1, 1), auto_fit=True, verbose=2) else: fit = og.GaussianFit(model, vx, grids, bounds, Ns=Ns, voxel_index=(ii, 1, 1), auto_fit=True, verbose=2) return (ii, vx) + tuple(fit.overloaded_estimate) + (fit.prediction,)
def test_resample_stimulus(): # stimulus features viewing_distance = 38 screen_width = 25 thetas = np.arange(0,360,90) num_blank_steps = 0 num_bar_steps = 30 ecc = 12 tr_length = 1.0 frames_per_tr = 1.0 scale_factor = 0.50 pixels_across = 100 pixels_down = 100 dtype = ctypes.c_int16 Ns = 3 voxel_index = (1,2,3) auto_fit = True verbose = 1 # create the sweeping bar stimulus in memory bar = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc) # create an instance of the Stimulus class stimulus = VisualStimulus(bar, viewing_distance, screen_width, scale_factor, tr_length, dtype) # grab the stimulus dimensions stim_dims = stimulus.stim_arr.shape stim_coarse_dims = stimulus.stim_arr0.shape # assert nt.assert_true(stim_coarse_dims[0]/stim_dims[0] == scale_factor) nt.assert_true(stim_coarse_dims[1]/stim_dims[1] == scale_factor) nt.assert_true(stim_coarse_dims[2] == stim_dims[2]) npt.assert_array_equal(np.unique(stimulus.stim_arr0), [0, 1]) # make sure the duty-cycle doesn't change with resampling npt.assert_almost_equal(np.sum(stimulus.stim_arr0==1)/np.sum(stimulus.stim_arr0>-1),np.sum(stimulus.stim_arr==1)/np.sum(stimulus.stim_arr>-1),3)
def read_prf_stimuli(n_vols=(224, 224)): img = loadmat('/Fridge/users/margriet/stimuli/BAIR_pRF/bar_apertures.mat') images = img['bar_apertures'] baseline = int(11.9 / 0.85) b_img = zeros((images.shape[0], images.shape[1], baseline)) c = concatenate((b_img, images, b_img), 2) all_img = [] for n_vol in n_vols: all_img.append(c[:, :, :n_vol].copy()) st = concatenate(all_img, 2) st = resize(st, (100, 100), anti_aliasing=True) stimulus = VisualStimulus(st, 112, 32, scale_factor=0.1, tr_length=0.85, dtype=c_short) return stimulus
def setup_data_from_h5(data_file, n_pix, extent=[-5,5], screen_distance=225, screen_width=69.0, rsq_threshold=0.5, TR=0.945, cv_fold=1, n_folds=6, use_median=True, mask_name = 'V1'): hdf5_file = get_figshare_data(data_file) ############################################################################################################################################ # getting the data ############################################################################################################################################ # timecourses are single-run psc data, either original or leave-one-out. timecourse_data_single_run = roi_data_from_hdf(['*psc'],mask_name, hdf5_file,'psc').astype(np.float64) timecourse_data_loo = roi_data_from_hdf(['*loo'],mask_name, hdf5_file,'loo').astype(np.float64) timecourse_data_all_psc = roi_data_from_hdf(['*av'],mask_name, hdf5_file,'all_psc').astype(np.float64) # prfs are per-run, as fit using the loo data all_prf_data = roi_data_from_hdf(['*all'],mask_name, hdf5_file,'all_prf').astype(np.float64) prf_data = roi_data_from_hdf(['*all'],mask_name, hdf5_file,'prf').astype(np.float64).reshape((all_prf_data.shape[0], -1, all_prf_data.shape[-1])) dm=create_visual_designmatrix_all(n_pixels=n_pix) if use_median: dm_crossv = dm else: dm_crossv = np.tile(dm,(1,1,n_folds-1)) # apply pixel mask to design matrix, as we also do this to the prf profiles. mask = dm.sum(axis = -1, dtype = bool) dm = dm[mask,:] # voxel mask for crossvalidation # only count those voxels here that have positive rsq rsq_crossv = np.mean(prf_data[:,:,-1], axis=1) * np.sign(np.mean(prf_data[:,:,4], axis=1)) rsq_mask_crossv = rsq_crossv > rsq_threshold # determine amount of trs nr_TRs = int(timecourse_data_single_run.shape[-1] / n_folds) # now, mask the data and select for this fold test_data = timecourse_data_single_run[rsq_mask_crossv,nr_TRs*cv_fold:nr_TRs*(cv_fold+1)] if use_median: train_data = timecourse_data_loo[rsq_mask_crossv,nr_TRs*cv_fold:nr_TRs*(cv_fold+1)] else: train_data = np.delete(timecourse_data_single_run[rsq_mask_crossv,:], np.s_[nr_TRs*cv_fold:nr_TRs*(cv_fold+1)], axis=1) # set up the prf_data variable needed for decoding prf_cv_fold_data = prf_data[rsq_mask_crossv,cv_fold] # rescale the data #sign=np.sign(train_data) #train_data -= prf_cv_fold_data[:, 5, np.newaxis] #train_data /= prf_cv_fold_data[:, 4, np.newaxis] #train_data = sign * np.abs(train_data)**(1.0/prf_cv_fold_data[:, 3, np.newaxis]) #test_data -= prf_cv_fold_data[:, 5, np.newaxis] #test_data /= prf_cv_fold_data[:, 4, np.newaxis] ############################################################################################################################################ # setting up prf timecourses - NOTE, this is for the 'all' situation, so should be really done on a run-by-run basis using a run's # loo data and prf parameters. A test set would then be taken from the single_run data as this hasn't been used for that run's fit. ############################################################################################################################################ # set up model with hrf etc. def my_spmt(delay, tr): return spmt(np.arange(0, 33, tr)) # we're going to use these popeye convenience functions # because they are fast, and because they were used in the fitting procedure stimulus = VisualStimulus(dm_crossv, screen_distance, screen_width, 1.0, TR, ctypes.c_int16) css_model = CompressiveSpatialSummationModelFiltered(stimulus, my_spmt) css_model.hrf_delay = 0 ############################################################################################################################################ # setting up prf spatial profiles for subsequent covariances, now some per-run stuff was done ############################################################################################################################################ # indices into prf output array: # 0: X # 1: Y # 2: s (size, standard deviation of gauss) # 3: n (nonlinearity power) # 4: a (amplitude) # 5: b (baseline, intercept value) # 6: rsq per-run # 7: rsq across all # deg_x, deg_y = np.meshgrid(np.linspace(extent[0], extent[1], n_pix, endpoint=True), np.linspace( extent[0], extent[1], n_pix, endpoint=True)) rfs = generate_og_receptive_fields( prf_data[rsq_mask_crossv, cv_fold, 0], prf_data[rsq_mask_crossv, cv_fold, 1], prf_data[rsq_mask_crossv, cv_fold, 2], np.ones((rsq_mask_crossv.sum())), deg_x, deg_y) #this step is used in the css model rfs_normal = rfs / ((2 * np.pi * prf_data[rsq_mask_crossv, cv_fold, 2]**2) * 1 /np.diff(css_model.stimulus.deg_x[0, 0:2])**2) #rfs **= prf_cv_fold_data[:, 3] #WARNING: CSS-like normalisation does not work well at all. simply divide by the sum for simplicity? #for i in range(rfs_normal.shape[2]): # rfs_normal[:,:,i]/=np.sum(rfs_normal[:,:,i]) #pl.imshow(rfs[:,:,3]) #print(np.sum(rfs_normal[:,:,0])) #print(np.sum(rfs_normal[:,:,1])) #print(np.sum(rfs_normal[:,:,2])) #print(np.sum(rfs_normal[:,:,3])) #print(np.sum(rfs_normal[:,:,4])) #pl.colorbar() #(however in very original decoding, masking was done only at the end.i.e. W had all the pixels in the square.) #shouldnt have an impact but remember to check if it does. ask tomas. # convert to 1D array and mask with circular mask (tested, works) rfs_normal = rfs_normal.reshape((np.prod(mask.shape),-1))[mask.ravel(),:] rfs = rfs.reshape((np.prod(mask.shape),-1))[mask.ravel(),:] #rfs **= prf_cv_fold_data[:, 3, np.newaxis].T ############################################################################################################################################ # setting up prf spatial profiles for the decoding step, creating linear_predictor_ip ############################################################################################################################################ # and then we try to use this: W=rfs_normal.T #linear_predictor_ip=np.zeros((W.shape[0], W.shape[1]+1)) #linear_predictor_ip[:,1:]=np.copy(W) #do some rescalings. This affects decoding quite a lot! #linear_predictor_ip **= np.tile(prf_cv_fold_data[:, 3], (linear_predictor_ip.shape[1],1)).T # #at this point (after power raising but before multiplication/subtraction) the css model convolves with hrf. #linear_predictor_ip *= np.tile(prf_cv_fold_data[:, 4], (linear_predictor_ip.shape[1],1)).T #linear_predictor_ip += np.tile(prf_cv_fold_data[:, 5], (linear_predictor_ip.shape[1],1)).T ############################################################################################################################################ # no convolution simple prediction. use to test difference between CSS model (time dependent) # and respective nonlinear, time-independent model that we use in decoding ("simple prediction") ############################################################################################################################################ simple_prediction= np.dot(rfs_normal.T, dm_crossv.reshape((np.prod(mask.shape),-1))[mask.ravel(),:]) simple_prediction **= prf_cv_fold_data[:, 3, np.newaxis] simple_prediction *= prf_cv_fold_data[:, 4, np.newaxis] simple_prediction += prf_cv_fold_data[:, 5, np.newaxis] hrf = css_model.hrf_model(css_model.hrf_delay, css_model.stimulus.tr_length) #for i in range(simple_prediction.shape[0]): #a=np.max(simple_prediction[i,:]) #simple_prediction[i,:] = fftconvolve(simple_prediction[i,:], hrf)[0:simple_prediction.shape[1]] #simple_prediction[i,:] -= savgol_filter(simple_prediction[i,:], window_length=css_model.sg_filter_window_length, polyorder=css_model.sg_filter_order, deriv=0, mode='nearest') css_prediction=np.zeros((rsq_mask_crossv.sum(),train_data.shape[1])) for g, vox_prf_pars in enumerate(prf_cv_fold_data): css_prediction[g] = css_model.generate_prediction( x=vox_prf_pars[0], y=vox_prf_pars[1], sigma=vox_prf_pars[2], n=vox_prf_pars[3], beta=vox_prf_pars[4], baseline=vox_prf_pars[5]) #b=np.max(css_prediction[g,:]) #simple_prediction[:,g] *= b/a all_residuals_css = train_data - css_prediction all_residuals_simple = train_data - simple_prediction print("Shapiro-Wilk normality test (if second value is large, residuals are normal):", sp.stats.shapiro(all_residuals_css)) print("CSS resid: ",np.sum(all_residuals_css)) print("simple model (no hrf) resid: ",np.sum(all_residuals_simple)) # print(np.max(simple_prediction[i,:])/a) # some quick visualization f = pl.figure(figsize=(17,5)) s = f.add_subplot(211) pl.plot(css_prediction[np.argmax(rsq_crossv[rsq_mask_crossv])], label='CSS prediction') pl.plot(train_data[np.argmax(rsq_crossv[rsq_mask_crossv])], label='data') pl.plot(simple_prediction[np.argmax(rsq_crossv[rsq_mask_crossv])], label='Simple prediction') #pl.plot(all_residuals_css[np.argmax(rsq_crossv[rsq_mask_crossv])], label='resid') pl.legend() s.set_title('best voxel') s = f.add_subplot(212) pl.plot(css_prediction[np.argmin(rsq_crossv[rsq_mask_crossv])], label='CSS prediction') pl.plot(train_data[np.argmin(rsq_crossv[rsq_mask_crossv])], label='data') pl.plot(simple_prediction[np.argmin(rsq_crossv[rsq_mask_crossv])], label='Simple prediction') #pl.plot(all_residuals_css[np.argmin(rsq_crossv[rsq_mask_crossv])], label='resid') pl.legend() s.set_title('worst voxel given this threshold') all_residual_covariance_css = np.cov(all_residuals_css) return prf_cv_fold_data, W, all_residuals_css, all_residual_covariance_css, test_data, mask
def test_og_fit(): # stimulus features viewing_distance = 38 screen_width = 25 thetas = np.arange(0, 360, 90) thetas = np.insert(thetas, 0, -1) thetas = np.append(thetas, -1) num_blank_steps = 30 num_bar_steps = 30 ecc = 12 tr_length = 1.0 frames_per_tr = 1.0 scale_factor = 1.0 pixels_across = 100 pixels_down = 100 dtype = ctypes.c_int16 # create the sweeping bar stimulus in memory bar = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc) # create an instance of the Stimulus class stimulus = VisualStimulus(bar, viewing_distance, screen_width, scale_factor, tr_length, dtype) # initialize the gaussian model model = og.GaussianModel(stimulus, utils.spm_hrf) model.hrf_delay = 0 model.mask_size = 5 # generate a random pRF estimate x = -5.24 y = 2.58 sigma = 1.24 hrf_delay = 0.66 beta = 2.5 baseline = -0.25 # create the "data" data = model.generate_prediction(x, y, sigma, hrf_delay, beta, baseline) # set search grid x_grid = (-10, 10) y_grid = (-10, 10) s_grid = (0.25, 5.25) h_grid = (-1.0, 1.0) # set search bounds x_bound = (-12.0, 12.0) y_bound = (-12.0, 12.0) s_bound = (0.001, 12.0) h_bound = (-1.5, 1.5) b_bound = (1e-8, None) m_bound = (None, None) # loop over each voxel and set up a GaussianFit object grids = ( x_grid, y_grid, s_grid, h_grid, ) bounds = (x_bound, y_bound, s_bound, h_bound, b_bound, m_bound) # fit the response fit = og.GaussianFit(model, data, grids, bounds, Ns=5) # coarse fit npt.assert_almost_equal(fit.x0, -5.0) npt.assert_almost_equal(fit.y0, 5.0) npt.assert_almost_equal(fit.s0, 2.75) npt.assert_almost_equal(fit.hrf0, 0.5) # the baseline/beta should be 0/1 when regressed data vs. estimate (m, b) = np.polyfit(fit.scaled_ballpark_prediction, data, 1) npt.assert_almost_equal(m, 1.0) npt.assert_almost_equal(b, 0.0) # assert equivalence npt.assert_almost_equal(fit.x, x) npt.assert_almost_equal(fit.y, y) npt.assert_almost_equal(fit.hrf_delay, hrf_delay) npt.assert_almost_equal(fit.sigma, sigma) npt.assert_almost_equal(fit.beta, beta) # test receptive field rf = generate_og_receptive_field(x, y, sigma, fit.model.stimulus.deg_x, fit.model.stimulus.deg_y) rf /= (2 * np.pi * sigma**2) * 1 / np.diff(model.stimulus.deg_x[0, 0:2])**2 npt.assert_almost_equal(np.round(rf.sum()), np.round(fit.receptive_field.sum())) # test model == fit RF npt.assert_almost_equal( np.round(fit.model.generate_receptive_field(x, y, sigma).sum()), np.round(fit.receptive_field.sum()))
raise ValueError( 'BOLD Image and Stimulus JSON do not have the same number of data points' ) fields = ('theta', 'rho', 'sigma', 'hrfdelay', 'beta', 'baseline') res = {k: [] for k in fields} res['pred'] = [] for (ii, vx, js) in zip(range(len(bold)), bold, stim_json): stdat = js['Stimulus'] if pimms.is_list(stdat): stdat = stdat[0] height = stdat['fieldofviewVert'] width = stdat['fieldofviewHorz'] ### STIMULUS # First get a viewing distance and screen size dist = 100 # 100 cm is arbitrary stim_width = 2 * dist * np.tan(np.pi / 180 * width / 2) stimulus = VisualStimulus(stim, dist, stim_width, 1.0, float(js['TR']), ctypes.c_int16) model = og.GaussianModel(stimulus, utils.double_gamma_hrf) ### FIT ## define search grids # these define min and max of the edge of the initial brute-force search. x_grid = (-width / 2, width / 2) y_grid = (-height / 2, height / 2) s_grid = (1 / stimulus.ppd + 0.25, 5.25) h_grid = (-1.0, 1.0) ## define search bounds # these define the boundaries of the final gradient-descent search. x_bound = (-width, width) y_bound = (-height, height) s_bound = (1 / stimulus.ppd, 12.0) # smallest sigma is a pixel b_bound = (1e-8, None) u_bound = (None, None)
def test_strf_fit(): viewing_distance = 38 screen_width = 25 thetas = np.tile(np.arange(0,360,90),2) thetas = np.insert(thetas,0,-1) thetas = np.append(thetas,-1) num_blank_steps = 20 num_bar_steps = 20 ecc = 10 tr_length = 1.0 frames_per_tr = 1.0 scale_factor = 0.50 pixels_down = 200 pixels_across = 200 dtype = ctypes.c_int16 Ns = 3 voxel_index = (1,2,3) auto_fit = True verbose = 1 projector_hz = 480 tau = 0.00875 mask_size = 5 hrf = 0.25 # create the sweeping bar stimulus in memory stim = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc) # create an instance of the Stimulus class stimulus = VisualStimulus(stim, viewing_distance, screen_width, scale_factor, tr_length, dtype) stimulus.fps = projector_hz flicker_vec = np.zeros_like(stim[0,0,:]).astype('uint8') flicker_vec[1*20:5*20] = 1 flicker_vec[5*20:9*20] = 2 stimulus.flicker_vec = flicker_vec stimulus.flicker_hz = [10,20] # initialize the gaussian model model = strf.SpatioTemporalModel(stimulus, utils.spm_hrf) model.tau = tau model.hrf_delay = hrf model.mask_size = mask_size # generate a random pRF estimate x = -2.24 y = 1.58 sigma = 1.23 weight = 0.90 beta = 1.0 baseline = -0.25 # create the "data" data = model.generate_prediction(x, y, sigma, weight, beta, baseline) # set search grid x_grid = utils.grid_slice(-8.0,7.0,5) y_grid = utils.grid_slice(-8.0,7.0,5) s_grid = utils.grid_slice(0.75,3.0,5) w_grid = utils.grid_slice(0.05,0.95,5) # set search bounds x_bound = (-10,10) y_bound = (-10,10) s_bound = (1/stimulus.ppd,10) w_bound = (1e-8,1.0) b_bound = (1e-8,1e5) u_bound = (None, None) # loop over each voxel and set up a GaussianFit object grids = (x_grid, y_grid, s_grid, w_grid,) bounds = (x_bound, y_bound, s_bound, w_bound, b_bound, u_bound) # fit the response fit = strf.SpatioTemporalFit(model, data, grids, bounds) # coarse fit ballpark = [-0.5, 3.25, 2.4375, 0.94999999999999996, 1.0292, -0.24999999999999992] npt.assert_almost_equal((fit.x0,fit.y0,fit.sigma0,fit.weight0,fit.beta0,fit.baseline0),ballpark,4) # fine fit npt.assert_almost_equal(fit.x, x, 2) npt.assert_almost_equal(fit.y, y, 2) npt.assert_almost_equal(fit.sigma, sigma, 2) npt.assert_almost_equal(fit.weight, weight, 2) npt.assert_almost_equal(fit.beta, beta, 2) npt.assert_almost_equal(fit.baseline, baseline, 2) # overloaded npt.assert_almost_equal(fit.overloaded_estimate, [ 2.5272803, 2.7411676, 1.23 , 0.9 , 1. , -0.25 ], 2) m_rf = fit.model.m_rf(fit.model.tau) p_rf = fit.model.p_rf(fit.model.tau) npt.assert_almost_equal(simps(np.abs(m_rf)),simps(p_rf),2) # responses m_resp = fit.model.generate_m_resp(fit.model.tau) p_resp = fit.model.generate_p_resp(fit.model.tau) npt.assert_(np.max(m_resp,0)[0]<np.max(m_resp,0)[1]) npt.assert_(np.max(p_resp,0)[0]>np.max(p_resp,0)[1]) # amps npt.assert_(fit.model.m_amp[0]<fit.model.m_amp[1]) npt.assert_(fit.model.p_amp[0]>fit.model.p_amp[1]) # receptive field rf = generate_og_receptive_field(x, y, sigma, fit.model.stimulus.deg_x, fit.model.stimulus.deg_y) rf /= (2 * np.pi * sigma**2) * 1/np.diff(model.stimulus.deg_x[0,0:2])**2 npt.assert_almost_equal(np.round(rf.sum()), np.round(fit.receptive_field.sum())) # test model == fit RF npt.assert_almost_equal(np.round(fit.model.generate_receptive_field(x,y,sigma).sum()), np.round(fit.receptive_field.sum()))
dms = [] for ix, row in df.iterrows(): dm = create_visual_designmatrix_all( bar_width=0.125, iti_duration=0, thetas=[row.direction], n_pixels=n_pixels, nr_timepoints=row.bar_pass_duration ) # Note that we make a design matrix at level of seconds dms.append(dm) dm = np.concatenate(dms, -1) stimulus = VisualStimulus(dm, distance_screen, size_cm, 0.50, 1.0, ctypes.c_int16) hrf = utils.spm_hrf(0, 1.) bold_dm = fftconvolve(stimulus.stim_arr, hrf[np.newaxis, np.newaxis, :], 'full') bold_dm = np.moveaxis(bold_dm, -1, 0)[:total_duration] bold_dm = resample(bold_dm, int(total_duration / TR), axis=0) np.savetxt('/data/odc/derivatives/prf/dm.txt', dm.reshape(-1, n_pixels**2)) np.savetxt('/data/odc/derivatives/prf/bold_dm.txt', bold_dm.reshape(-1, n_pixels**2)) np.save('/data/odc/derivatives/prf/dm.npy', dm)
# remove fixation point dm[49, 88, :] = 0 dm[49, 89, :] = 0 dm[50, 88, :] = 0 dm[50, 89, :] = 0 #revert y axis dm = dm[::-1, :, :] # this is how popeye wants y dim (0 point is top of dm) ######################################################################################## # setup popeye filtered css model ######################################################################################## stimulus = VisualStimulus(stim_arr=dm, viewing_distance=225, screen_width=69.84, scale_factor=1, tr_length=TR, dtype=np.short) model_func = CompressiveSpatialSummationModelFiltered( stimulus=stimulus, hrf_model=utils.spm_hrf, sg_filter_window_length=120, sg_filter_order=3, tr=TR) model_func.hrf_delay = hrf_delay print 'loading data' # load data
def test_dog(): # stimulus features viewing_distance = 31 screen_width = 41 thetas = np.arange(0, 360, 90) # thetas = np.insert(thetas,0,-1) # thetas = np.append(thetas,-1) num_blank_steps = 0 num_bar_steps = 30 ecc = 10 tr_length = 1.0 frames_per_tr = 1.0 scale_factor = 0.50 pixels_down = 100 pixels_across = 100 dtype = ctypes.c_int16 auto_fit = True verbose = 0 # create the sweeping bar stimulus in memory bar = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc) # create an instance of the Stimulus class stimulus = VisualStimulus(bar, viewing_distance, screen_width, scale_factor, tr_length, dtype) # initialize the gaussian model model = dog.DifferenceOfGaussiansModel(stimulus, utils.spm_hrf) model.hrf_delay = 0 model.mask_size = 20 # set the pRF params x = 2.2 y = 2.5 sigma = 0.90 sigma_ratio = 1.5 volume_ratio = 0.5 beta = 0.25 baseline = -0.10 # create "data" data = model.generate_prediction(x, y, sigma, sigma_ratio, volume_ratio, beta, baseline) # set up the grids x_grid = utils.grid_slice(-5, 5, 4) y_grid = utils.grid_slice(-5, 5, 4) s_grid = utils.grid_slice(1 / stimulus.ppd0 * 1.10, 3.5, 4) sr_grid = utils.grid_slice(1.0, 2.0, 4) vr_grid = utils.grid_slice(0.10, 0.90, 4) grids = ( x_grid, y_grid, s_grid, sr_grid, vr_grid, ) # set up the bounds x_bound = (-ecc, ecc) y_bound = (-ecc, ecc) s_bound = (1 / stimulus.ppd, 5) sr_bound = (1.0, None) vr_bound = (1e-8, 1.0) bounds = ( x_bound, y_bound, s_bound, sr_bound, vr_bound, ) # fit it fit = dog.DifferenceOfGaussiansFit(model, data, grids, bounds) # coarse fit ballpark = [ 1.666666666666667, 1.666666666666667, 2.8243187483428391, 1.9999999999999998, 0.10000000000000001 ] npt.assert_almost_equal((fit.x0, fit.y0, fit.s0, fit.sr0, fit.vr0), ballpark) # the baseline/beta should be 0/1 when regressed data vs. estimate (m, b) = np.polyfit(fit.scaled_ballpark_prediction, data, 1) npt.assert_almost_equal(m, 1.0) npt.assert_almost_equal(b, 0.0) # fine fit npt.assert_almost_equal(fit.x, x, 2) npt.assert_almost_equal(fit.y, y, 2) npt.assert_almost_equal(fit.sigma, sigma, 2) npt.assert_almost_equal(fit.sigma_ratio, sigma_ratio, 1) npt.assert_almost_equal(fit.volume_ratio, volume_ratio, 1) # test the RF rf = fit.model.receptive_field(*fit.estimate[0:-2]) est = fit.estimate[0:-2].copy() rf_new = fit.model.receptive_field(*est) value_1 = np.sqrt(simps(simps(rf))) value_2 = np.sqrt(simps(simps(rf_new))) nt.assert_almost_equal(value_1, value_2) # polar coordinates npt.assert_almost_equal( [fit.theta, fit.rho], [np.arctan2(y, x), np.sqrt(x**2 + y**2)], 4)
def test_strf_css_fit(): viewing_distance = 38 screen_width = 25 thetas = np.tile(np.arange(0,360,90),2) num_blank_steps = 0 num_bar_steps = 30 ecc = 10 tr_length = 1.0 frames_per_tr = 1.0 scale_factor = 0.50 pixels_down = 100 pixels_across = 100 dtype = ctypes.c_int16 Ns = 3 voxel_index = (1,2,3) auto_fit = True verbose = 1 projector_hz = 480 tau = 0.00875 mask_size = 5 hrf = 0.25 # create the sweeping bar stimulus in memory stim1 = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc, clip=0.33) # create the sweeping bar stimulus in memory stim2 = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc, clip=0.0001) stim = np.concatenate((stim1,stim2),-1) # create an instance of the Stimulus class stimulus = VisualStimulus(stim, viewing_distance, screen_width, scale_factor, tr_length, dtype) stimulus.fps = projector_hz flicker_vec = np.zeros_like(stim1[0,0,:]).astype('uint8') flicker_vec[1*20:5*20] = 1 flicker_vec[5*20:9*20] = 2 flicker_vec = np.tile(flicker_vec,2) stimulus.flicker_vec = flicker_vec stimulus.flicker_hz = [10,20,10,20] # initialize the gaussian model model = strf.SpatioTemporalModel(stimulus, utils.spm_hrf) model.tau = tau model.hrf_delay = hrf model.mask_size = mask_size # generate a random pRF estimate x = -2.24 y = 1.58 sigma = 1.23 n = 0.90 weight = 0.95 beta = 0.88 baseline = -0.25 # create the "data" data = model.generate_prediction(x, y, sigma, n, weight, beta, baseline) # set search grid x_grid = utils.grid_slice(-8.0,7.0,4) y_grid = utils.grid_slice(-8.0,7.0,4) s_grid = utils.grid_slice(0.75,3.0,4) n_grid = utils.grid_slice(0.25,0.95,4) w_grid = utils.grid_slice(0.25,0.95,4) # set search bounds x_bound = (-10,10) y_bound = (-10,10) s_bound = (1/stimulus.ppd,10) n_bound = (1e-8,1.0-1e-8) w_bound = (1e-8,1.0-1e-8) b_bound = (1e-8,1e5) u_bound = (None, None) # loop over each voxel and set up a GaussianFit object grids = (x_grid, y_grid, s_grid, n_grid, w_grid,) bounds = (x_bound, y_bound, s_bound, n_bound, w_bound, b_bound, u_bound) # fit the response fit = strf.SpatioTemporalFit(model, data, grids, bounds) # coarse fit ballpark = [-3.0, 2.0, 1.5, 0.95, 0.95, 0.88574075, -0.25] npt.assert_almost_equal((fit.x0,fit.y0,fit.sigma0, fit.n0, fit.weight0,fit.beta0,fit.baseline0),ballpark) # fine fit npt.assert_almost_equal(fit.x, x, 2) npt.assert_almost_equal(fit.y, y, 2) npt.assert_almost_equal(fit.sigma, sigma, 1) npt.assert_almost_equal(fit.n, n, 2) npt.assert_almost_equal(fit.weight, weight, 2) npt.assert_almost_equal(fit.beta, beta, 2) npt.assert_almost_equal(fit.baseline, baseline, 2) # overloaded npt.assert_almost_equal(fit.overloaded_estimate,[2.5266437, 2.7390143, 1.3014282, 0.9004958, 0.9499708, 0.8801774], 2) # rfs m_rf = fit.model.m_rf(fit.model.tau) p_rf = fit.model.p_rf(fit.model.tau) npt.assert_almost_equal(simps(np.abs(m_rf)),simps(p_rf),5) # responses m_resp = fit.model.generate_m_resp(fit.model.tau) p_resp = fit.model.generate_p_resp(fit.model.tau) npt.assert_(np.max(m_resp,0)[0]<np.max(m_resp,0)[1]) npt.assert_(np.max(p_resp,0)[0]>np.max(p_resp,0)[1]) # amps npt.assert_(fit.model.m_amp[0]<fit.model.m_amp[1]) npt.assert_(fit.model.p_amp[0]>fit.model.p_amp[1]) # receptive field npt.assert_almost_equal(4.0, fit.receptive_field.sum())
def test_css_fit(): viewing_distance = 38 screen_width = 25 thetas = np.arange(0, 360, 90) num_blank_steps = 0 num_bar_steps = 30 ecc = 10 tr_length = 1.0 frames_per_tr = 1.0 scale_factor = 0.50 pixels_down = 50 pixels_across = 50 dtype = ctypes.c_int16 Ns = 3 voxel_index = (1, 2, 3) auto_fit = True verbose = 1 # create the sweeping bar stimulus in memory bar = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc) # create an instance of the Stimulus class stimulus = VisualStimulus(bar, viewing_distance, screen_width, scale_factor, tr_length, dtype) # initialize the gaussian model model = css.CompressiveSpatialSummationModel(stimulus, utils.spm_hrf) model.hrf_delay = 0.2 # generate a random pRF estimate x = -2.24 y = 1.58 sigma = 1.23 n = 0.90 beta = 1.0 baseline = -0.25 # create the "data" data = model.generate_prediction(x, y, sigma, n, beta, baseline) # set search grid x_grid = (-3, 2) y_grid = (-3, 2) s_grid = (1 / stimulus.ppd, 2.75) n_grid = (0.1, 0.90) # set search bounds x_bound = (-10, 10) y_bound = (-10, 10) s_bound = (1 / stimulus.ppd, 10) n_bound = (1e-8, 1.0) b_bound = (1e-8, 1e5) h_bound = (-3.0, 3.0) # loop over each voxel and set up a GaussianFit object grids = ( x_grid, y_grid, s_grid, n_grid, ) bounds = ( x_bound, y_bound, s_bound, n_bound, b_bound, ) # fit the response fit = css.CompressiveSpatialSummationFit(model, data, grids, bounds, Ns=Ns) # coarse fit observed = [fit.x0, fit.y0, fit.s0, fit.n0, fit.beta0, fit.baseline0] expected = [-3., 2., 0.72833938, 0.5, 0.9358213, -0.24999999999999997] npt.assert_almost_equal(observed, expected) # fine fit npt.assert_almost_equal(fit.x, x) npt.assert_almost_equal(fit.y, y) npt.assert_almost_equal(fit.sigma, sigma) npt.assert_almost_equal(fit.n, n) npt.assert_almost_equal(fit.beta, beta) npt.assert_almost_equal(fit.beta, beta) # overloaded npt.assert_almost_equal(fit.overloaded_estimate, [ 2.5272803327893043, 2.7411676344215277, 1.2965338406691291, 0.90000000000036384, 0.99999999999999067, -0.25000000000200889 ])
def test_bounded_amplitude_failure(): # stimulus features viewing_distance = 38 screen_width = 25 thetas = np.arange(0, 360, 90) thetas = np.insert(thetas, 0, -1) thetas = np.append(thetas, -1) num_blank_steps = 30 num_bar_steps = 30 ecc = 12 tr_length = 1.0 frames_per_tr = 1.0 scale_factor = 1.0 pixels_across = 100 pixels_down = 100 dtype = ctypes.c_int16 # create the sweeping bar stimulus in memory bar = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc) # create an instance of the Stimulus class stimulus = VisualStimulus(bar, viewing_distance, screen_width, scale_factor, tr_length, dtype) # initialize the gaussian model model = og.GaussianModel(stimulus, utils.double_gamma_hrf, utils.percent_change) model.hrf_delay = 0 model.mask_size = 6 # generate a random pRF estimate x = -5.24 y = 2.58 sigma = 1.24 beta = -0.25 baseline = 0.25 # create the "data" data = model.generate_prediction(x, y, sigma, beta, baseline) # set search grid x_grid = utils.grid_slice(-10, 10, 5) y_grid = utils.grid_slice(-10, 10, 5) s_grid = utils.grid_slice(0.25, 5.25, 5) # set search bounds x_bound = (-12.0, 12.0) y_bound = (-12.0, 12.0) s_bound = (0.001, 12.0) b_bound = (1e-8, None) m_bound = (None, None) # loop over each voxel and set up a GaussianFit object grids = ( x_grid, y_grid, s_grid, ) bounds = (x_bound, y_bound, s_bound, b_bound, m_bound) # fit the response fit = og.GaussianFit(model, data, grids, bounds) nt.assert_true(fit.model.bounded_amplitude) nt.assert_true(fit.slope > 0) nt.assert_true(fit.beta0 > 0) nt.assert_true(fit.beta > 0) nt.assert_true(fit.beta != beta)
def test_recast_estimation_results(): # stimulus features viewing_distance = 38 screen_width = 25 thetas = np.arange(0, 360, 45) num_blank_steps = 0 num_bar_steps = 30 ecc = 10 tr_length = 1.0 frames_per_tr = 1.0 scale_factor = 0.10 pixels_down = 100 pixels_across = 100 dtype = ctypes.c_int16 voxel_index = (1, 2, 3) auto_fit = True verbose = 1 # create the sweeping bar stimulus in memory bar = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc) # create an instance of the Stimulus class stimulus = VisualStimulus(bar, viewing_distance, screen_width, scale_factor, tr_length, dtype) # initialize the gaussian model model = og.GaussianModel(stimulus, utils.spm_hrf) model.hrf_delay = 0 # generate a random pRF estimate x = -5.24 y = 2.58 sigma = 1.24 beta = 2.5 baseline = -0.25 # create the "data" data = model.generate_prediction(x, y, sigma, beta, baseline) # set search grid x_grid = utils.grid_slice(-5, 4, 5) y_grid = utils.grid_slice(-5, 7, 5) s_grid = utils.grid_slice(1 / stimulus.ppd, 5.25, 5) b_grid = utils.grid_slice(0.1, 4.0, 5) # set search bounds x_bound = (-12.0, 12.0) y_bound = (-12.0, 12.0) s_bound = (1 / stimulus.ppd, 12.0) b_bound = (1e-8, 1e2) m_bound = (None, None) # loop over each voxel and set up a GaussianFit object grids = ( x_grid, y_grid, s_grid, ) bounds = (x_bound, y_bound, s_bound, b_bound, m_bound) # create 3 voxels of data all_data = np.array([data, data, data]) indices = [(0, 0, 0), (0, 0, 1), (0, 0, 2)] # bundle the voxels bundle = utils.multiprocess_bundle(og.GaussianFit, model, all_data, grids, bounds, indices) # run analysis with sharedmem.Pool(np=3) as pool: output = pool.map(utils.parallel_fit, bundle) # create grid parent arr = np.zeros((1, 1, 3)) grid_parent = nibabel.Nifti1Image(arr, np.eye(4, 4)) # recast the estimation results nif = utils.recast_estimation_results(output, grid_parent) dat = nif.get_data() # assert equivalence npt.assert_almost_equal(np.mean(dat[..., 0]), x) npt.assert_almost_equal(np.mean(dat[..., 1]), y) npt.assert_almost_equal(np.mean(dat[..., 2]), sigma) npt.assert_almost_equal(np.mean(dat[..., 3]), beta) npt.assert_almost_equal(np.mean(dat[..., 4]), baseline) # recast the estimation results - OVERLOADED nif = utils.recast_estimation_results(output, grid_parent, True) dat = nif.get_data() # assert equivalence npt.assert_almost_equal(np.mean(dat[..., 0]), np.arctan2(y, x), 2) npt.assert_almost_equal(np.mean(dat[..., 1]), np.sqrt(x**2 + y**2), 2) npt.assert_almost_equal(np.mean(dat[..., 2]), sigma) npt.assert_almost_equal(np.mean(dat[..., 3]), beta) npt.assert_almost_equal(np.mean(dat[..., 4]), baseline)
rsq_mask_crossv = np.mean(prf_data[:, :, -1], axis=1) > rsq_threshold ############################################################################################################################################ # setting up prf timecourses - NOTE, this is for the 'all' situation, so should be really done on a run-by-run basis using a run's # loo data and prf parameters. A test set would then be taken from the single_run data as this hasn't been used for that run's fit. ############################################################################################################################################ # set up model with hrf etc. def my_spmt(delay, tr): return spmt(np.arange(0, 33, tr)) # we're going to use these popeye convenience functions # because they are fast, and because they were used in the fitting procedure stimulus = VisualStimulus(dm_crossv, screen_distance, screen_width, 1.0 / 3.0, TR, ctypes.c_int16) css_model = CompressiveSpatialSummationModelFiltered(stimulus, my_spmt) css_model.hrf_delay = 0 ############################################################################################################################################ # setting up prf spatial profiles for subsequent covariances, now some per-run stuff was done ############################################################################################################################################ #use this number to choose which section to use in crossvalidate setup crossv = 0 deg_x, deg_y = np.meshgrid( np.linspace(extent[0], extent[1], n_pix, endpoint=True), np.linspace(extent[0], extent[1], n_pix, endpoint=True)) rfs = generate_og_receptive_fields(prf_data[rsq_mask_crossv, crossv, 0], prf_data[rsq_mask_crossv, crossv, 1],
def test_strf_hrf_fit(): viewing_distance = 38 screen_width = 25 thetas = np.tile(np.arange(0, 360, 90), 2) thetas = np.insert(thetas, 0, -1) thetas = np.append(thetas, -1) num_blank_steps = 20 num_bar_steps = 20 ecc = 10 tr_length = 1.0 frames_per_tr = 1.0 scale_factor = 0.50 pixels_down = 200 pixels_across = 200 dtype = ctypes.c_int16 Ns = 3 voxel_index = (1, 2, 3) auto_fit = True verbose = 1 projector_hz = 480 tau = 0.00875 mask_size = 5 # create the sweeping bar stimulus in memory stim = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc) # create an instance of the Stimulus class stimulus = VisualStimulus(stim, viewing_distance, screen_width, scale_factor, tr_length, dtype) stimulus.fps = projector_hz flicker_vec = np.zeros_like(stim[0, 0, :]).astype('uint8') flicker_vec[1 * 20:5 * 20] = 1 flicker_vec[5 * 20:9 * 20] = 2 stimulus.flicker_vec = flicker_vec stimulus.flicker_hz = [10, 20] # initialize the gaussian model model = strf.SpatioTemporalModel(stimulus, utils.double_gamma_hrf) model.tau = tau model.mask_size = mask_size # generate a random pRF estimate x = -2.24 y = 1.58 sigma = 1.23 weight = 0.90 hrf_delay = -0.13 beta = 1.0 baseline = -0.25 # create the "data" data = model.generate_prediction(x, y, sigma, weight, hrf_delay, beta, baseline) # set search grid x_grid = utils.grid_slice(-8.0, 7.0, 3) y_grid = utils.grid_slice(-8.0, 7.0, 3) s_grid = utils.grid_slice(0.75, 3.0, 3) w_grid = utils.grid_slice(0.05, 0.95, 3) h_grid = utils.grid_slice(-0.25, 0.25, 3) # set search bounds x_bound = (-10, 10) y_bound = (-10, 10) s_bound = (1 / stimulus.ppd, 10) w_bound = (1e-8, 1.0) b_bound = (1e-8, 1e5) u_bound = (None, None) h_bound = (-2.0, 2.0) # loop over each voxel and set up a GaussianFit object grids = ( x_grid, y_grid, s_grid, w_grid, h_grid, ) bounds = (x_bound, y_bound, s_bound, w_bound, h_bound, b_bound, u_bound) # fit the response fit = strf.SpatioTemporalFit(model, data, grids, bounds) # coarse fit npt.assert_almost_equal((fit.x0, fit.y0, fit.sigma0, fit.weight0, fit.hrf0, fit.beta0, fit.baseline0), [-0.5, -0.5, 3., 0.95, -0.25, 1., 0.02], 2) # fine fit npt.assert_almost_equal(fit.x, x, 2) npt.assert_almost_equal(fit.y, y, 2) npt.assert_almost_equal(fit.sigma, sigma, 2) npt.assert_almost_equal(fit.weight, weight, 2) npt.assert_almost_equal(fit.beta, beta, 2) npt.assert_almost_equal(fit.baseline, baseline, 2) # overloaded npt.assert_almost_equal(fit.overloaded_estimate, [2.53, 2.74, 1.23, 0.9, 5.87, 1., -0.25], 2) m_rf = fit.model.m_rf(fit.model.tau) p_rf = fit.model.p_rf(fit.model.tau) npt.assert_almost_equal(simps(np.abs(m_rf)), simps(p_rf), 5) # responses m_resp = fit.model.generate_m_resp(fit.model.tau) p_resp = fit.model.generate_p_resp(fit.model.tau) npt.assert_(np.max(m_resp, 0)[0] < np.max(m_resp, 0)[1]) npt.assert_(np.max(p_resp, 0)[0] > np.max(p_resp, 0)[1]) # amps npt.assert_(fit.model.m_amp[0] < fit.model.m_amp[1]) npt.assert_(fit.model.p_amp[0] > fit.model.p_amp[1]) # receptive field npt.assert_almost_equal(4.0, fit.receptive_field.sum())
def test_strf_css_fit(): viewing_distance = 38 screen_width = 25 thetas = np.tile(np.arange(0,360,90),2) thetas = np.insert(thetas,0,-1) thetas = np.append(thetas,-1) num_blank_steps = 20 num_bar_steps = 20 ecc = 10 tr_length = 1.0 frames_per_tr = 1.0 scale_factor = 0.50 pixels_down = 100 pixels_across = 100 dtype = ctypes.c_int16 Ns = 3 voxel_index = (1,2,3) auto_fit = True verbose = 1 projector_hz = 480 tau = 0.00875 mask_size = 5 hrf = 0.25 # create the sweeping bar stimulus in memory stim1 = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc, clip=0.33) # create the sweeping bar stimulus in memory stim2 = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc, clip=0.0001) stim = np.concatenate((stim1,stim2),-1) # create an instance of the Stimulus class stimulus = VisualStimulus(stim, viewing_distance, screen_width, scale_factor, tr_length, dtype) stimulus.fps = projector_hz flicker_vec = np.zeros_like(stim1[0,0,:]).astype('uint8') flicker_vec[1*20:5*20] = 1 flicker_vec[5*20:9*20] = 2 flicker_vec = np.tile(flicker_vec,2) stimulus.flicker_vec = flicker_vec stimulus.flicker_hz = [10,20,10,20] # initialize the gaussian model model = strf.SpatioTemporalModel(stimulus, utils.double_gamma_hrf) model.tau = tau model.hrf_delay = hrf model.mask_size = mask_size # generate a random pRF estimate x = -2.24 y = 1.58 sigma = 1.23 n = 0.90 weight = 0.95 beta = 1.0 baseline = 0 # create the "data" data = model.generate_prediction(x, y, sigma, n, weight, beta, baseline) # set search grid x_grid = utils.grid_slice(-8.0,7.0,3) y_grid = utils.grid_slice(-8.0,7.0,3) s_grid = utils.grid_slice(0.75,3.0,3) n_grid = utils.grid_slice(0.25,0.95,3) w_grid = utils.grid_slice(0.25,0.95,3) # set search bounds x_bound = (-10,10) y_bound = (-10,10) s_bound = (1/stimulus.ppd,10) n_bound = (1e-8,1.0-1e-8) w_bound = (1e-8,1.0-1e-8) b_bound = (1e-8,1e5) u_bound = (None, None) # loop over each voxel and set up a GaussianFit object grids = (x_grid, y_grid, s_grid, n_grid, w_grid,) bounds = (x_bound, y_bound, s_bound, n_bound, w_bound, b_bound, u_bound) # fit the response fit = strf.SpatioTemporalFit(model, data, grids, bounds) # coarse fit npt.assert_almost_equal((fit.x0,fit.y0,fit.sigma0, fit.n0, fit.weight0,fit.beta0,fit.baseline0),[-0.5 , -0.5 , 1.875, 0.95 , 0.95 , 1. , 0. ]) # fine fit npt.assert_almost_equal(fit.x, x, 1) npt.assert_almost_equal(fit.y, y, 1) npt.assert_almost_equal(fit.sigma, sigma, 1) npt.assert_almost_equal(fit.n, n, 1) npt.assert_almost_equal(fit.weight, weight, 1) npt.assert_almost_equal(fit.beta, beta, 1) npt.assert_almost_equal(fit.baseline, baseline, 1) # overloaded npt.assert_almost_equal(fit.overloaded_estimate, [2.5259863707822303, 2.7330681871539069, 1.3062396482386418, 0.9011492100931614, 0.94990930073215352, 1.0005707740082497],4) # rfs m_rf = fit.model.m_rf(fit.model.tau) p_rf = fit.model.p_rf(fit.model.tau) npt.assert_almost_equal(simps(np.abs(m_rf)),simps(p_rf),5) # responses m_resp = fit.model.generate_m_resp(fit.model.tau) p_resp = fit.model.generate_p_resp(fit.model.tau) npt.assert_(np.max(m_resp,0)[0]<np.max(m_resp,0)[1]) npt.assert_(np.max(p_resp,0)[0]>np.max(p_resp,0)[1]) # amps npt.assert_(fit.model.m_amp[0]<fit.model.m_amp[1]) npt.assert_(fit.model.p_amp[0]>fit.model.p_amp[1]) # receptive field npt.assert_almost_equal(4.0, fit.receptive_field.sum())
def test_resurrect_model(): # stimulus features viewing_distance = 38 screen_width = 25 thetas = np.arange(0,360,90) thetas = np.insert(thetas,0,-1) thetas = np.append(thetas,-1) num_blank_steps = 20 num_bar_steps = 20 ecc = 10 tr_length = 1.5 frames_per_tr = 1.0 scale_factor = 1.0 pixels_across = 100 pixels_down = 100 dtype = ctypes.c_int16 # create the sweeping bar stimulus in memory bar = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc, clip=0.01) # create an instance of the Stimulus class stimulus = VisualStimulus(bar, viewing_distance, screen_width, scale_factor, tr_length, dtype) # set cache grids x_grid = utils.grid_slice(-10, 10, 5) y_grid = utils.grid_slice(-10, 10, 5) s_grid = utils.grid_slice(0.55,5.25, 5) grids = (x_grid, y_grid, s_grid,) # set search bounds x_bound = (-12.0,12.0) y_bound = (-12.0,12.0) s_bound = (0.001,12.0) b_bound = (1e-8,None) m_bound = (None,None) bounds = (x_bound, y_bound, s_bound, b_bound, m_bound) # initialize the gaussian model model = og.GaussianModel(stimulus, utils.double_gamma_hrf) model.hrf_delay = 0 model.mask_size = 5 cache = model.cache_model(grids, ncpus=3) # seed rng np.random.seed(4932) # pluck an estimate and create timeseries x, y, sigma = cache[51][1] beta = 1.25 baseline = 0.25 # create "data" data = cache[51][0] # fit it fit = og.GaussianFit(model, data, grids, bounds, verbose=0) # assert npt.assert_equal(fit.estimate,fit.ballpark) # create "data" data = model.generate_prediction(x,y,sigma,beta,baseline) # fit it fit = og.GaussianFit(model, data, grids, bounds, verbose=0) # assert npt.assert_almost_equal(np.sum(fit.scaled_ballpark_prediction-fit.data)**2,0)
def test_bootstrap(): # stimulus features viewing_distance = 38 screen_width = 25 thetas = np.array([-1, 0, 90, 180, 270, -1]) num_blank_steps = 30 num_bar_steps = 30 ecc = 10 tr_length = 1.0 frames_per_tr = 1.0 scale_factor = 0.10 pixels_down = 100 pixels_across = 100 dtype = ctypes.c_int16 voxel_index = (1, 2, 3) auto_fit = True verbose = 1 # rng np.random.seed(2764932) # create the sweeping bar stimulus in memory bar = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc) # create an instance of the Stimulus class stimulus = VisualStimulus(bar, viewing_distance, screen_width, scale_factor, tr_length, dtype) # initialize the gaussian model model = og.GaussianModel(stimulus, utils.spm_hrf) model.hrf_delay = 0 # generate a random pRF estimate x = -5.24 y = 2.58 sigma = 1.24 beta = 2.5 baseline = -0.25 # create the "data" data = model.generate_prediction(x, y, sigma, beta, baseline) # set search grid x_grid = utils.grid_slice(-10, 10, 5) y_grid = utils.grid_slice(-10, 10, 5) s_grid = utils.grid_slice(0.5, 3.25, 5) # set search bounds x_bound = (-12.0, 12.0) y_bound = (-12.0, 12.0) s_bound = (0.001, 12.0) b_bound = (1e-8, None) m_bound = (None, None) # loop over each voxel and set up a GaussianFit object grids = ( x_grid, y_grid, s_grid, ) bounds = (x_bound, y_bound, s_bound, b_bound, m_bound) # pack multiple "runs" data = np.vstack((data, data, data)) # make it a singular "voxel" data = np.reshape(data, (1, data.shape[0], data.shape[1])) # set bootstraps and resamples bootstraps = 2 resamples = np.array((2, )) # make fodder bundle = utils.bootstrap_bundle(bootstraps, resamples, og.GaussianFit, model, data, grids, bounds, np.tile((1, 2, 3), (bootstraps, 1))) # test for b in bundle: fit = utils.parallel_bootstrap(b) npt.assert_almost_equal(fit.rss, 0) npt.assert_equal(fit.n_resamples, resamples[0]) npt.assert_equal(np.sum(fit.resamples), np.sum(np.arange(resamples[0])))
def test_dog(): # stimulus features viewing_distance = 38 screen_width = 25 thetas = np.arange(0, 360, 90) num_blank_steps = 0 num_bar_steps = 30 ecc = 10 tr_length = 1.0 frames_per_tr = 1.0 scale_factor = 0.50 pixels_down = 50 pixels_across = 50 dtype = ctypes.c_int16 voxel_index = (1, 2, 3) auto_fit = True verbose = 1 # create the sweeping bar stimulus in memory bar = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc) # create an instance of the Stimulus class stimulus = VisualStimulus(bar, viewing_distance, screen_width, scale_factor, tr_length, dtype) # initialize the gaussian model model = dog.DifferenceOfGaussiansModel(stimulus, utils.spm_hrf) model.hrf_delay = 0.2 # set the pRF params x = -1.4 y = 1.5 sigma = 1.0 sigma_ratio = 2.0 volume_ratio = 0.5 hrf_delay = -0.2 # create "data" data = model.generate_prediction( x, y, sigma, sigma_ratio, volume_ratio, ) # set up the grids x_grid = slice(-10, 10, 3) y_grid = slice(-10, 10, 3) s_grid = slice(1 / stimulus.ppd, 5, 3) sr_grid = slice(1.0, 5.0, 3) vr_grid = slice(0.01, 0.99, 3) grids = ( x_grid, y_grid, s_grid, sr_grid, vr_grid, ) # set up the bounds x_bound = (-ecc, ecc) y_bound = (-ecc, ecc) s_bound = (1 / stimulus.ppd, 5) sr_bound = (1.0, None) vr_bound = (1e-8, 1.0) bounds = ( x_bound, y_bound, s_bound, sr_bound, vr_bound, ) # fit it fit = dog.DifferenceOfGaussiansFit(model, data, grids, bounds, voxel_index) # coarse fit nt.assert_almost_equal((fit.x0, fit.y0, fit.s0, fit.sr0, fit.vr0), (-1.0, 2.0, 0.72833937882323319, 1.0, 0.01)) # fine fit nt.assert_almost_equal(fit.x, x) nt.assert_almost_equal(fit.y, y) nt.assert_almost_equal(fit.sigma, sigma) nt.assert_almost_equal(fit.sigma_ratio, sigma_ratio) nt.assert_almost_equal(fit.volume_ratio, volume_ratio) # test the RF rf = fit.model.receptive_field(*fit.estimate) est = fit.estimate.copy() est[2] *= 2 rf_new = fit.model.receptive_field(*est) value_1 = np.sqrt(simps(simps(rf))) value_2 = np.sqrt(simps(simps(rf_new))) nt.assert_almost_equal(value_2 / value_1, sigma_ratio, 1) # polar coordinates npt.assert_almost_equal( [fit.theta, fit.rho], [np.arctan2(y, x), np.sqrt(x**2 + y**2)])
def test_parallel_fit_manual_grids(): # stimulus features viewing_distance = 38 screen_width = 25 thetas = np.arange(0, 360, 45) num_blank_steps = 0 num_bar_steps = 30 ecc = 10 tr_length = 1.0 frames_per_tr = 1.0 scale_factor = 0.10 pixels_down = 100 pixels_across = 100 dtype = ctypes.c_int16 voxel_index = (1, 2, 3) auto_fit = True verbose = 1 # create the sweeping bar stimulus in memory bar = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc) # create an instance of the Stimulus class stimulus = VisualStimulus(bar, viewing_distance, screen_width, scale_factor, tr_length, dtype) # initialize the gaussian model model = og.GaussianModel(stimulus, utils.double_gamma_hrf) model.hrf_delay = 0 # generate a random pRF estimate x = -5.24 y = 2.58 sigma = 1.24 beta = 2.5 baseline = -0.25 # create the "data" data = model.generate_prediction(x, y, sigma, beta, baseline) # set search grid x_grid = slice(-5, 4, 5) y_grid = slice(-5, 7, 5) s_grid = slice(1 / stimulus.ppd, 5.25, 5) b_grid = slice(0.1, 4.0, 5) # set search bounds x_bound = (-12.0, 12.0) y_bound = (-12.0, 12.0) s_bound = (1 / stimulus.ppd, 12.0) b_bound = (1e-8, 1e2) m_bound = (None, None) # loop over each voxel and set up a GaussianFit object grids = ( x_grid, y_grid, s_grid, ) bounds = (x_bound, y_bound, s_bound, b_bound, m_bound) # make 3 voxels all_data = np.array([data, data, data]) num_voxels = data.shape[0] indices = [(1, 2, 3)] * 3 # bundle the voxels bundle = utils.multiprocess_bundle(og.GaussianFit, model, all_data, grids, bounds, indices) # run analysis with sharedmem.Pool(np=3) as pool: output = pool.map(utils.parallel_fit, bundle) # assert equivalence for fit in output: npt.assert_almost_equal(fit.x, x, 2) npt.assert_almost_equal(fit.y, y, 2) npt.assert_almost_equal(fit.sigma, sigma, 2) npt.assert_almost_equal(fit.beta, beta, 2) npt.assert_almost_equal(fit.baseline, baseline, 2)
import numpy as np import sharedmem import popeye.og_hrf as og import popeye.utilities as utils from popeye.visual_stimulus import VisualStimulus, simulate_bar_stimulus # seed random number generator so we get the same answers ... np.random.seed(2764932) ### STIMULUS ## create sweeping bar stimulus sweeps = np.array([-1, 0, 90, 180, 270, -1]) # in degrees, -1 is blank bar = simulate_bar_stimulus(100, 100, 40, 20, sweeps, 30, 30, 10) ## create an instance of the Stimulus class stimulus = VisualStimulus(bar, 50, 25, 0.50, 1.0, ctypes.c_int16) ### MODEL ## initialize the gaussian model model = og.GaussianModel(stimulus, utils.double_gamma_hrf) ## generate a random pRF estimate x = -5.24 y = 2.58 sigma = 1.24 hrf_delay = -0.25 beta = 0.55 baseline = -0.88 x = 6 y = 6
def test_strf_2dcos_fit(): viewing_distance = 38 screen_width = 25 thetas = np.tile(np.arange(0, 360, 90), 2) thetas = np.insert(thetas, 0, -1) thetas = np.append(thetas, -1) num_blank_steps = 0 num_bar_steps = 30 ecc = 10 tr_length = 1 frames_per_tr = 1 scale_factor = 1.0 pixels_down = 100 pixels_across = 100 dtype = ctypes.c_int16 Ns = 5 voxel_index = (1, 2, 3) auto_fit = True verbose = 1 projector_hz = 480 tau = 0.00875 mask_size = 5 hrf = 0.25 # create the sweeping bar stimulus in memory stim = simulate_bar_stimulus(pixels_across, pixels_down, viewing_distance, screen_width, thetas, num_bar_steps, num_blank_steps, ecc) # create an instance of the Stimulus class stimulus = VisualStimulus(stim, viewing_distance, screen_width, scale_factor, tr_length, dtype) stimulus.fps = projector_hz flicker_vec = np.zeros_like(stim[0, 0, :]).astype('uint8') flicker_vec[1 * 20:5 * 20] = 1 flicker_vec[5 * 20:9 * 20] = 2 stimulus.flicker_vec = flicker_vec stimulus.flicker_hz = [10, 20] # initialize the gaussian model model = strf.SpatioTemporalModel(stimulus, utils.spm_hrf) model.tau = tau model.hrf_delay = hrf model.mask_size = mask_size model.power = 0.7 # generate a random pRF estimate x = -2.24 y = 1.58 sigma = 1.23 weight = 0.90 beta = 1.0 baseline = -0.25 # create the "data" data = model.generate_prediction(x, y, sigma, weight, beta, baseline) # set search grid x_grid = utils.grid_slice(-8.0, 7.0, 5) y_grid = utils.grid_slice(-8.0, 7.0, 5) s_grid = utils.grid_slice(0.75, 3.0, 5) w_grid = utils.grid_slice(0.05, 0.95, 5) # set search bounds x_bound = (-10, 10) y_bound = (-10, 10) s_bound = (1 / stimulus.ppd, 10) w_bound = (1e-8, 1.0) b_bound = (1e-8, 1e5) u_bound = (None, None) # loop over each voxel and set up a GaussianFit object grids = ( x_grid, y_grid, s_grid, w_grid, ) bounds = (x_bound, y_bound, s_bound, w_bound, b_bound, u_bound) # fit the response fit = strf.SpatioTemporalFit(model, data, grids, bounds) # coarse fit ballpark = [ -0.5, 3.25, 3.0, 0.72499999999999998, 0.858317, -0.25000000000000011 ] npt.assert_almost_equal( (fit.x0, fit.y0, fit.sigma0, fit.weight0, fit.beta0, fit.baseline0), ballpark) # fine fit npt.assert_almost_equal(fit.x, x) npt.assert_almost_equal(fit.y, y) npt.assert_almost_equal(fit.sigma, sigma) npt.assert_almost_equal(fit.weight, weight) npt.assert_almost_equal(fit.beta, beta) npt.assert_almost_equal(fit.baseline, baseline) # overloaded npt.assert_almost_equal(fit.overloaded_estimate, [ 2.5272803327887128, 2.7411676344185993, 1.2300000000008835, 0.89999999999333258, 1.0000000000005003, -0.25000000000063088 ]) m_rf = fit.model.m_rf(fit.model.tau) p_rf = fit.model.p_rf(fit.model.tau) npt.assert_almost_equal(simps(np.abs(m_rf)), simps(p_rf), 5) # responses m_resp = fit.model.generate_m_resp(fit.model.tau) p_resp = fit.model.generate_p_resp(fit.model.tau) npt.assert_(np.max(m_resp, 0)[0] < np.max(m_resp, 0)[1]) npt.assert_(np.max(p_resp, 0)[0] > np.max(p_resp, 0)[1]) # amps npt.assert_(fit.model.m_amp[0] < fit.model.m_amp[1]) npt.assert_(fit.model.p_amp[0] > fit.model.p_amp[1]) # receptive field rf = generate_2dcos_receptive_field(x, y, sigma, fit.model.power, fit.model.stimulus.deg_x, fit.model.stimulus.deg_y) rf /= (2 * np.pi * sigma**2) * 1 / np.diff(model.stimulus.deg_x[0, 0:2])**2 npt.assert_almost_equal(np.round(rf.sum()), np.round(fit.receptive_field.sum())) # test model == fit RF npt.assert_almost_equal( np.round(fit.model.generate_receptive_field(x, y, sigma).sum()), np.round(fit.receptive_field.sum()))
# visual_dm = np.vstack(visual_dm).transpose((1,2,0)) # the code above recreates Kendrick's design matrices, we'll now just load them. visual_dm = [] # for i in [1,3,5]: for i in [5]: file = tables.open_file( os.path.join(base_dir, 'retinotopysmall{i}.mat'.format(i=i))) visual_dm.append(file.get_node('/stim')[:]) file.close() visual_dm = np.vstack(visual_dm).transpose((1, 2, 0)) stimulus = VisualStimulus(stim_arr=visual_dm, viewing_distance=analysis_info["screen_distance"], screen_width=analysis_info["screen_width"], scale_factor=0.05, tr_length=analysis_info["TR"], dtype=np.short) ############################################################################################################################################ # # load cii data, timepoints by grayordinates # ############################################################################################################################################ # averaged_runs = ['CCW','EXP','RETBAR1'] averaged_runs = ['RETBAR1'] gii_files = [ glob.glob( os.path.join( subject_folder,