def _format_for_gam2(count, time, pos): assert np.rank(count) == np.rank(time) == (np.rank(pos) - 1) assert count.shape[0] == time.shape[0] == pos.shape[0] assert (count.shape[1] + 1) == time.shape[1] == pos.shape[1] y = count.flatten()[:,None] npt = y.size tax, spax = 1, -1 # don't use real time as won't compare equivalent portions of trials # t = edge2cen(time, axis=tax) # (ntrial, nbin) # subtract offset to get all relative times #t = (t - t[:,:1]).flatten()[:,None] # instead use bin numbers ntrial, nbin = count.shape t = np.tile(np.arange(nbin, dtype=float)[None], (ntrial, 1)) t = t.flatten()[:,None] # also create trial numbers for pulling out appropriate later on # these don't correspond to original trial numbers because original trials # have been permuted before getting here tr = np.tile(np.arange(ntrial), (nbin, 1)).T.flatten() d = kin.get_dir(pos, tax=tax, spax=spax).reshape(npt, 3) p = edge2cen(pos, axis=tax).reshape(npt, 3) v = kin.get_vel(pos, time, tax=tax, spax=spax).reshape(npt, 3) sp = kin.get_speed(pos, time, tax=tax, spax=spax).flatten()[:,None] # q is a second direction set-of-columns for deviance calculation q = kin.get_dir(pos, tax=tax, spax=spax).reshape(npt, 3) return np.concatenate([y,t,d,p,v,sp,q], axis=1), tr
def encode(self, bnd): ''' Return spike counts corresponding to given direction and encoding model. Parameters ---------- bnd :BinnedData uses bnd.pos, bnd.bin_edges ''' pos = bnd.pos time = bnd.bin_edges ntask, nrep, nedge, ndim = pos.shape model = self.model assert(ndim == 3) nbin = nedge - 1 lshape = ntask, nrep, nbin rate = np.zeros(lshape, dtype=float) assert(model == 'kd') # only model currently implemented rate += self.B['k'] # baseline dr = get_dir(pos) rate += np.dot(dr, self.B['D']) # direction rate += np.dot(pos[...,:-1,:], self.B['P']) # position speed = get_speed(pos, time, tax=2, spax=-1) rate += self.B['s'] * speed return np.exp(rate)
def encode(self, bnd): ''' Return spike counts corresponding to given direction and encoding model. Parameters ---------- bnd :BinnedData uses bnd.pos, bnd.bin_edges ''' pos = bnd.pos time = bnd.bin_edges ntask, nrep, nedge, ndim = pos.shape model = self.model assert (ndim == 3) nbin = nedge - 1 lshape = ntask, nrep, nbin rate = np.zeros(lshape, dtype=float) assert (model == 'kd') # only model currently implemented rate += self.B['k'] # baseline dr = get_dir(pos) rate += np.dot(dr, self.B['D']) # direction rate += np.dot(pos[..., :-1, :], self.B['P']) # position speed = get_speed(pos, time, tax=2, spax=-1) rate += self.B['s'] * speed return np.exp(rate)
def _format_for_gam(count, time, pos): ''' Format data for gam_predict_cv, i.e. an (n, 12) array Parameters ---------- count : ndarray spike counts, shape (ntrial, nbin) time : ndarray bin_edges, shape (ntrial, nbin + 1) pos : ndarray positions at `bin_edges`, shape (ntrial, nbin + 1, 3) Returns ------- formatted_data : ndarray shape (ntrial * nbin, 12) dimension 1 is [count, t, dx, dy, dz, px, py, pz, vx, vy, vz, sp] ''' assert np.rank(count) == np.rank(time) == (np.rank(pos) - 1) assert count.shape[0] == time.shape[0] == pos.shape[0] assert (count.shape[1] + 1) == time.shape[1] == pos.shape[1] y = count.flatten()[:,None] npt = y.size tax, spax = 1, -1 # don't use real time as won't compare equivalent portions of trials # t = edge2cen(time, axis=tax) # (ntrial, nbin) # subtract offset to get all relative times #t = (t - t[:,:1]).flatten()[:,None] # instead use bin numbers ntrial, nbin = count.shape t = np.tile(np.arange(nbin, dtype=float)[None], (ntrial, 1)) t = t.flatten()[:,None] d = kin.get_dir(pos, tax=tax, spax=spax).reshape(npt, 3) p = edge2cen(pos, axis=tax).reshape(npt, 3) v = kin.get_vel(pos, time, tax=tax, spax=spax).reshape(npt, 3) sp = kin.get_speed(pos, time, tax=tax, spax=spax).flatten()[:,None] # q is a second direction set-of-columns for deviance calculation q = kin.get_dir(pos, tax=tax, spax=spax).reshape(npt, 3) return np.concatenate([y,t,d,p,v,sp,q], axis=1)
def make_inst_dir_rate(time, pos, pd, kd, sqp={}): ''' Create directional firing components from instantaneous direction, preferred direction, and modulation depth. Parameters ---------- time : ndarray times for pos samples, shape (??) pos : ndarray positional data, shape (ntrial, nbin, 3) pd : array_like pds for a number of cells, shape (nunit, 3) kd : array_like modulation depth, shape (nunit) sqp : dict, optional parameter values for squashing function ''' drn = get_dir(pos, tax=1, spax=-1) rate = np.dot(drn, pd.T) * kd set_squash_defaults(sqp, rate) return squash(rate, sqp)
def prepare_regressors(count, pos, time, model=''): ''' Parameters ---------- count : array_like firing rates, shape (ntrial, nbin) pos : array_like positional data, shape (ntrial, nbin + 1, ndim) these are positions at bin edges time : array_like bin edge times, shape (ntrial, nbin + 1) model : string model Returns ------- reg_vars : ndarray reg_frs : ndarray ''' count = np.asarray(count) assert(np.rank(count) == 2) ntrial, nbin = count.shape assert(not np.any(np.isnan(count))) pos = np.asarray(pos) assert(np.rank(pos) == 3) assert(pos.shape[0:2] == (ntrial, nbin + 1)) time = np.asarray(time) assert(np.rank(time) == 2) assert(time.shape == (ntrial, nbin + 1)) assert(type(model) == str) #ntrial, nbin = count.shape ndim = pos.shape[-1] nvar = ntrial * nbin endog = count.reshape(nvar) # should be equivalent to flatten vels = None exog = None # add the time-invariant variables if 'p' in model: pos_flat = pos[:,1:,:].reshape(nvar, ndim) exog = add_column(exog, pos_flat) if 's' in model: if vels == None: vels = get_vel(pos, time, tax=1, spax=2) spds = np.sqrt(np.sum(vels**2, axis=2)) spds_flat = spds.reshape(nvar) exog = add_column(exog, spds_flat) # do the potentially time-variant variables if ('d' in model or 'v' in model): if 'd' in model: var = get_dir(pos, tax=1, spax=2) elif 'v' in model: if vels == None: vels = get_vel(pos, time, tax=1, spax=2) var = vels if not 'X' in model: # time-static variable var_flat = np.reshape(var, (nvar, ndim)) else: # time-dynamic variable mask = np.eye(nbin) var_flat = np.reshape(mask[None,...,None] * var[...,None,:], (nvar, nbin * ndim)) exog = add_column(exog, var_flat) # do the constant + dynamic direction model if 'q' in model: assert ('X' in model) # for simplicity's sake, let us call this model 'kqX' assert ('d' not in model) assert ('v' not in model) if 'k' in model: exog = sm.tools.add_constant(exog, prepend=False) offset = np.log(np.diff(time, axis=-1).reshape(nvar)) return endog, exog, offset
def test_gam_predict_cv(): dsname = 'frank-osmd' align = 'hold' lag = 0.1 # s b0 = 20 # Hz noise_sd = 1. # Hz b_scale = 10. nbin = 10 ds = datasets[dsname] dc = DataCollection(ds.get_files()[:5]) unit = ds.get_units()[0] dc.add_unit(unit, lag) bnd = dc.make_binned(nbin=nbin, align=align, do_count=True) ntask, nrep, nedge, ndim = bnd.pos.shape pos = bnd.pos.reshape(ntask * nrep, nedge, -1) drn = kin.get_dir(pos) # simplest model # y = b0 + Bd.D B = np.array([.2, .6, .4]) * b_scale y = b0 + np.dot(drn, B) noise = np.random.normal(0, noise_sd, size=y.shape) y += noise bnd.set_count_from_flat(y[:,None]) out = gam_predict_cv(bnd, ['kd'], [dsname, unit, lag, align], \ family='gaussian') have = np.mean(out.coef[0], axis=0)[:4] want = np.array([b0, B[0], B[1], B[2]]) np.testing.assert_array_almost_equal(have, want, decimal=1) # changing Bdt model, gaussian noise model # y = b0 + Bdt.D gc_type = [('A', float), ('fwhm', float), ('c', float)] gcoeff = np.array([[(1., 1.5, 3.), (.75, 2.5, 6.)], [(.4, 4., 2.), (.1, 2., 5.)], [(.8, 3., 5.), (.6, 4.5, 6.5)]], dtype=gc_type) gcoeff = gcoeff.view(np.recarray) x = np.linspace(0, 10, nbin) Bt = np.zeros((3, nbin)) for Bkt, gc in zip(Bt, gcoeff): g0 = gauss1d(x, gc.A[0], gc.fwhm[0], gc.c[0]) g1 = gauss1d(x, gc.A[1], gc.fwhm[1], gc.c[1]) Bkt[:] = g0 + g1 Bt *= b_scale y = b0 + np.sum(Bt.T[None] * drn, axis=-1) y = np.random.normal(y, noise_sd) bnd.set_count_from_flat(y[:,None]) out = gam_predict_cv(bnd, ['kdX'], [dsname, unit, lag, align], \ family='gaussian') # check that actual and predicted are correlated x = out.actual.flatten() y = out.pred[8].flatten() mc, rp = pearsonr(x,y) np.testing.assert_approx_equal(mc, 1, significant=1)