def get_threshold_index(p_load): ''' Return a dataframe with a binary telling you if a particular contact ellicited a spike for each cell :param p_load: path to the neo files :return: a pandas dataframe with all the contacts for all cells. Cannot reshape since every whisker has a dif. number of contacts ''' df_all = pd.DataFrame() for f in glob.glob(os.path.join(p_load, '*.h5')): blk = neoUtils.get_blk(f) num_units = len(blk.channel_indexes[-1].units) for unit_num in xrange(num_units): df = pd.DataFrame() id = neoUtils.get_root(blk, unit_num) print('working on {}'.format(id)) trains = spikeAnalysis.get_contact_sliced_trains(blk, unit_num)[-1] dir_idx, med_dir = worldGeometry.get_contact_direction( blk, plot_tgl=False) if dir_idx is -1: continue dir_map = {key: value for (key, value) in enumerate(med_dir)} df['id'] = [id for x in xrange(len(trains))] df['did_spike'] = [len(x) > 0 for x in trains] df['dir_idx'] = dir_idx df['med_dir'] = df['dir_idx'].map(dir_map) df_all = df_all.append(df) return (df_all)
def ISI_by_deflection(blk, unit_num=0): unit = blk.channel_indexes[-1].units[unit_num] ISI = spikeAnalysis.get_contact_sliced_trains(blk, unit)[1] CV, LV = spikeAnalysis.get_CV_LV(ISI) mean_ISI = np.array([np.mean(x) for x in ISI]) idx, med_angle = worldGeometry.get_contact_direction(blk, plot_tgl=False) df = pd.DataFrame() df['id'] = [neoUtils.get_root(blk, unit_num) for x in range(len(ISI))] df['mean_ISI'] = mean_ISI df['CV'] = CV df['LV'] = LV df['dir_idx'] = idx df['med_dir'] = [med_angle[x] for x in idx] return (df)
def get_onset_and_duration_spikes(p_load, dur=10 * pq.ms): """ loops through all the data we have and gets the number of spikes during an onset duration, the total number of spikes during the contact duration, and the length of the contact. This will allow us to calculate how much the spiking occurs in the first interval :param p_load: directory where the h5 files live :param dur: a python quantity to determine the 'onset' epoch :return: a dataframe with a summary of the relevant data """ df_all = pd.DataFrame() for f in glob.glob(os.path.join(p_load, '*.h5')): blk = neoUtils.get_blk(f) num_units = len(blk.channel_indexes[-1].units) for unit_num in range(num_units): df = pd.DataFrame() id = neoUtils.get_root(blk, unit_num) print('Working on {}'.format(id)) _, _, trains = spikeAnalysis.get_contact_sliced_trains( blk, unit_num) dir_idx, med_angle = worldGeometry.get_contact_direction( blk, plot_tgl=False) dir = [] full = [] contact_duration = [] onset = [] for train, direction in zip(trains, dir_idx): onset.append( len(train.time_slice(train.t_start, train.t_start + dur))) full.append(len(train)) dir.append(direction) contact_duration.append(float(train.t_stop - train.t_start)) df_dir = pd.DataFrame() df_dir['dir_idx'] = dir df_dir['time'] = contact_duration df_dir['total_spikes'] = full df_dir['onset_spikes'] = onset df_dir['med_angle'] = [med_angle[x] for x in df_dir.dir_idx] df_dir['id'] = id df_all = df_all.append(df_dir) df_all['onset_period'] = dur return (df_all)
def get_first_spike_vals(fname, p_smooth, unit_num): """ Return a dataframe with length Ncontacts and the value of relevant stimulus features at that time :param blk: neo block :param unit_num: int :return: pandas dataframe """ # get the blocks blk = neoUtils.get_blk(fname) blk_smooth = GLM.get_blk_smooth(fname, p_smooth) # get the trains and times of first spikes _, _, trains = spikeAnalysis.get_contact_sliced_trains(blk, unit_num) t_idx = [ train[0].magnitude if len(train) > 0 else np.nan for train in trains ] t_idx = np.array(t_idx) t_idx = t_idx[np.isfinite(t_idx)].astype('int') # get the stimuli varlist = ['M', 'F', 'TH', 'PHIE'] X = GLM.create_design_matrix(blk, varlist) Xsmooth = GLM.get_deriv(blk, blk_smooth, varlist, smoothing=[9])[1] MB = np.sqrt(X[:, 1]**2 + X[:, 2]**2)[:, np.newaxis] FB = np.sqrt(X[:, 4]**2 + X[:, 5]**2)[:, np.newaxis] RB = np.sqrt(X[:, 6]**2 + X[:, 7]**2)[:, np.newaxis] # use smooth to calculate derivative MBsmooth = np.sqrt(Xsmooth[:, 1]**2 + Xsmooth[:, 2]**2)[:, np.newaxis] FBsmooth = np.sqrt(Xsmooth[:, 4]**2 + Xsmooth[:, 5]**2)[:, np.newaxis] RBsmooth = np.sqrt(Xsmooth[:, 6]**2 + Xsmooth[:, 7]**2)[:, np.newaxis] X = np.concatenate([MB, FB, RB], axis=1) Xsmooth = np.concatenate([MBsmooth, FBsmooth, RBsmooth], axis=1) Xdot = np.diff(np.concatenate([np.zeros([1, 3]), Xsmooth]), axis=0) X = np.concatenate([X, Xdot], axis=1) #extract stimulus at time of first spike and output to a dataframe vals = X[t_idx] vallist = ['MB', 'FB', 'RB', 'MBdot', 'FBdot', 'RBdot'] df = pd.DataFrame() for ii in range(len(vallist)): df[vallist[ii]] = vals[ii, :] df['id'] = neoUtils.get_root(blk, unit_num) return (df)
def get_PSTH_by_dir(blk, unit_num=0, norm_dur=True, binsize=5 * pq.ms): ''' Gets the PSTHs for each direction. :param blk: :param unit_num: :param norm_dur: :param binsize: :return PSTH, t_edges, max_fr: The PSTH binheights, the bin edges, and the max value of FR ''' unit = blk.channel_indexes[-1].units[unit_num] _, _, trains = spikeAnalysis.get_contact_sliced_trains(blk, unit) b, durations = spikeAnalysis.get_binary_trains(trains) idx, med_angle = worldGeometry.get_contact_direction(blk, plot_tgl=False) if idx is -1: return (-1, -1, -1, -1) th_contacts, ph_contacts = worldGeometry.get_delta_angle(blk) PSTH = [] t_edges = [] max_fr = [] for dir in np.arange(np.max(idx) + 1): sub_idx = np.where(idx == dir)[0] sub_trains = [trains[ii] for ii in sub_idx] if norm_dur: t_edges_temp, PSTH_temp, w = spikeAnalysis.get_time_stretched_PSTH( sub_trains, nbins=25) else: spt = spikeAnalysis.trains2times(sub_trains, concat_tgl=True) PSTH_temp, t_edges_temp = np.histogram(spt, bins=np.arange( 0, 500, float(binsize))) PSTH_temp = PSTH_temp.astype('f8') / len(durations) / pq.ms * 1000. w = binsize max_fr.append(np.max(PSTH_temp)) PSTH.append(PSTH_temp) t_edges.append(t_edges_temp) max_fr = np.max(max_fr) return (PSTH, t_edges, max_fr, med_angle)
def anova_analysis(blk, unit_num=0): use_flags = neoUtils.concatenate_epochs(blk) root = neoUtils.get_root(blk, unit_num) idx_dir, med_dir = worldGeometry.get_contact_direction(blk, plot_tgl=False) FR = spikeAnalysis.get_contact_sliced_trains(blk, unit_num)[0].magnitude idx_S = worldGeometry.get_radial_distance_group(blk, plot_tgl=False) # Create arclength groups if idx_S is -1: print('Only one arclength group') arclength_labels = ['Proximal'] elif idx_S is -2: print('Too few contacts') return (-1, -1) if np.max(idx_S) == 2: arclength_labels = ['Proximal', 'Medial', 'Distal'] elif np.max(idx_S) == 1: arclength_labels = ['Proximal', 'Distal'] idx_S = [arclength_labels[x] for x in idx_S] df = pd.DataFrame() directions = pd.DataFrame() df['Firing_Rate'] = FR df['Arclength'] = idx_S df['Direction'] = idx_dir df['id'] = root directions['med_dir'] = med_dir directions['Direction'] = list(set(df['Direction'])) df = df.merge(directions) df.dropna() formula = 'Firing_Rate ~ C(Direction) + C(Arclength) + C(Arclength):C(Direction)' model = ols(formula, df).fit(missing='drop') aov_table = anova_lm(model, typ=1) aov_table['id'] = root return df, aov_table
def onset_tuning(blk, unit_num=0, use_zeros=True): ''' Calculate the onset velocity in both terms of CP and in terms of rotation. Calculate the relationship between the onset firing rate and the different velcocities :param blk: :param unit_num: :param use_zeros: :return V_cp_fit,V_rot_fit: ''' use_flags = neoUtils.concatenate_epochs(blk) trains = spikeAnalysis.get_contact_sliced_trains(blk, unit_num)[-1] apex = neoUtils.get_contact_apex_idx(blk) * pq.ms apex_idx = apex.magnitude.astype('int') id = neoUtils.get_root(blk, unit_num) # get MB and FB at apex M = neoUtils.get_var(blk) MB = neoUtils.get_MB_MD(M)[0] MB_contacts = neoUtils.get_analog_contact_slices(MB, use_flags) MB_apex = neoUtils.get_value_at_idx(MB_contacts, apex_idx).squeeze() MB_dot = MB_apex / apex F = neoUtils.get_var(blk, 'F') FB = neoUtils.get_MB_MD(F)[0] FB_contacts = neoUtils.get_analog_contact_slices(FB, use_flags) FB_apex = neoUtils.get_value_at_idx(FB_contacts, apex_idx).squeeze() FB_dot = FB_apex / apex # Get onset FR onset_counts = np.array([ len(train.time_slice(train.t_start, train.t_start + dur)) for train, dur in zip(trains, apex) ]) onset_FR = np.divide(onset_counts, apex) onset_FR.units = 1 / pq.s # get V_onset_rot V_rot, _, D = worldGeometry.get_onset_velocity(blk) dir_idx, dir_angle = worldGeometry.get_contact_direction(blk, False) if dir_idx is -1: return (-1, -1, -1) df = pd.DataFrame() df['id'] = [id for x in xrange(MB_dot.shape[0])] df['MB'] = MB_apex df['MB_dot'] = MB_dot df['FB_dot'] = FB_dot df['FB'] = FB_apex df['rot'] = D df['rot_dot'] = V_rot df['dir_idx'] = dir_idx df['FR'] = onset_FR df['dir_angle'] = [dir_angle[x] for x in dir_idx] df = df.replace(np.inf, np.nan) df = df.dropna() # FIT: fits_all = pd.DataFrame( columns=['id', 'var', 'rvalue', 'pvalue', 'slope', 'intercept']) fits_direction = pd.DataFrame() idx = 0 idx2 = 0 for var in ['MB', 'MB_dot', 'FB', 'FB_dot', 'rot', 'rot_dot']: fit = stats.linregress(df[var], df['FR'])._asdict() fits_all.loc[idx, 'id'] = id fits_all.loc[idx, 'var'] = var for k, v in fit.iteritems(): fits_all.loc[idx, k] = v idx += 1 for direction in xrange(np.max(dir_idx) + 1): temp_idx = df['dir_idx'] == direction if not np.any(temp_idx): continue fit = stats.linregress(df[var][temp_idx], df['FR'][temp_idx])._asdict() fits_direction.loc[idx2, 'id'] = id fits_direction.loc[idx2, 'var'] = var fits_direction.loc[idx2, 'dir_idx'] = direction fits_direction.loc[idx2, 'med_dir'] = dir_angle[direction] for k, v in fit.iteritems(): fits_direction.loc[idx2, k] = v idx2 += 1 return (fits_all, fits_direction, df)
def plot_spike_trains_by_direction(blk, unit_num=0, norm_dur=False, binsize=5 * pq.ms): unit = blk.channel_indexes[-1].units[unit_num] _, _, trains = spikeAnalysis.get_contact_sliced_trains(blk, unit) b, durations = spikeAnalysis.get_binary_trains(trains) idx, med_angle = worldGeometry.get_contact_direction(blk, plot_tgl=False) if idx is -1: return (-1) th_contacts, ph_contacts = worldGeometry.get_delta_angle(blk) cc = sns.color_palette("husl", 8) f = plt.figure(tight_layout=True) f.set_dpi(300) f.set_size_inches(9, 9) gs = gridspec.GridSpec(3, 3) ax = plt.subplot(gs[1:-1, 1:-1]) to_rotate = -med_angle[0] R = np.array([[np.cos(to_rotate), -np.sin(to_rotate)], [np.sin(to_rotate), np.cos(to_rotate)]]) # plot deflections for ii in xrange(len(idx)): th = np.deg2rad(th_contacts[:, ii]) ph = np.deg2rad(ph_contacts[:, ii]) X = np.vstack((th, ph)) X_rot = np.dot(R, X) plt.plot(np.rad2deg(X_rot[0, :]), np.rad2deg(X_rot[1, :]), '.-', color=cc[idx[ii]], alpha=0.3) ax.set_xlabel(r'$\theta$ (deg)') ax.set_ylabel(r'$\phi$ (deg)') axis_coords = [[1, 2], [0, 2], [0, 1], [0, 0], [1, 0], [2, 0], [2, 1], [2, 2]] time_lim = np.percentile(durations, 90) # drop the tenth percentile of durations PSTH = [] t_edges = [] max_fr = [] for dir in np.arange(np.max(idx) + 1): sub_idx = np.where(idx == dir)[0] sub_trains = [trains[ii] for ii in sub_idx] if norm_dur: t_edges_temp, PSTH_temp, w = spikeAnalysis.get_time_stretched_PSTH( sub_trains) else: spt = spikeAnalysis.trains2times(sub_trains, concat_tgl=True) PSTH_temp, t_edges_temp = np.histogram(spt, bins=np.arange( 0, 500, float(binsize))) PSTH_temp = PSTH_temp.astype('f8') / len(durations) / pq.ms * 1000. w = binsize max_fr.append(np.max(PSTH_temp)) PSTH.append(PSTH_temp) t_edges.append(t_edges_temp) max_fr = np.max(max_fr) for dir in np.arange(np.max(idx) + 1): ax = plt.subplot(gs[axis_coords[dir][0], axis_coords[dir][1]]) ax.set_ylim([0, 1]) if norm_dur: ax.set_xlim(0, 1) else: ax.set_xlim(0, time_lim) plt.bar(t_edges[dir][:-1], PSTH[dir] / max_fr, width=w, align='edge', alpha=1, color=cc[dir]) sns.despine() f.suptitle(neoUtils.get_root(blk, unit_num)) return (0)