def generate_prediction(self, x, y, sigma, sigma_ratio, volume_ratio): # extract the center response rf_center = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) # extract surround response rf_surround = generate_og_receptive_field( x, y, sigma * sigma_ratio, self.stimulus.deg_x, self.stimulus.deg_y) * 1 / sigma_ratio**2 # difference rf = rf_center - np.sqrt(volume_ratio) * rf_surround # extract the response response = generate_rf_timeseries_nomask(self.stimulus.stim_arr, rf) # generate the hrf hrf = self.hrf_model(self.hrf_delay, self.stimulus.tr_length) # convolve it model = fftconvolve(response, hrf)[0:len(response)] return model
def generate_ballpark_prediction(self, x, y, sigma, sigma_ratio, volume_ratio): # extract the center response rf_center = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x0, self.stimulus.deg_y0) # extract surround response rf_surround = generate_og_receptive_field(x, y, sigma*sigma_ratio, self.stimulus.deg_x0, self.stimulus.deg_x0) * 1/sigma_ratio**2 # difference rf = ne.evaluate('rf_center - sqrt(volume_ratio)*rf_surround') # extract the response mask = self.distance_mask(x, y, sigma*sigma_ratio) response = generate_rf_timeseries(self.stimulus.stim_arr0, rf, mask) # generate the hrf hrf = self.hrf_model(self.hrf_delay, self.stimulus.tr_length) # convolve it model = fftconvolve(response, hrf)[0:len(response)] # units model = self.normalizer(model) # regress out mean and linear beta, baseline = self.regress(model, self.data) # offset model += baseline # scale model *= beta return model
def receptive_field(self, x, y, sigma, sigma_ratio, volume_ratio): rf_center = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) rf_surround = generate_og_receptive_field( x, y, sigma * sigma_ratio, self.stimulus.deg_x, self.stimulus.deg_y) * 1.0 / sigma_ratio**2 rf = rf_center - np.sqrt(volume_ratio) * rf_surround return rf
def receptive_field(self): rf_center = generate_og_receptive_field(self.model.stimulus.deg_x, self.model.stimulus.deg_y, self.x, self.y, self.sigma_center) rf_surround = generate_og_receptive_field(self.model.stimulus.deg_x, self.model.stimulus.deg_y, self.x, self.y, self.sigma_surround) return rf_center*self.beta_center - rf_surround*self.beta_surround
def generate_prediction(self, x, y, sigma, n, weight, beta, baseline): # mask for speed mask = self.distance_mask(x, y, sigma) # generate the RF spatial_rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) spatial_rf /= ((2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x[0,0:2])**2) # spatial response spatial_ts = generate_rf_timeseries(self.stimulus.stim_arr, spatial_rf, mask) # compression spatial_ts **= n # temporal response m_ts, p_ts = generate_mp_timeseries(spatial_ts, self.m_amp, self.p_amp, self.stimulus.flicker_vec) # mix them mp_ts = (1-weight) * m_ts + weight * p_ts # convolve with HRF model = fftconvolve(mp_ts, self.hrf())[0:len(mp_ts)] # convert units model = (model - np.mean(model)) / np.mean(model) # scale model *= beta # offset model += baseline return model
def generate_prediction(self, x, y, sigma, mbeta, pbeta): # mask for speed mask = self.distance_mask(x, y, sigma) # generate the RF spatial_rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) spatial_rf /= ((2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x[0,0:2])**2) # spatial response spatial_ts = generate_rf_timeseries(self.stimulus.stim_arr, spatial_rf, mask) # temporal response m_ts, p_ts = generate_mp_timeseries(spatial_ts, self.m_amp, self.p_amp, self.stimulus.flicker_vec) # convolve with HRF hrf = self.hrf_model(self.hrf_delay, self.stimulus.tr_length) # M m_model = fftconvolve(m_ts, hrf)[0:len(m_ts)] # P p_model = fftconvolve(p_ts, hrf)[0:len(p_ts)] # convert units m_model = (m_model - np.mean(m_model))/np.mean(m_model) p_model = (p_model - np.mean(p_model))/np.mean(p_model) # mix model = m_model * mbeta + p_model * pbeta return model
def generate_ballpark_prediction(self, x, y, sigma, weight): # mask for speed mask = self.distance_mask_coarse(x, y, sigma) # generate the RF spatial_rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x0, self.stimulus.deg_y0) spatial_rf /= ((2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x0[0,0:2])**2) # spatial_response spatial_ts = generate_rf_timeseries(self.stimulus.stim_arr0, spatial_rf, mask) # temporal response m_ts, p_ts = generate_mp_timeseries(spatial_ts, self.m_amp, self.p_amp, self.stimulus.flicker_vec) # mix them mp_ts = (1-weight) * m_ts + weight * p_ts # convolve with HRF model = fftconvolve(mp_ts, self.hrf())[0:len(mp_ts)] # units model = (model - np.mean(model)) / np.mean(model) # regress out mean and linear p = linregress(model, self.data) # offset model += p[1] # scale model *= np.abs(p[0]) return model
def generate_prediction(self, x, y, sigma, hrf_delay, beta, baseline): # mask for speed mask = self.distance_mask(x, y, sigma) # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) rf /= (2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x[0,0:2])**2 # extract the stimulus time-series response = generate_rf_timeseries(self.stimulus.stim_arr, rf, mask) # convolve it with the stimulus hrf = self.hrf_model(hrf_delay, self.stimulus.tr_length) model = fftconvolve(response, hrf)[0:len(response)] # units model = (model-np.mean(model)) / np.mean(model) # offset model += baseline # scale it by beta model *= beta return model
def generate_ballpark_prediction(self, x, y, sigma, n): # generate the RF rf = generate_og_receptive_field(x, y, sigma,self.stimulus.deg_x0, self.stimulus.deg_y0) # normalize by the integral rf /= ((2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x0[0,0:2])**2) # extract the stimulus time-series response = generate_rf_timeseries_nomask(self.stimulus.stim_arr0, rf) # compression response **= n # convolve with the HRF hrf = self.hrf_model(self.hrf_delay, self.stimulus.tr_length) # convolve it with the stimulus model = fftconvolve(response, hrf)[0:len(response)] # units model = (model - np.mean(model)) / np.mean(model) # regress it p = linregress(model, self.data) # offset model += p[1] # scale it model *= np.abs(p[0]) return model
def generate_ballpark_prediction(self, x, y, sigma, hrf_delay): # mask for speed mask = self.distance_mask_coarse(x, y, sigma) # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x0, self.stimulus.deg_y0) rf /= (2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x0[0,0:2])**2 # extract the stimulus time-series response = generate_rf_timeseries(self.stimulus.stim_arr0, rf, mask) # convolve it with the stimulus hrf = self.hrf_model(hrf_delay, self.stimulus.tr_length) model = fftconvolve(response, hrf)[0:len(response)] # units model = (model-np.mean(model)) / np.mean(model) # regress out mean and linear p = linregress(model, self.data) # offset model += p[1] # scale model *= np.abs(p[0]) return model
def test_generate_og_receptive_field(): xpixels = 500 # simulated screen width ypixels = 500 # simulated screen height ppd = 1 # simulated visual angle scale_factor = 1.0 # simulated stimulus resampling rate distance = 5 # standard deviations to compute gauss out to xcenter = 0 # x coordinate of the pRF center ycenter = 0 # y coordinate of the pRF center sigma = 1 # width of the pRF test_value = 6 # this is the sum of a gaussian given 1 ppd # and a 1 sigma prf centered on (0,0) # generate the visuotopic coordinates dx,dy = generate_coordinate_matrices(xpixels, ypixels, ppd, scale_factor) # generate a pRF at (0,0) and 1 sigma wide rf = generate_og_receptive_field(xcenter, ycenter, sigma, dx, dy) # divide by integral rf /= 2 * np.pi * sigma ** 2 # compare the volume of the pRF to a known value nt.assert_almost_equal(np.sum(rf),1)
def generate_prediction(self, x, y, sigma, weight, beta, hrf_delay): # mask for speed mask = self.distance_mask(x, y, sigma) # generate the RF spatial_rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) spatial_rf /= (2 * np.pi * sigma ** 2) * 1 / np.diff(self.stimulus.deg_x[0, 0:2]) ** 2 # spatial response spatial_ts = generate_rf_timeseries(self.stimulus.stim_arr, spatial_rf, mask) # temporal response m_ts, p_ts = generate_mp_timeseries(spatial_ts, self.m_amp, self.p_amp, self.stimulus.flicker_vec) # mix them mp_ts = (1 - weight) * m_ts + weight * p_ts # convolve with HRF model = fftconvolve(mp_ts, self.hrf_model(hrf_delay, self.stimulus.tr_length))[0 : len(mp_ts)] # convert units model = (model - np.mean(model)) / np.mean(model) # scale model *= beta return model
def generate_prediction(self, x, y, sigma, n, beta, baseline): # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) # normalize by the integral rf /= ((2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x[0,0:2])**2) # extract the stimulus time-series response = generate_rf_timeseries_nomask(self.stimulus.stim_arr, rf) # compression response **= n # convolve with the HRF hrf = self.hrf_model(self.hrf_delay, self.stimulus.tr_length) # convolve it with the stimulus model = fftconvolve(response, hrf)[0:len(response)] # convert units model = (model - np.mean(model)) / np.mean(model) # offset model += baseline # scale it by beta model *= beta return model
def generate_prediction(self, x, y, sigma, n, beta, baseline): # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) # normalize by the integral rf /= ((2 * np.pi * sigma**2) * 1 / np.diff(self.stimulus.deg_x[0, 0:2])**2) # extract the stimulus time-series response = generate_rf_timeseries_nomask(self.stimulus.stim_arr, rf) # compression response **= n # convolve with the HRF hrf = self.hrf_model(self.hrf_delay, self.stimulus.tr_length) # convolve it with the stimulus model = fftconvolve(response, hrf)[0:len(response)] # units model /= np.max(model) # offset model += baseline # scale it by beta model *= beta return model
def generate_ballpark_prediction(self, x, y, sigma, weight): r""" Predict signal for the Gaussian Model using the downsampled stimulus. The rate of stimulus downsampling is defined in `model.stimulus.scale_factor`. Parameters __________ x : float Horizontal location of the Gaussian RF. y: float Vertical location of the Gaussian RF. sigma: float Dipsersion of the Gaussian RF. weight: float Mixture of the magnocellar and parvocellular temporal response to a flickering visual stimulus. The `weight` ranges between 0 and 1, with 0 being a totally magnocellular response and ` being a totally parvocellular response. """ # mask for speed mask = self.distance_mask_coarse(x, y, sigma) # generate the RF spatial_rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x0, self.stimulus.deg_y0) spatial_rf /= ((2 * np.pi * sigma**2) * 1 / np.diff(self.stimulus.deg_x0[0, 0:2])**2) # spatial_response spatial_ts = generate_rf_timeseries(self.stimulus.stim_arr0, spatial_rf, mask) # temporal response m_ts, p_ts = generate_mp_timeseries(spatial_ts, self.m_amp, self.p_amp, self.stimulus.flicker_vec) # mix them mp_ts = (1 - weight) * m_ts + weight * p_ts # convolve with HRF model = fftconvolve(mp_ts, self.hrf())[0:len(mp_ts)] # units model = self.normalizer(model) # regress out mean and linear p = linregress(model, self.data) # scale model *= p[0] # offset model += p[1] return model
def generate_prediction(self, x, y, sigma, beta, baseline, hrf, nr_TRs): # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) # normalize by the integral rf /= ((2 * np.pi * sigma**2) * 1 / np.diff(self.stimulus.deg_x[0, 0:2])**2) # extract the stimulus time-series response = generate_rf_timeseries_nomask(self.stimulus.stim_arr, rf) # convolve HRF with the stimulus model = fftconvolve(response, hrf)[0:len(response)] # resample to TR (because hrf and stim in sample frequency) model = signal.resample(model, num=nr_TRs, axis=0) # units model /= np.max(model) # offset model += baseline # scale it by beta model *= beta return model
def generate_prediction(self, x, y, sigma, weight, beta, baseline): r""" Predict signal for the Gaussian Model using the full resolution stimulus. Parameters __________ x : float Horizontal location of the Gaussian RF. y: float Vertical location of the Gaussian RF. sigma: float Dipsersion of the Gaussian RF. weight: float Mixture of the magnocellar and parvocellular temporal response to a flickering visual stimulus. The `weight` ranges between 0 and 1, with 0 being a totally magnocellular response and ` being a totally parvocellular response. beta : float Amplitude scaling factor to account for units. baseline: float Amplitude intercept to account for baseline. """ # mask for speed mask = self.distance_mask(x, y, sigma) # generate the RF spatial_rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) spatial_rf /= ((2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x[0,0:2])**2) # spatial response spatial_ts = generate_rf_timeseries(self.stimulus.stim_arr, spatial_rf, mask) # temporal response m_ts, p_ts = generate_mp_timeseries(spatial_ts, self.m_amp, self.p_amp, self.stimulus.flicker_vec) # mix them mp_ts = (1-weight) * m_ts + weight * p_ts # convolve with HRF model = fftconvolve(mp_ts, self.hrf())[0:len(mp_ts)] # units model = (model - np.mean(model)) / np.mean(model) # offset model += baseline # scale it by beta model *= beta return model
def receptive_field(self): rf = generate_og_receptive_field(self.x, self.y, self.sigma, self.model.stimulus.deg_x, self.model.stimulus.deg_y) rf /= ((2 * np.pi * self.sigma**2) * 1/np.diff(self.model.stimulus.deg_x0[0,0:2])**2) return rf
def receptive_field(self): rf = generate_og_receptive_field(self.x, self.y, self.sigma, self.model.stimulus.deg_x, self.model.stimulus.deg_y) rf /= ((2 * np.pi * self.sigma**2) * 1/np.diff(self.model.stimulus.deg_x0[0,0:2])**2) return rf
def receptive_field(self): rf = generate_og_receptive_field(self.model.stimulus.deg_x, self.model.stimulus.deg_y, self.x, self.y, self.sigma) rf *= self.beta return rf
def generate_prediction(self, x, y, sigma, hrf_delay, beta, baseline, unscaled=False): r""" Predict signal for the Gaussian Model. Parameters __________ x : float Horizontal location of the Gaussian RF. y: float Vertical location of the Gaussian RF. sigma: float Dipsersion of the Gaussian RF. hrf_delay: float The delay of the hemodynamic response function (HRF). We assume the cannonical HRF delay is 5 s, and that this parameter is a deviation +/- that 5 s. beta : float Amplitude scaling factor to account for units. baseline: float Amplitude intercept to account for baseline. """ # mask for speed mask = self.distance_mask(x, y, sigma) # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) rf /= (2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x[0,0:2])**2 # extract the stimulus time-series response = generate_rf_timeseries(self.stimulus.stim_arr, rf, mask) # convolve it with the stimulus hrf = self.hrf_model(hrf_delay, self.stimulus.tr_length) model = fftconvolve(response, hrf)[0:len(response)] # units model = self.normalizer(model) if unscaled: return model else: # offset model += baseline # scale it by beta model *= beta return model
def generate_ballpark_prediction(self, x, y, sigma, weight): r""" Predict signal for the Gaussian Model using the downsampled stimulus. The rate of stimulus downsampling is defined in `model.stimulus.scale_factor`. Parameters __________ x : float Horizontal location of the Gaussian RF. y: float Vertical location of the Gaussian RF. sigma: float Dipsersion of the Gaussian RF. weight: float Mixture of the magnocellar and parvocellular temporal response to a flickering visual stimulus. The `weight` ranges between 0 and 1, with 0 being a totally magnocellular response and ` being a totally parvocellular response. """ # mask for speed mask = self.distance_mask_coarse(x, y, sigma) # generate the RF spatial_rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x0, self.stimulus.deg_y0) spatial_rf /= ((2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x0[0,0:2])**2) # spatial_response spatial_ts = generate_rf_timeseries(self.stimulus.stim_arr0, spatial_rf, mask) # temporal response m_ts, p_ts = generate_mp_timeseries(spatial_ts, self.m_amp, self.p_amp, self.stimulus.flicker_vec) # mix them mp_ts = (1-weight) * m_ts + weight * p_ts # convolve with HRF model = fftconvolve(mp_ts, self.hrf())[0:len(mp_ts)] # units model = self.normalizer(model) # regress out mean and linear p = linregress(model, self.data) # offset model += p[1] # scale model *= p[0] return model
def generate_prediction(self, x, y, sigma, hrf_delay, beta, baseline): r""" Predict signal for the Gaussian Model. Parameters __________ x : float Horizontal location of the Gaussian RF. y: float Vertical location of the Gaussian RF. sigma: float Dipsersion of the Gaussian RF. hrf_delay: float The delay of the hemodynamic response function (HRF). We assume the cannonical HRF delay is 5 s, and that this parameter is a deviation +/- that 5 s. beta : float Amplitude scaling factor to account for units. baseline: float Amplitude intercept to account for baseline. """ # mask for speed mask = self.distance_mask(x, y, sigma) # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) rf /= (2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x[0,0:2])**2 # extract the stimulus time-series response = generate_rf_timeseries(self.stimulus.stim_arr, rf, mask) # convolve it with the stimulus hrf = self.hrf_model(hrf_delay, self.stimulus.tr_length) model = fftconvolve(response, hrf)[0:len(response)] # units model = (model-np.mean(model)) / np.mean(model) # offset model += baseline # scale it by beta model *= beta return model
def field_coverage(x, y, s, deg_x, deg_y, log=False, polar=False): # set up figure fig = plt.figure(figsize=(8, 8), dpi=100) if polar: ax = fig.add_subplot(111, projection='polar') else: ax = fig.add_subplot(111, aspect='equal') # set up a blank field field = np.zeros_like(deg_x) # create the RFs for r in np.arange(len(x)): rf = generate_og_receptive_field(x[r], y[r], s[r], deg_x, deg_y) # d = np.sqrt((x[r]-deg_x)**2 + (y[r]-deg_y)**2)<s[r] field += rf # normalize field /= np.max(field) field *= 100 # create image if log: im = ax.imshow(field, cmap='viridis', extent=(-12, 12, -12, 12), norm=LogNorm(), vmin=1e0, vmax=1e2) cb = plt.colorbar( im, format=LogFormatterMathtext(), ) else: im = ax.imshow(field, cmap='viridis', extent=(-12, 12, -12, 12), vmin=1e0, vmax=1e2) cb = plt.colorbar(im) # beautify plt.xticks(np.arange(-12, 13, 3), fontsize='16') plt.yticks(np.arange(-12, 13, 3), fontsize='16') plt.xlabel('degrees in X', fontsize='20') plt.ylabel('degrees in Y', fontsize='20') plt.xlim((-12, 12)) plt.ylim((-12, 12)) plt.subplots_adjust(left=0.12, right=0.98, top=0.98, bottom=.06) plt.grid('on', c='w') plt.show() return field
def generate_prediction(self, x, y, sigma, beta, baseline, unscaled=False): r""" Predict signal for the Gaussian Model. Parameters __________ x : float Horizontal location of the Gaussian RF. y: float Vertical location of the Gaussian RF. sigma: float Dipsersion of the Gaussian RF. beta : float Amplitude scaling factor to account for units. baseline: float Amplitude intercept to account for baseline. """ # mask for speed mask = self.distance_mask(x, y, sigma) # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) rf /= (2 * np.pi * sigma**2) * 1 / np.diff(self.stimulus.deg_x[0, 0:2])**2 # extract the stimulus time-series response = generate_rf_timeseries(self.stimulus.stim_arr, rf, mask) # convolve it with the stimulus model = fftconvolve(response, self.hrf())[0:len(response)] # units model = self.normalizer(model) if unscaled: return model else: # scale it by beta model *= beta # offset model += baseline return model
def generate_ballpark_prediction(self, x, y, sigma, hrf_delay): r""" Predict signal for the Gaussian Model using the downsampled stimulus. The rate of stimulus downsampling is defined in `model.stimulus.scale_factor`. Parameters __________ x : float Horizontal location of the Gaussian RF. y: float Vertical location of the Gaussian RF. sigma: float Dipsersion of the Gaussian RF. hrf_delay: float The delay of the hemodynamic response function (HRF). We assume the cannonical HRF delay is 5 s, and that this parameter is a deviation +/- that 5 s. """ # mask for speed mask = self.distance_mask_coarse(x, y, sigma) # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x0, self.stimulus.deg_y0) rf /= (2 * np.pi * sigma**2) * 1 / np.diff( self.stimulus.deg_x0[0, 0:2])**2 # extract the stimulus time-series response = generate_rf_timeseries(self.stimulus.stim_arr0, rf, mask) # convolve it with the stimulus hrf = self.hrf_model(hrf_delay, self.stimulus.tr_length) model = fftconvolve(response, hrf)[0:len(response)] # units model = self.normalizer(model) # regress out mean and linear p = linregress(model, self.data) # scale model *= p[0] # offset model += p[1] return model
def generate_prediction(self, x, y, sigma, sigma_ratio, volume_ratio): # extract the center response rf_center = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) # extract surround response rf_surround = generate_og_receptive_field(x, y, sigma*sigma_ratio, self.stimulus.deg_x, self.stimulus.deg_y) * 1/sigma_ratio**2 # difference rf = rf_center - np.sqrt(volume_ratio)*rf_surround # extract the response response = generate_rf_timeseries_nomask(self.stimulus.stim_arr, rf) # generate the hrf hrf = self.hrf_model(self.hrf_delay, self.stimulus.tr_length) # convolve it model = fftconvolve(response, hrf)[0:len(response)] return model
def generate_ballpark_prediction(self, x, y, sigma, hrf_delay): r""" Predict signal for the Gaussian Model using the downsampled stimulus. The rate of stimulus downsampling is defined in `model.stimulus.scale_factor`. Parameters __________ x : float Horizontal location of the Gaussian RF. y: float Vertical location of the Gaussian RF. sigma: float Dipsersion of the Gaussian RF. hrf_delay: float The delay of the hemodynamic response function (HRF). We assume the cannonical HRF delay is 5 s, and that this parameter is a deviation +/- that 5 s. """ # mask for speed mask = self.distance_mask_coarse(x, y, sigma) # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x0, self.stimulus.deg_y0) rf /= (2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x0[0,0:2])**2 # extract the stimulus time-series response = generate_rf_timeseries(self.stimulus.stim_arr0, rf, mask) # convolve it with the stimulus hrf = self.hrf_model(hrf_delay, self.stimulus.tr_length) model = fftconvolve(response, hrf)[0:len(response)] # units model = self.normalizer(model) # regress out mean and linear p = linregress(model, self.data) # offset model += p[1] # scale model *= p[0] return model
def generate_prediction(self, x, y, sigma, n, beta, baseline, unscaled=False): # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) # normalize by the integral rf /= ((2 * np.pi * sigma**2) * 1 / np.diff(self.stimulus.deg_x[0, 0:2])**2) # extract the stimulus time-series response = generate_rf_timeseries_nomask(self.stimulus.stim_arr, rf) # compression response **= n # convolve with the HRF hrf = self.hrf_model(self.hrf_delay, self.stimulus.tr_length) # convolve it with the stimulus model = fftconvolve(response, hrf)[0:len(response)] # units model /= np.max(model) # at this point, add filtering with a savitzky-golay filter model_drift = savgol_filter(model, window_length=self.window, polyorder=self.sg_filter_order, deriv=0, mode='nearest') # demain model_drift, so baseline parameter is still interpretable model_drift_demeaned = model_drift - np.mean(model_drift) # and apply to data model -= model_drift_demeaned # offset model += baseline # scale it by beta model *= beta return model
def simulate_neural_sigma(estimate, scatter, deg_x, deg_y, voxel_index, num_neurons=1000, verbose=True): # timestamp start = time.clock() # unpack x = estimate[0] y = estimate[1] sigma = estimate[2] # create the Gaussian voxel_rf = generate_og_receptive_field(deg_x, deg_y, x, y, sigma) # normalize by integral voxel_rf /= 2 * np.pi * sigma**2 # generate random angles and scatters angles = np.random.uniform(0, 2 * np.pi, num_neurons) lengths = np.random.uniform(0, scatter, num_neurons) # convert to cartesian coords xs = x + np.sin(angles) * lengths ys = y + np.cos(angles) * lengths sigma_phat = fmin_powell(error_function, sigma, args=(sigma, voxel_rf, deg_x, deg_y, xs, ys), full_output=True, disp=False) # timestamp finish = time.clock() # progress if verbose: txt = ( "VOXEL=(%.03d,%.03d,%.03d) TIME=%.03d OLD=%.02f NEW=%.02f SCATTER=%.02f" % (voxel_index[0], voxel_index[1], voxel_index[2], finish - start, sigma, sigma_phat[0], scatter)) print(txt) return (voxel_index, sigma, sigma_phat, scatter)
def generate_prediction(self, x, y, sigma, sigma_ratio, volume_ratio, beta, baseline, unscaled=False): # extract the center response rf_center = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) # extract surround response rf_surround = generate_og_receptive_field(x, y, sigma*sigma_ratio, self.stimulus.deg_x, self.stimulus.deg_y) * 1/sigma_ratio**2 # difference rf = ne.evaluate('rf_center - sqrt(volume_ratio)*rf_surround') # extract the response mask = self.distance_mask(x, y, sigma*sigma_ratio) response = generate_rf_timeseries(self.stimulus.stim_arr, rf, mask) # generate the hrf hrf = self.hrf_model(self.hrf_delay, self.stimulus.tr_length) # convolve it model = fftconvolve(response, hrf)[0:len(response)] # units model = self.normalizer(model) if unscaled: return model else: # offset model += baseline # scale it by beta model *= beta return model
def generate_ballpark_prediction(self, x, y, sigma): r""" Predict signal for the Gaussian Model using the downsampled stimulus. The rate of stimulus downsampling is defined in `model.stimulus.scale_factor`. Parameters __________ x : float Horizontal location of the Gaussian RF. y: float Vertical location of the Gaussian RF. sigma: float Dipsersion of the Gaussian RF. """ # mask for speed mask = self.distance_mask_coarse(x, y, sigma) # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x0, self.stimulus.deg_y0) rf /= (2 * np.pi * sigma**2) * 1 / np.diff( self.stimulus.deg_x0[0, 0:2])**2 # extract the stimulus time-series response = generate_rf_timeseries(self.stimulus.stim_arr0, rf, mask) # convolve it with the stimulus model = fftconvolve(response, self.hrf())[0:len(response)] # units model = self.normalizer(model) # regress out mean and amplitude beta, baseline = self.regress(model, self.data) # scale model *= beta # offset model += baseline return model
def generate_ballpark_prediction(self, x, y, sigma): r""" Predict signal for the Gaussian Model using the downsampled stimulus. The rate of stimulus downsampling is defined in `model.stimulus.scale_factor`. Parameters __________ x : float Horizontal location of the Gaussian RF. y: float Vertical location of the Gaussian RF. sigma: float Dipsersion of the Gaussian RF. """ # mask for speed mask = self.distance_mask_coarse(x, y, sigma) # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x0, self.stimulus.deg_y0) rf /= (2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x0[0,0:2])**2 # extract the stimulus time-series response = generate_rf_timeseries(self.stimulus.stim_arr0, rf, mask) # convolve it with the stimulus model = fftconvolve(response, self.hrf())[0:len(response)] # units model = self.normalizer(model) # regress out mean and amplitude beta, baseline = self.regress(model, self.data) # offset model += baseline # scale model *= beta return model
def generate_ballpark_prediction(self, x, y, sigma, n, weight): # mask for speed mask = self.distance_mask_coarse(x, y, sigma) # generate the RF spatial_rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x0, self.stimulus.deg_y0) spatial_rf /= ((2 * np.pi * sigma**2) * 1 / np.diff(self.stimulus.deg_x0[0, 0:2])**2) # spatial_response spatial_ts = generate_rf_timeseries(self.stimulus.stim_arr0, spatial_rf, mask) # compression spatial_ts **= n # temporal response m_ts, p_ts = generate_mp_timeseries(spatial_ts, self.m_amp, self.p_amp, self.stimulus.flicker_vec) # mix them mp_ts = (1 - weight) * m_ts + weight * p_ts # convolve with HRF model = fftconvolve(mp_ts, self.hrf())[0:len(mp_ts)] # units # model = (model - np.mean(model)) / np.mean(model) model = self.normalizer(model) # regress out mean and linear p = linregress(model, self.data) # scale model *= p[0] # offset model += p[1] return model
def generate_prediction(self, x, y, sigma, beta, baseline, hrf_delay): r""" Predict signal for the Gaussian Model using the downsampled stimulus. The rate of stimulus downsampling is defined in `model.stimulus.scale_factor`. Parameters __________ x : float Horizontal location of the Gaussian RF. y: float Vertical location of the Gaussian RF. sigma: float Dipsersion of the Gaussian RF. """ # mask for speed mask = self.distance_mask(x, y, sigma) # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) rf /= (2 * np.pi * sigma**2) * 1 / np.diff(self.stimulus.deg_x[0, 0:2])**2 # extract the stimulus time-series response = generate_rf_timeseries(self.stimulus.stim_arr, rf, mask) # convolve it with the stimulus model = fftconvolve(response, self.hrf_delay())[0:len(response)] # units model = (model - np.mean(model)) / np.mean(model) # offset model += baseline # scale it by beta model *= beta return model
def simulate_neural_sigma(estimate, scatter, deg_x, deg_y, voxel_index, num_neurons=1000, verbose=True): # timestamp start = time.clock() # unpack x = estimate[0] y = estimate[1] sigma = estimate[2] # create the Gaussian voxel_rf = generate_og_receptive_field(deg_x, deg_y, x, y, sigma) # normalize by integral voxel_rf /= 2*np.pi*sigma**2 # generate random angles and scatters angles = np.random.uniform(0,2*np.pi,num_neurons) lengths = np.random.uniform(0,scatter,num_neurons) # convert to cartesian coords xs = x + np.sin(angles)*lengths ys = y + np.cos(angles)*lengths sigma_phat = fmin_powell(error_function, sigma, args=(sigma, voxel_rf, deg_x, deg_y, xs, ys),full_output=True,disp=False) # timestamp finish = time.clock() # progress if verbose: txt = ("VOXEL=(%.03d,%.03d,%.03d) TIME=%.03d OLD=%.02f NEW=%.02f SCATTER=%.02f" %(voxel_index[0], voxel_index[1], voxel_index[2], finish-start, sigma, sigma_phat[0], scatter)) print(txt) return (voxel_index,sigma,sigma_phat,scatter)
def generate_prediction(self, x, y, sigma, beta, baseline, hrf_delay): r""" Predict signal for the Gaussian Model using the downsampled stimulus. The rate of stimulus downsampling is defined in `model.stimulus.scale_factor`. Parameters __________ x : float Horizontal location of the Gaussian RF. y: float Vertical location of the Gaussian RF. sigma: float Dipsersion of the Gaussian RF. """ # mask for speed mask = self.distance_mask(x, y, sigma) # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) rf /= (2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x[0,0:2])**2 # extract the stimulus time-series response = generate_rf_timeseries(self.stimulus.stim_arr, rf, mask) # convolve it with the stimulus model = fftconvolve(response, self.hrf_delay())[0:len(response)] # units model = (model-np.mean(model)) / np.mean(model) # offset model += baseline # scale it by beta model *= beta return model
def field_coverage(x, y, s, deg_x, deg_y, log=False, polar=False): # set up figure fig = plt.figure(figsize=(8,8),dpi=100) if polar: ax = fig.add_subplot(111, projection='polar') else: ax = fig.add_subplot(111, aspect='equal') # set up a blank field field = np.zeros_like(deg_x) # create the RFs for r in np.arange(len(x)): rf = generate_og_receptive_field(x[r], y[r], s[r], deg_x, deg_y) # d = np.sqrt((x[r]-deg_x)**2 + (y[r]-deg_y)**2)<s[r] field += rf # normalize field /= np.max(field) field *= 100 # create image if log: im = ax.imshow(field,cmap='viridis',extent=(-12,12,-12,12),norm=LogNorm(),vmin=1e0,vmax=1e2) cb = plt.colorbar(im, format=LogFormatterMathtext(),) else: im = ax.imshow(field,cmap='viridis',extent=(-12,12,-12,12),vmin=1e0,vmax=1e2) cb = plt.colorbar(im) # beautify plt.xticks(np.arange(-12,13,3),fontsize='16') plt.yticks(np.arange(-12,13,3),fontsize='16') plt.xlabel('degrees in X',fontsize='20') plt.ylabel('degrees in Y',fontsize='20') plt.xlim((-12,12)) plt.ylim((-12,12)) plt.subplots_adjust(left=0.12, right=0.98, top=0.98, bottom=.06) plt.grid('on',c='w') plt.show() return field
def generate_receptive_field(self, x, y, sigma): r""" Generate a Gaussian receptive field in stimulus-referred coordinates. Parameters __________ x : float Horizontal location of the Gaussian RF. y: float Vertical location of the Gaussian RF. sigma: float Dipsersion of the Gaussian RF. """ rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) rf /= (2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x[0,0:2])**2 return rf
def generate_receptive_field(self, x, y, sigma): r""" Generate a Gaussian receptive field in stimulus-referred coordinates. Parameters __________ x : float Horizontal location of the Gaussian RF. y: float Vertical location of the Gaussian RF. sigma: float Dipsersion of the Gaussian RF. """ rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) rf /= (2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x[0,0:2])**2 return rf
def estimate_scaling(self, x, y, sigma): # mask for speed mask = self.distance_mask_coarse(x, y, sigma) # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x0, self.stimulus.deg_y0) rf /= (2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x0[0,0:2])**2 # extract the stimulus time-series response = generate_rf_timeseries(self.stimulus.stim_arr0, rf, mask) # convolve it with the stimulus model = fftconvolve(response, self.hrf())[0:len(response)] # units model = (model-np.mean(model)) / np.mean(model) # regress out mean and linear p = linregress(model, self.data) return p
def generate_prediction(self, x, y, sigma, n, weight, beta, baseline, unscaled=False): # mask for speed mask = self.distance_mask(x, y, sigma) # generate the RF spatial_rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) spatial_rf /= ((2 * np.pi * sigma**2) * 1/np.diff(self.stimulus.deg_x[0,0:2])**2) # spatial response spatial_ts = generate_rf_timeseries(self.stimulus.stim_arr, spatial_rf, mask) # compression spatial_ts **= n # temporal response m_ts, p_ts = generate_mp_timeseries(spatial_ts, self.m_amp, self.p_amp, self.stimulus.flicker_vec) # mix them mp_ts = (1-weight) * m_ts + weight * p_ts # convolve with HRF model = fftconvolve(mp_ts, self.hrf())[0:len(mp_ts)] # convert units model = self.normalizer(model) if unscaled: return model else: # scale model *= beta # offset model += baseline return model
def generate_ballpark_prediction(self, x, y, sigma, n, beta, baseline): # generate the RF rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x0, self.stimulus.deg_y0) # normalize by the integral rf /= ((2 * np.pi * sigma**2) * 1 / np.diff(self.stimulus.deg_x0[0, 0:2])**2) # extract the stimulus time-series response = generate_rf_timeseries_nomask(self.stimulus.stim_arr0, rf) # compression response **= n # convolve with the HRF hrf = self.hrf_model(self.hrf_delay, self.stimulus.tr_length) # convolve it with the stimulus model = fftconvolve(response, hrf)[0:len(response)] # at this point, add filtering with a savitzky-golay filter model = model - savgol_filter( model, window_length=self.sg_filter_window_length, polyorder=self.sg_filter_order, deriv=0, mode='nearest') # scale it by beta model *= beta # offset model += baseline return model
def test_generate_og_receptive_field(): xpixels = 100 # simulated screen width ypixels = 100 # simulated screen height ppd = 1 # simulated visual angle scale_factor = 1.0 # simulated stimulus resampling rate xcenter = 0 # x coordinate of the pRF center ycenter = 0 # y coordinate of the pRF center sigma = 1 # width of the pRF test_value = 6 # this is the sum of a gaussian given 1 ppd # and a 1 sigma prf centered on (0,0) # generate the visuotopic coordinates dx,dy = generate_coordinate_matrices(xpixels, ypixels, ppd, scale_factor) # generate a pRF at (0,0) and 1 sigma wide rf = generate_og_receptive_field(dx, dy, xcenter, ycenter, sigma) # compare the volume of the pRF to a known value nt.assert_equal(np.round(np.sum(rf)), test_value)
def test_generate_og_receptive_field(): xpixels = 500 # simulated screen width ypixels = 500 # simulated screen height ppd = 1 # simulated visual angle scale_factor = 1.0 # simulated stimulus resampling rate distance = 5 # standard deviations to compute gauss out to xcenter = 0 # x coordinate of the pRF center ycenter = 0 # y coordinate of the pRF center sigma = 1 # width of the pRF test_value = 6 # this is the sum of a gaussian given 1 ppd # and a 1 sigma prf centered on (0,0) # generate the visuotopic coordinates dx, dy = generate_coordinate_matrices(xpixels, ypixels, ppd, scale_factor) # generate a pRF at (0,0) and 1 sigma wide rf = generate_og_receptive_field(xcenter, ycenter, sigma, dx, dy) # divide by integral rf /= 2 * np.pi * sigma**2 # compare the volume of the pRF to a known value nt.assert_almost_equal(np.sum(rf), 1)
def receptive_field(self, x, y, sigma, sigma_ratio, volume_ratio): rf_center = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) rf_surround = generate_og_receptive_field(x, y, sigma*sigma_ratio, self.stimulus.deg_x, self.stimulus.deg_y) * 1.0/sigma_ratio**2 rf = rf_center - np.sqrt(volume_ratio)*rf_surround return rf
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 = 0.10 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) model.hrf_delay = 0 model.mask_size = 6 # 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 = (-10,10) y_grid = (-10,10) s_grid = (0.25,5.25) # 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, Ns=3) # coarse fit npt.assert_almost_equal(fit.x0,-10.0) npt.assert_almost_equal(fit.y0,0.0) npt.assert_almost_equal(fit.s0, 5.25) npt.assert_almost_equal(fit.beta0, 1.0) # assert equivalence 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) # test receptive field rf = generate_og_receptive_field(x, y, sigma, fit.model.stimulus.deg_x, fit.model.stimulus.deg_y) 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())) # def test_og_nuisance_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 = 200 # pixels_down = 200 # 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) # model.hrf_delay = 0 # # # generate a random pRF estimate # x = -5.24 # y = 2.58 # sigma = 0.98 # beta = 2.5 # baseline = 0.0 # # # create the "data" # data = model.generate_prediction(x, y, sigma, beta, baseline) # # # create nuisance signal # step = np.zeros(len(data)) # step[30:-30] = 1 # # # add to data # data += step # # # create design matrix # nuisance = sm.add_constant(step) # # # recreate model with nuisance # model = og.GaussianModel(stimulus, utils.double_gamma_hrf, nuisance) # model.hrf_delay = 0 # # # set search grid # x_grid = (-7,7) # y_grid = (-7,7) # s_grid = (0.25,3.25) # # # set search bounds # x_bound = (-10.0,10.0) # y_bound = (-10.0,10.0) # s_bound = (0.001,10.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, Ns=3) # # # assert equivalence # nt.assert_almost_equal(fit.x, x, 1) # nt.assert_almost_equal(fit.y, y, 1) # nt.assert_almost_equal(fit.sigma, sigma, 1) # nt.assert_almost_equal(fit.beta, beta, 1)
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()))
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()))
def receptive_field(self): return generate_og_receptive_field( self.x, self.y, self.sigma, self.model.stimulus.deg_x, self.model.stimulus.deg_y )
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.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 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 npt.assert_almost_equal((fit.x0,fit.y0,fit.sigma0,fit.weight0,fit.beta0,fit.baseline0),[-0.5 , 3.25 , 2.4375, 0.95 , 1. , 0.0113],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.5270727137292481, 2.7416305841622624, 1.2256761293512328, 0.89789336800034436, 0.99962425175020264, -0.25009416568850351],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 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()))
def generate_prediction(self, x, y, sigma, weight, hrf_delay, beta, baseline, unscaled=False): r""" Predict signal for the Gaussian Model using the full resolution stimulus. Parameters __________ x : float Horizontal location of the Gaussian RF. y: float Vertical location of the Gaussian RF. sigma: float Dipsersion of the Gaussian RF. weight: float Mixture of the magnocellar and parvocellular temporal response to a flickering visual stimulus. The `weight` ranges between 0 and 1, with 0 being a totally magnocellular response and ` being a totally parvocellular response. hrf_delay : float The delay of the peak and undershoot of the hemodynamic response function in seconds. This is a number varying about 0 which will be added to the 5 and 15, representing the constant delay of the peak and undershoot. beta : float Amplitude scaling factor to account for units. baseline: float Amplitude intercept to account for baseline. """ # mask for speed mask = self.distance_mask(x, y, sigma) # generate the RF spatial_rf = generate_og_receptive_field(x, y, sigma, self.stimulus.deg_x, self.stimulus.deg_y) spatial_rf /= ((2 * np.pi * sigma**2) * 1 / np.diff(self.stimulus.deg_x[0, 0:2])**2) # spatial response spatial_ts = generate_rf_timeseries(self.stimulus.stim_arr, spatial_rf, mask) # temporal response m_ts, p_ts = generate_mp_timeseries(spatial_ts, self.m_amp, self.p_amp, self.stimulus.flicker_vec) # mix them mp_ts = (1 - weight) * m_ts + weight * p_ts # convolve with HRF model = fftconvolve( mp_ts, self.hrf_model(hrf_delay, self.stimulus.tr_length))[0:len(mp_ts)] # convert units model = self.normalizer(model) if unscaled: return model else: # scale model *= beta # offset model += baseline return model
def test_negative_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.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 = (None,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) # coarse fit ballpark = [-5.0, 5.0, 2.75, -0.27940915461573274, -0.062499999999999993] npt.assert_almost_equal((fit.x0, fit.y0, fit.s0, fit.beta0, fit.baseline0), ballpark) # assert equivalence 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) nt.assert_false(fit.model.bounded_amplitude) nt.assert_true(fit.slope<0) nt.assert_true(fit.beta0<0) nt.assert_true(fit.beta<0) # 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()))