def plot_binaural_psths(df, cellid, bg, fg, batch, save=False, close=False): '''Takes input of a data fram from ohel.calc_psth_metrics along with a cellid and pair of sounds and will plot all the spatial psth combos with spectrogram of sound. Can save.''' manager = BAPHYExperiment(cellid=cellid, batch=batch) options = ohel.get_load_options(batch) rec = manager.get_recording(**options) rec['resp'] = rec['resp'].extract_channels([cellid]) resp = copy.copy(rec['resp'].rasterize()) expt_params = manager.get_baphy_exptparams() # Using Charlie's manager if len(expt_params) == 1: ref_handle = expt_params[0]['TrialObject'][1]['ReferenceHandle'][1] if len(expt_params) > 1: ref_handle = expt_params[-1]['TrialObject'][1]['ReferenceHandle'][1] BG_folder, FG_folder = ref_handle['BG_Folder'], ref_handle['FG_Folder'] ## I could make this not dependent on DF if I add some code that loads the epochs of the cell ## that you inputted and applies that type label function, that's really all I'm using from df df_filtered = df[(df.BG == bg) & (df.FG == fg) & (df.cellid == cellid)] if len(df_filtered) == 0: pairs = get_pair_names(cellid, df, show=False) raise ValueError(f"The inputted BG: {bg} and FG: {fg} are not in {cellid}.\n" f"Maybe try one of these:\n{pairs}") epochs = [] name = df_filtered.epoch.loc[df_filtered.kind == '11'].values[0] bb, ff = name.split('_')[1], name.split('_')[2] bb1, ff1 = name.replace(ff, 'null'), name.replace(bb, 'null') epochs.append(bb1), epochs.append(ff1) name = df_filtered.epoch.loc[df_filtered.kind == '22'].values[0] bb, ff = name.split('_')[1], name.split('_')[2] bb2, ff2 = name.replace(ff, 'null'), name.replace(bb, 'null') epochs.append(bb2), epochs.append(ff2) epochs.extend(df_filtered.epoch.values) r = resp.extract_epochs(epochs) SR = df_filtered['SR'].values[0] f = plt.figure(figsize=(18, 9)) psth11 = plt.subplot2grid((9, 8), (0, 0), rowspan=3, colspan=3) psth12 = plt.subplot2grid((9, 8), (0, 3), rowspan=3, colspan=3, sharey=psth11) psth21 = plt.subplot2grid((9, 8), (3, 0), rowspan=3, colspan=3, sharey=psth11) psth22 = plt.subplot2grid((9, 8), (3, 3), rowspan=3, colspan=3, sharey=psth11) specA1 = plt.subplot2grid((9, 8), (7, 0), rowspan=1, colspan=3) specB1 = plt.subplot2grid((9, 8), (8, 0), rowspan=1, colspan=3) specA2 = plt.subplot2grid((9, 8), (7, 3), rowspan=1, colspan=3) specB2 = plt.subplot2grid((9, 8), (8, 3), rowspan=1, colspan=3) psthbb = plt.subplot2grid((9, 8), (0, 6), rowspan=3, colspan=2, sharey=psth11) psthff = plt.subplot2grid((9, 8), (3, 6), rowspan=3, colspan=2, sharey=psth11) ax = [psth11, psth12, psth21, psth22, specA1, specB1, specA2, specB2, psthbb, psthff] prestim = resp.epochs[resp.epochs['name'] == 'PreStimSilence'].copy().iloc[0]['end'] time = (np.arange(0, r[epochs[0]].shape[-1]) / options['rasterfs']) - prestim # r_mean = {e: np.squeeze(np.nanmean(r[e], axis=0)) for e in epochs} r_mean = {e: np.squeeze(np.nanmean(r[e], axis=0)) - SR for e in epochs} epochs.extend(['lin11', 'lin12', 'lin21', 'lin22']) bg1, fg1, bg2, fg2 = epochs[0], epochs[1], epochs[2], epochs[3] r_mean['lin11'], r_mean['lin12'] = r_mean[bg1]+r_mean[fg1], r_mean[bg1]+r_mean[fg2] r_mean['lin21'], r_mean['lin22'] = r_mean[bg2]+r_mean[fg1], r_mean[bg2]+r_mean[fg2] colors = ['deepskyblue'] *3 + ['violet'] *3 + ['yellowgreen'] *3 + ['darksalmon'] *3 \ + ['dimgray'] *4 + ['black'] *4 styles = ['-'] *16 + [':'] *4 ax_num = [0, 1, 8, 2, 3, 8, 0, 2, 9, 1, 3, 9, 0, 1, 2, 3, 0, 1, 2, 3] ep_num = [0, 0, 0, 2, 2, 2, 1, 1, 1, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11] labels = ['BG1'] *3 + ['BG2'] *3 + ['FG1'] *3 + ['FG2'] *3 \ + ['BG1+FG1'] + ['BG1+FG2'] + ['BG2+FG1'] + ['BG2+FG2'] + ['LS'] *4 for e, a, c, s, l in zip(ep_num, ax_num, colors, styles, labels): ax[a].plot(time, sf.gaussian_filter1d(r_mean[epochs[e]], sigma=2) * options['rasterfs'], color=c, linestyle=s, label=l) ymin, ymax = ax[0].get_ylim() AXS = [0, 1, 2, 3, 8, 9] for AX, tt, aab, bab, ali, bli, prf in zip(range(4), df_filtered.kind, df_filtered.AcorAB, df_filtered.BcorAB, df_filtered.AcorLin, df_filtered.BcorLin, df_filtered.pref): ax[AX].legend((f'BG{tt[0]}, corr={np.around(aab, 3)}', f'FG{tt[1]}, corr={np.around(bab, 3)}', f'BG{tt[0]}+FG{tt[1]}', f'LS, Acorr={np.around(ali, 3)}\nBcorr={np.around(bli, 3)}\npref={np.around(prf, 3)}')) for AX in AXS: ax[AX].vlines([0, 1.0], ymin, ymax, color='black', lw=0.75, ls='--') ax[AX].vlines(0.5, ymax * 0.9, ymax, color='black', lw=0.75, ls=':') ax[AX].spines['right'].set_visible(True), ax[AX].spines['top'].set_visible(True) if AX !=8 and AX !=9: ax[AX].set_xlim((-prestim * 0.5), (1 + (prestim * 0.75))) else: ax[AX].set_xlim((-prestim * 0.15), (1 + (prestim * 0.25))) if AX == 0 or AX == 1 or AX == 8: plt.setp(ax[AX].get_xticklabels(), visible=False) if AX == 1 or AX == 3 or AX == 8 or AX == 9: plt.setp(ax[AX].get_yticklabels(), visible=False) if AX == 2 or AX == 3 or AX == 9: ax[AX].set_xlabel('Time(s)', fontweight='bold', fontsize=10) if AX == 0 or AX == 2: ax[AX].set_ylabel('Spikes', fontweight='bold', fontsize=10) ax[0].set_title(f"{cellid} - BG: {bg} - FG: {fg}", fontweight='bold', fontsize=12) bbn, ffn = bb[:2], ff[:2] bg_path = glob.glob((f'/auto/users/hamersky/baphy/Config/lbhb/SoundObjects/@OverlappingPairs/' f'{BG_folder}/{bbn}*.wav'))[0] fg_path = glob.glob((f'/auto/users/hamersky/baphy/Config/lbhb/SoundObjects/@OverlappingPairs/' f'{FG_folder}/{ffn}*.wav'))[0] xf = 100 low, high = ax[0].get_xlim() low, high = low * xf, high * xf for AX in range(4,8): if AX == 4 or AX == 6: sfs, W = wavfile.read(bg_path) elif AX == 5 or AX == 7: sfs, W = wavfile.read(fg_path) spec = gtgram(W, sfs, 0.02, 0.01, 48, 100, 24000) ax[AX].imshow(spec, aspect='auto', origin='lower', extent=[0, spec.shape[1], 0, spec.shape[0]]) ax[AX].set_xlim(low, high) ax[AX].set_xticks([]), ax[AX].set_yticks([]) ax[AX].set_xticklabels([]), ax[AX].set_yticklabels([]) ax[AX].spines['top'].set_visible(False), ax[AX].spines['bottom'].set_visible(False) ax[AX].spines['left'].set_visible(False), ax[AX].spines['right'].set_visible(False) ax[4].set_ylabel(f"{bb.split('-')[0]}", fontweight='bold') ax[5].set_ylabel(f"{ff.split('-')[0]}", fontweight='bold') if save: site, animal, area, unit = cellid.split('-')[0], cellid[:3], df.area.loc[df.cellid == cellid].unique()[0], cellid[8:] path = f"/home/hamersky/OLP Binaural/{animal}/{area}/{site}/{unit}/" Path(path).mkdir(parents=True, exist_ok=True) print(f"Saving to {path + f'{cellid}-{bg}-{fg}.png'}") plt.savefig(path + f"{cellid}-{bg}-{fg}.png") if close: plt.close()
p2ax.plot((spk_times2[1] / rasterfs) - 2, lim + (spk_times2[0] / 1), '|', color='k', markersize=0.75, alpha=0.5) spec_offset = lim + ((spk_times1[0] / 1)).max() + 2 # spectrogram fs, data = wavfile.read(soundfile) # pad / crop data data = data[:int(3 * fs)] spbins = int(2 * fs) postbins = int(0.5 * fs) data = np.concatenate((np.zeros(spbins), data, np.zeros(postbins))) spec = gt.gtgram(data, fs, 0.01, 0.002, 100, 0) p1ax.imshow(np.sqrt(spec), cmap='Greys', origin='lower', aspect='auto', extent=[-2, 3.5, spec_offset, spec_offset + 20]) p1ax.axvline(0, linestyle='--', lw=1, color='lime') p1ax.axvline(3, linestyle='--', lw=1, color='lime') p1ax.set_ylabel("Spk / s") p1ax.set_title(r"$\bar p_{k} = %s$" % np.round(mean_pupil1, 2)) p1ax.set_xlabel('Time (s)') p1ax.set_xlim((-2, 3.5)) p1ax.set_ylim((0, spec_offset + 20)) p2ax.imshow(np.sqrt(spec), cmap='Greys',
def get_sound_statistics(weight_df, plot=True): '''5/12/22 Takes a cellid and batch and figures out all the sounds that were played in that experiment and calculates some stastistics it plots side by side. Also outputs those numbers in a cumbersome dataframe''' lfreq, hfreq, bins = 100, 24000, 48 cid, btch = weight_df.cellid.iloc[0], weight_df.batch.iloc[0] manager = BAPHYExperiment(cellid=cid, batch=btch) expt_params = manager.get_baphy_exptparams() # Using Charlie's manager ref_handle = expt_params[-1]['TrialObject'][1]['ReferenceHandle'][1] BG_folder, FG_folder = ref_handle['BG_Folder'], ref_handle['FG_Folder'] bbs = list(set([bb.split('_')[1][:2] for bb in weight_df.epoch])) ffs = list(set([ff.split('_')[2][:2] for ff in weight_df.epoch])) bbs.sort(key=int), ffs.sort(key=int) bg_paths = [glob.glob((f'/auto/users/hamersky/baphy/Config/lbhb/SoundObjects/@OverlappingPairs/' f'{BG_folder}/{bb}*.wav'))[0] for bb in bbs] fg_paths = [glob.glob((f'/auto/users/hamersky/baphy/Config/lbhb/SoundObjects/@OverlappingPairs/' f'{FG_folder}/{ff}*.wav'))[0] for ff in ffs] paths = bg_paths + fg_paths bgname = [bb.split('/')[-1].split('.')[0] for bb in bg_paths] fgname = [ff.split('/')[-1].split('.')[0] for ff in fg_paths] names = bgname + fgname Bs, Fs = ['BG'] * len(bgname), ['FG'] * len(fgname) labels = Bs + Fs sounds = [] means = np.empty((bins, len(names))) means[:] = np.NaN for cnt, sn, pth, ll in zip(range(len(labels)), names, paths, labels): sfs, W = wavfile.read(pth) spec = gtgram(W, sfs, 0.02, 0.01, bins, lfreq, hfreq) dev = np.std(spec, axis=1) freq_mean = np.nanmean(spec, axis=1) x_freq = np.logspace(np.log2(lfreq), np.log2(hfreq), num=bins, base=2) csm = np.cumsum(freq_mean) big = np.max(csm) freq75 = x_freq[np.abs(csm - (big * 0.75)).argmin()] freq25 = x_freq[np.abs(csm - (big * 0.25)).argmin()] freq50 = x_freq[np.abs(csm - (big * 0.5)).argmin()] bandw = np.log2(freq75 / freq25) means[:, cnt] = freq_mean sounds.append({'name': sn, 'type': ll, 'std': dev, 'bandwidth': bandw, '75th': freq75, '25th': freq25, 'center': freq50, 'spec': spec, 'mean_freq': freq_mean, 'freq_stationary': np.std(freq_mean)}) sound_df = pd.DataFrame(sounds) # allmean = np.nanmean(means, axis=1, keepdims=True) # norm_mean = [aa / allmean for aa in sound_df.mean_freq] # freq_stationarity = [np.std(aa) for aa in allmean] # sound_df['norm_mean'], = norm_mean # sound_df['freq_stationary'] = freq_stationarity ss = sound_df.explode('std') # frs = sound_df.explode('norm_mean') # frs = sound_df.explode('mean_freq') snames = [dd[2:] for dd in sound_df.name] if plot: fig, ax = plt.subplots(1, 3, figsize=(18, 8)) sb.barplot(x='name', y='std', palette=["lightskyblue" if x == 'BG' else 'yellowgreen' for x in sound_df.type], data=ss, ci=68, ax=ax[0], errwidth=1) ax[0].set_xticklabels(snames, rotation=90, fontweight='bold', fontsize=7) ax[0].set_ylabel('Non-stationariness', fontweight='bold', fontsize=12) ax[0].spines['top'].set_visible(True), ax[0].spines['right'].set_visible(True) ax[0].set(xlabel=None) sb.barplot(x='name', y='bandwidth', palette=["lightskyblue" if x == 'BG' else 'yellowgreen' for x in sound_df.type], data=sound_df, ax=ax[1]) ax[1].set_xticklabels(snames, rotation=90, fontweight='bold', fontsize=7) ax[1].set_ylabel('Bandwidth (octaves)', fontweight='bold', fontsize=12) ax[1].spines['top'].set_visible(True), ax[1].spines['right'].set_visible(True) ax[1].set(xlabel=None) sb.barplot(x='name', y='freq_stationary', palette=["lightskyblue" if x == 'BG' else 'yellowgreen' for x in sound_df.type], data=sound_df, ax=ax[2]) ax[2].set_xticklabels(snames, rotation=90, fontweight='bold', fontsize=7) ax[2].set_ylabel('Frequency Non-stationariness', fontweight='bold', fontsize=12) ax[2].spines['top'].set_visible(True), ax[2].spines['right'].set_visible(True) ax[2].set(xlabel=None) fig.tight_layout() return sound_df
f'Background2/*.wav')) fg_dir = glob.glob((f'/auto/users/hamersky/baphy/Config/lbhb/SoundObjects/@OverlappingPairs/' f'Foreground3/*.wav')) fgs= fg_dir[:5] #ferrets fgs = fg_dir[5:15] # marms names = [aa.split('/')[-1] for aa in fgs] pl = 0 fig, axes = plt.subplots(5,1, sharey=True) ax = axes.ravel() for pl in range(len(fgs)): path = fgs[pl] sfs, W = wavfile.read(path) spec = gtgram(W, sfs, 0.02, 0.01, 48, 100, 32000) # ax[pl].plot(W) ax[pl].set_title(f"{names[pl]}") ax[pl].imshow(np.log(spec), aspect='auto', origin='lower', extent=[0, spec.shape[1], 0, spec.shape[0]]) fig.tight_layout() pl = 0 fig, axes = plt.subplots(5,1, sharey=True) ax = axes.ravel() for pl in range(len(fgs)): path = fgs[pl] sfs, W = wavfile.read(path)
def NAT_stim(exptevents, exptparams, stimfmt='gtgram', separate_files_only=False, channels=18, rasterfs=100, f_min=200, f_max=20000, mono=False, binaural=False, **options): """ :param exptevents: from baphy :param exptparams: from baphy :param stimfmt: string, currently must be 'wav' or 'gtgram' :param separate_files_only: boolean [=False] if True, just return each individual sound file rather than combinations (eg, as specified for binaural stim) :param channels: int number of gtgram channels :param rasterfs: int gtgram sampling rate :param f_min: float gtgram min frequency :param f_max: float gtgram max frequency :param mono: boolean [False] if True, collapse wavs to single channel (dumb control for binaural) :param binaural: if True, apply model to simulate sound at each ear. Currently, a very dumb HRTF :param options: dict extra stuff to pass through :return: stim, tags, stimparam """ ReferenceClass = exptparams['TrialObject'][1]['ReferenceClass'] ReferenceHandle = exptparams['TrialObject'][1]['ReferenceHandle'][1] OveralldB = exptparams['TrialObject'][1]['OveralldB'] if exptparams['TrialObject'][1]['ReferenceClass'] == 'BigNat': sound_root = Path(exptparams['TrialObject'][1]['ReferenceHandle'][1] ['SoundPath'].replace("H:/", "/auto/data/")) #stim_epochs = exptevents.loc[exptevents.name.str.startswith("Stim"),'name'].tolist() #print(exptevents.loc[exptevents.name.str.startswith("Stim"),'name'].tolist()[:10]) #wav1=[e.split(' , ')[1].split("+")[0].split(":")[0].replace("STIM_","") for e in stim_epochs] #wav2=[e.split(' , ')[1].split("+")[0].split(":")[0].replace("STIM_","") for e in stim_epochs] stim_epochs = exptparams['TrialObject'][1]['ReferenceHandle'][1][ 'Names'] #print(exptparams['TrialObject'][1]['ReferenceHandle'][1]['Names'][:10]) wav1 = [e.split("+")[0].split(":")[0] for e in stim_epochs] wav2 = [e.split("+")[1].split(":")[0] for e in stim_epochs] chan1 = [int(e.split("+")[0].split(":")[1]) - 1 for e in stim_epochs] chan2 = [int(e.split("+")[1].split(":")[1]) - 1 for e in stim_epochs] #log.info(wav1[0],chan1[0],wav2[0],chan2[0]) file_unique = wav1.copy() file_unique.extend(wav2) file_unique = list(set(file_unique)) if 'NULL' in file_unique: file_unique.remove('NULL') elif ReferenceClass == 'NaturalSounds': subset = ReferenceHandle['Subsets'] if subset == 1: sound_root = Path( f'/auto/users/svd/code/baphy/Config/lbhb/SoundObjects/@NaturalSounds/sounds' ) else: sound_root = Path( f'/auto/users/svd/code/baphy/Config/lbhb/SoundObjects/@NaturalSounds/sounds_set{subset}' ) stim_epochs = ReferenceHandle['Names'] file_unique = [f.replace('.wav', '') for f in stim_epochs] wav1 = file_unique.copy() chan1 = [0] * len(wav1) wav2 = ["NULL"] * len(wav1) chan2 = [0] * len(wav1) elif ReferenceClass == 'OverlappingPairs': bg_folder = ReferenceHandle['BG_Folder'] fg_folder = ReferenceHandle['FG_Folder'] bg_root = Path( f'/auto/users/hamersky/baphy/Config/lbhb/SoundObjects/@OverlappingPairs/{bg_folder}' ) fg_root = Path( f'/auto/users/hamersky/baphy/Config/lbhb/SoundObjects/@OverlappingPairs/{fg_folder}' ) stim_epochs = ReferenceHandle['Names'] #print(exptparams['TrialObject'][1]['ReferenceHandle'][1]['Names'][:10]) wav1 = [e.split("_")[0].split("-")[0] for e in stim_epochs] wav2 = [e.split("_")[1].split("-")[0] for e in stim_epochs] chan1 = [ int(e.split("_")[0].split("-")[3]) - 1 if e.split("_")[0] != 'null' else 0 for e in stim_epochs ] chan2 = [ int(e.split("_")[1].split("-")[3]) - 1 if e.split("_")[1] != 'null' else 0 for e in stim_epochs ] #log.info(wav1[0],chan1[0],wav2[0],chan2[0]) #wav1 = [wav for wav in wav1 if wav != 'null'] #wav2 = [wav for wav in wav2 if wav != 'null'] file_unique = wav1.copy() file_unique.extend(wav2) file_unique = list(set(file_unique)) file_unique = [f for f in file_unique if f != 'null'] log.info( 'NOTE: Stripping spaces from epoch names in OverlappingPairs files' ) stim_epochs = [s.replace(" ", "") for s in stim_epochs] else: raise ValueError( f"ReferenceClass {ReferenceClass} gtgram not supported.") max_chans = np.max(np.concatenate([np.array(chan1), np.array(chan2)])) + 1 max_chans_was = max_chans if mono: log.info("Forcing mono stimulus, averaging across space") chan1 = [0] * len(wav1) chan2 = [0] * len(wav2) max_chans = 1 PreStimSilence = ReferenceHandle['PreStimSilence'] Duration = ReferenceHandle['Duration'] PostStimSilence = ReferenceHandle['PostStimSilence'] log.info(f"Pre/Dur/Pos: {PreStimSilence}/{Duration}/{PostStimSilence}") wav_unique = {} fs0 = None for filename in file_unique: if ReferenceClass == "OverlappingPairs": try: fs, w = wavfile.read(Path(bg_root) / (filename + '.wav')) except: fs, w = wavfile.read(Path(fg_root) / (filename + '.wav')) else: fs, w = wavfile.read(sound_root / (filename + '.wav')) if fs0 is None: fs0 = fs elif fs != fs0: raise ValueError( "fs mismatch between wav files. Need to implement resampling!") #print(f"{filename} fs={fs} len={w.shape}") duration_samples = int(np.floor(Duration * fs)) # 10ms ramp at onset: w = w[:duration_samples].astype(float) ramp = np.hanning(.01 * fs * 2) ramp = ramp[:int(np.floor(len(ramp) / 2))] w[:len(ramp)] *= ramp w[-len(ramp):] = w[-len(ramp):] * np.flipud(ramp) # scale peak-to-peak amplitude to OveralldB w = w / np.max(np.abs(w)) * 5 sf = 10**((80 - OveralldB) / 20) w /= sf wav_unique[filename] = w[:, np.newaxis] if separate_files_only: # combine into pairs that were actually presented wav_all = wav_unique else: wav_all = {} fs_all = {} for (f1, c1, f2, c2, n) in zip(wav1, chan1, wav2, chan2, stim_epochs): #print(f1,f2) if f1.upper() != "NULL": w1 = wav_unique[f1] if f2.upper() != "NULL": w2 = wav_unique[f2] else: w2 = np.zeros(w1.shape) else: w2 = wav_unique[f2] w1 = np.zeros(w2.shape) w = np.zeros((w1.shape[0], max_chans)) if (binaural is None) | (binaural == False): #log.info(f'binaural model: None') w[:, [c1]] = w1 w[:, [c2]] += w2 else: #log.info(f'binaural model: {binaural}') #import pdb; pdb.set_trace() db_atten = 10 factor = 10**(-db_atten / 20) w[:, [c1]] = w1 * 1 / (1 + factor) + w2 * factor / (1 + factor) w[:, [c2]] += w2 * 1 / (1 + factor) + w1 * factor / (1 + factor) wav_all[n] = w if stimfmt == 'wav': for f, w in wav_all.items(): wav_all[f] = np.concatenate([ np.zeros((int(np.floor(fs * PreStimSilence)), max_chans)), w, np.zeros((int(np.floor(fs * PostStimSilence)), max_chans)) ], axis=0) return wav_all if stimfmt == 'gtgram': window_time = 1 / rasterfs hop_time = 1 / rasterfs duration_bins = int(np.floor(rasterfs * Duration)) sg_pre = np.zeros((channels, int(np.floor(rasterfs * PreStimSilence)))) sg_null = np.zeros((channels, duration_bins)) sg_post = np.zeros( (channels, int(np.floor(rasterfs * PostStimSilence)))) sg_unique = {} stimparam = {'f_min': f_min, 'f_max': f_max, 'rasterfs': rasterfs} padbins = int(np.ceil((window_time - hop_time) / 2 * fs)) for (f, w) in wav_all.items(): if len(sg_unique) % 100 == 99: log.info(f"i={len(sg_unique)+1} {f} {w.std(axis=0)}") sg = [ gtgram(np.pad(w[:, i], [padbins, padbins]), fs, window_time, hop_time, channels, f_min, f_max) if w[:, i].var() > 0 else sg_null for i in range(w.shape[1]) ] sg = [ np.concatenate( [sg_pre, np.abs(s[:, :duration_bins])**0.5, sg_post], axis=1) for s in sg ] if mono & (max_chans_was > 1): sgshuff = np.random.permutation(sg[0].flatten()) sgshuff = np.reshape(sgshuff, sg[0].shape) sg.append(sgshuff) sg_unique[f] = np.concatenate(sg, axis=0) return sg_unique, list(sg_unique.keys()), stimparam
def psth_responses(parm, pair_idx, cell, sigma=2, save=False, rasterfs=100): expt = BAPHYExperiment(parm) rec = expt.get_recording(rasterfs=rasterfs, resp=True, stim=False) resp = rec['resp'].rasterize() site, unit = expt.siteid[:-1], resp.chans[cell] if len(resp.chans) <= cell: raise ValueError(f"Cell {cell} is out of range for site with {len(resp.chans) - 1} units") expt_params = expt.get_baphy_exptparams() # Using Charlie's manager ref_handle = expt_params[0]['TrialObject'][1]['ReferenceHandle'][1] soundies = list(ref_handle['SoundPairs'].values()) pairs = [tuple([j for j in (soundies[s]['bg_sound_name'].split('.')[0], soundies[s]['fg_sound_name'].split('.')[0])]) for s in range(len(soundies))] if len(pairs) <= pair_idx: raise ValueError(f"Pair_idx {pair_idx} is out of range for unit with {len(pairs) - 1} sound pairs") BG, FG = pairs[pair_idx] colors = ['deepskyblue', 'yellowgreen', 'grey', 'silver'] bg_path = f'/auto/users/hamersky/baphy/Config/lbhb/SoundObjects/@OverlappingPairs/Background2/{BG}.wav' fg_path = f'/auto/users/hamersky/baphy/Config/lbhb/SoundObjects/@OverlappingPairs/Foreground3/{FG}.wav' #turn pairs into format for epochs, not file getting for c, t in enumerate(pairs): pairs[c] = tuple([ss.replace(' ', '') for ss in t]) BG, FG = pairs[pair_idx] epochs = [f'STIM_{BG}-0-1_null', f'STIM_null_{FG}-0-1', f'STIM_{BG}-0-1_{FG}-0-1', f'STIM_{BG}-0.5-1_{FG}-0-1'] prestim = ref_handle['PreStimSilence'] f = plt.figure(figsize=(15,9)) psth = plt.subplot2grid((4, 5), (0, 0), rowspan=2, colspan=5) specBG = plt.subplot2grid((4, 5), (2, 0), rowspan=1, colspan=5) specFG = plt.subplot2grid((4, 5), (3, 0), rowspan=1, colspan=5) ax = [psth, specBG, specFG] r = resp.extract_epochs(epochs) time = (np.arange(0, r[epochs[0]].shape[-1]) / rasterfs ) - prestim for e, c in zip(epochs, colors): ax[0].plot(time, sf.gaussian_filter1d(np.nanmean(r[e][:,cell,:], axis=0), sigma=sigma) * rasterfs, color=c, label=e) ax[0].legend() ax[0].set_title(f"{resp.chans[cell]} - Pair {pair_idx} - BG: {BG} - FG: {FG} - sigma={sigma}", weight='bold') # ax[0].set_xlim([0-(prestim/2), time[-1]]) ymin, ymax = ax[0].get_ylim() ax[0].vlines([0,1.0], ymin, ymax, color='black', lw=0.75, ls='--') ax[0].vlines(0.5, ymin, ymax, color='black', lw=0.75, ls=':') xf = 100 low, high = ax[0].get_xlim() low, high = low * xf, high * xf sfs, W = wavfile.read(bg_path) spec = gtgram(W, sfs, 0.02, 0.01, 48, 100, 24000) ax[1].imshow(spec, aspect='auto', origin='lower', extent=[0, spec.shape[1], 0, spec.shape[0]]) ax[1].set_xlim(low, high) ax[1].set_xticks([0, 20, 40, 60, 80]), ax[1].set_yticks([]) ax[1].set_xticklabels([0, 0.2, 0.4, 0.6, 0.8]), ax[1].set_yticklabels([]) ax[1].spines['top'].set_visible(False), ax[1].spines['bottom'].set_visible(False) ax[1].spines['left'].set_visible(False), ax[1].spines['right'].set_visible(False) ymin2, ymax2 = ax[1].get_ylim() ax[1].vlines((spec.shape[-1]+1)/2, ymin2, ymax2, color='white', lw=0.75, ls=':') sfs, W = wavfile.read(fg_path) spec = gtgram(W, sfs, 0.02, 0.01, 48, 100, 24000) ax[2].imshow(spec, aspect='auto', origin='lower', extent=[0, spec.shape[1], 0, spec.shape[0]]) ax[2].set_xlim(low, high) ax[2].set_xticks([0, 20, 40, 60, 80]), ax[2].set_yticks([]) ax[2].set_xticklabels([0, 0.2, 0.4, 0.6, 0.8]), ax[2].set_yticklabels([]) ax[2].spines['top'].set_visible(False), ax[2].spines['bottom'].set_visible(False) ax[2].spines['left'].set_visible(False), ax[2].spines['right'].set_visible(False) ymin3, ymax3 = ax[2].get_ylim() ax[2].vlines((spec.shape[-1]+1)/2, ymin3, ymax3, color='white', lw=0.75, ls=':') ax[2].set_xlabel('Seconds', weight='bold') ax[1].set_ylabel(f"Background:\n{BG}", weight='bold', labelpad=-80, rotation=0) ax[2].set_ylabel(f"Foreground:\n{FG}", weight='bold', labelpad=-80, rotation=0) if save: path = f"/home/hamersky/Tabor PSTHs/{site}/" # if os.path.isfile(path): Path(path).mkdir(parents=True, exist_ok=True) plt.savefig(path + f"{unit} - Pair {pair_idx} - {BG} - {FG} - sigma{sigma}.png") plt.close() # parm = '/auto/data/daq/Tabor/TBR011/TBR011a17_p_OLP.m' # # parm = '/auto/data/daq/Tabor/TBR007/TBR007a10_p_OLP.m' # expt = BAPHYExperiment(parm) # rec = expt.get_recording(rasterfs=rasterfs, resp=True, stim=False) # resp = rec['resp'].rasterize() # # expt_params = expt.get_baphy_exptparams() # Using Charlie's manager # ref_handle = expt_params[0]['TrialObject'][1]['ReferenceHandle'][1] # soundies = list(ref_handle['SoundPairs'].values()) # pairs = [tuple([j for j in (soundies[s]['bg_sound_name'].split('.')[0], # soundies[s]['fg_sound_name'].split('.')[0])]) # for s in range(len(soundies))] # #TBR011a-58-1 = -3 # cell = -3 #TBR011a-58-1 # cell = 2 # # cell = 3 #large effect # # epochs = ['STIM_17Tuning-0-1_13Tsik-0-1', 'STIM_17Tuning-0-1_null', 'STIM_null_13Tsik-0-1', # 'STIM_17Tuning-0.5-1_13Tsik-0-1', 'STIM_17Tuning-0-1_13Tsik-0.5-1'] # epochs = ['STIM_17Tuning-0-1_13Tsik-0-1', 'STIM_null_13Tsik-0-1', # 'STIM_17Tuning-0.5-1_13Tsik-0-1'] # epochs = ['STIM_17Tuning-0-1_13Tsik-0-1', 'STIM_17Tuning-0-1_null', # 'STIM_17Tuning-0-1_13Tsik-0.5-1'] # # epochs = ['STIM_17Tuning-0-1_13Tsik-0-1', 'STIM_null_13Tsik-0-1', # 'STIM_17Tuning-0.5-1_13Tsik-0-1', 'STIM_17Tuning-0-1_null'] # colors = ['black', 'yellowgreen', 'lightgrey', 'blue'] # # #final colors for better plot # epochs = ['STIM_17Tuning-0-1_null', 'STIM_null_13Tsik-0-1', 'STIM_17Tuning-0-1_13Tsik-0-1', # 'STIM_17Tuning-0.5-1_13Tsik-0-1'] # colors = ['deepskyblue', 'yellowgreen', 'grey', 'rosybrown'] # # # epochs = [f'STIM_17Tuning-0-1_null', 'STIM_null_13Tsik-0-1', 'STIM_17Tuning-0-1_13Tsik-0-1', # 'STIM_17Tuning-0.5-1_13Tsik-0-1'] # colors = ['deepskyblue', 'yellowgreen', 'grey', 'rosybrown'] # # bg_path = f'/auto/users/hamersky/baphy/Config/lbhb/SoundObjects/@OverlappingPairs/Background1/{AA}.wav' # fg_path = f'/auto/users/hamersky/baphy/Config/lbhb/SoundObjects/@OverlappingPairs/Foreground2/{BB}.wav' # # smooval = 6 # # f = plt.figure(figsize=(15, 9)) # psth = plt.subplot2grid((4, 6), (0, 0), rowspan=2, colspan=6) # specBG = plt.subplot2grid((4, 6), (2, 0), rowspan=1, colspan=6) # specFG = plt.subplot2grid((4, 6), (3, 0), rowspan=1, colspan=6) # # ax = [psth, specBG, specFG] # # time = np.arange(0, r[epochs[0]].shape[-1] / rasterfs) # # for e, c in zip(epochs, colors): # mean = r[e][:,cell,:].mean(axis=0) # mean = smooth(mean, smooval) # ax[0].plot(mean, label=e, color=c) # ax[0].legend() # ax[0].set_title(f"{resp.chans[cell]}") # # # # r = resp.extract_epochs(epochs) # fig, ax = plt.subplots() # for e, c in zip(epochs,colors): # mean = r[e][:,cell,:].mean(axis=0) # mean = smooth(mean, 7) # ax.plot(mean, label=e, color=c) # ax.legend() # ax.set_title(f"{resp.chans[cell]}") # ymin,ymax = ax.get_ylim() # ax.vlines([50, 100, 150], ymin, ymax, color = 'black', ls=':')
f'{FG_folder}/{ff}*.wav'))[0] for ff in idxstr ] fgname = [ ff.split('/')[-1].split('.')[0].replace(' ', '') for ff in fg_paths ] ep_fg = [f"STIM_null_{ff}" for ff in fgname] prebins = int(ref_handle['PreStimSilence'] * options['rasterfs']) postbins = int(ref_handle['PostStimSilence'] * options['rasterfs']) durbins = int(ref_handle['Duration'] * options['rasterfs']) trialbins = durbins + postbins env_cuts = {} for nm, pth in zip(fgname, fg_paths): sfs, W = wavfile.read(pth) spec = gtgram(W, sfs, 0.02, 0.01, bins, lfreq, hfreq) env = np.nanmean(spec, axis=0) cutoff = np.max(env) * threshold # aboves = np.squeeze(np.argwhere(env >= cutoff)) # belows = np.squeeze(np.argwhere(env < cutoff)) highs, lows, whole_thing = env >= cutoff, env < cutoff, env > 0 prestimFalse = np.full((prebins, ), False) poststimTrue = np.full((trialbins - len(env), ), True) poststimFalse = np.full((trialbins - len(env), ), False) full = np.concatenate((prestimFalse, np.full((trialbins, ), True))) aboves = np.concatenate((prestimFalse, highs, poststimFalse)) belows = np.concatenate((prestimFalse, lows, poststimFalse))