RHOBINS = np.arange(RHOMIN, RHOMAX+0.1, 0.1) # left edges + rightmost edge # build corresponding lists of recs and stranges, even entries are desynched, odd are synched: recs, stranges = [], [] # recs has repetitions, not unique for rec in urecs: # iterate over sorted unique recs tranges = REC2STATETRANGES[rec.absname] for trange in tranges: recs.append(rec) stranges.append(trange) nrecsec = len(recs) assert nrecsec == len(stranges) assert nrecsec % 2 == 0 # should always be an even number of recording sections states = ['desynch', 'synch'] * (nrecsec // 2) # alternating states # get active or all neuron ids for each section of each recording: recsecnids = core.get_ssnids(recs, stranges, kind=NIDSKIND)[1] # calculate responsive PSTHs: rts = {} # index into by [rec.absname][statei] rpsths = {} # index into by [rec.absname][statei][nid] for rec, nids, strange, state in zip(recs, recsecnids, stranges, states): print(rec.absname, state) statei = {'desynch': 0, 'synch': 1}[state] if rec.absname not in rts: rts[rec.absname] = [None, None] # init, index into using statei rpsths[rec.absname] = [{}, {}] # init, index into using statei t, psths, spikets = rec.psth(nids=nids, natexps=False, blank=BLANK, strange=strange, plot=False, binw=BINW, tres=TRES, gauss=GAUSS, norm='ntrials') rts[rec.absname][statei] = t for nid, psth, ts in zip(nids, psths, spikets): # run PSTH peak detection:
ptc22tr1r08s = [ptc22.tr1.r08, ptc22.tr1.r08] strangesr08s = [(0, 1500e6), # r08 desynched, us (1550e6, np.inf)] # r08 synched, us, end is ~ 2300s ptc22tr1r10s = [ptc22.tr1.r10, ptc22.tr1.r10] strangesr10s = [(0, 1400e6), # r10 synched, us (1480e6, np.inf)] # r10 desynched, us, end is ~ 2300s ptc22tr1recs = [ptc22.tr1.r05, ptc22.tr1.r08, ptc22.tr1.r10, ptc22.tr1.r19] ptc22tr2recs = [ptc22.tr2.r28, ptc22.tr2.r33] # ptc15.tr7c: SEPMAX = 1675 # get superset of active nids for all natexps of both recs in ptc15tr7crecs: stranges = etrangesr74 + etrangesr95b # 8 stranges in total recs = [ptc15.tr7c.r74]*4 + [ptc15.tr7c.r95b]*4 # 8 recs corresponding to 8 stranges ssnids, recsecnids = get_ssnids(recs, stranges) ssseps = get_seps(ssnids, ptc15.tr7c.alln) # get separate supersets of active nids for all 4 natexps in each recording: ptc15tr7crecsecnids = [np.unique(np.hstack(recsecnids[:4])), np.unique(np.hstack(recsecnids[4:]))] # do psthcorr plots and collect ssrho matrices: ssrhos = [] for rec, nids in zip(ptc15tr7crecs, ptc15tr7crecsecnids): ssrho = psthcorr(rec, nids=nids, ssnids=ssnids, ssseps=ssseps, natexps=True) # in sec ssrhos.append(ssrho) # plot differences in superset rho matrices for the two recordings: psthcorrdiff(ssrhos, ssseps, 'r74-r95b') ## rho for ns1 figure: #In [124]: np.where(ssnids == 328) #Out[124]: (array([31]),)
def psthcorrtype(trackrecs, pool=False, alpha=ALPHA1, vmin=VMIN, vmax=VMAX, separatetypeplots=True): """Plot mean PSTH correlation (rho) 2D histograms, indexed by spike and RF type. Plot one for each set of recordings in trackrecs (ostensibly, one per track). If pool, plot only one rho celltype histogram pooled across all trackrecs. If pool, return rhotype matrix filled only with those distributions whose mean is significantly different from 0.""" ntracks = len(trackrecs) tracknames = [ trackrec[0].tr.absname for trackrec in trackrecs ] rhotype = listarr(np.empty((8, 8))) # init rho cell type 2D array of lists npairs = 0 # init npairs for tracki, recs in enumerate(trackrecs): track = recs[0].tr natexps = False trackname = recs[0].tr.absname if trackname == 'ptc15.tr7c': natexps = True ssnids, recsecnids = get_ssnids(recs) ssrhos = [] for rec in recs: ssrho = psthcorr(rec, nids=None, ssnids=ssnids, natexps=natexps, plot=False) ssrhos.append(ssrho) ssrhos = np.asarray(ssrhos) # convert to 3D array if pool == False: listarr(rhotype) # reset between tracks npairs = 0 # reset between tracks nn = len(ssnids) nanis = np.isnan(ssrhos) # indices of nan values ssrhos[nanis] = 0 # replace nans with 0s maxabsssrhos = core.maxabs(ssrhos, axis=0) # keep only the max rho of each cell pair alln = track.alln for i in range(nn): ni = alln[ssnids[i]] # neuron i si = celltype2int[ni.spiketype] ri = celltype2int[ni.rftype] for j in range(i+1, nn): # use only upper triangle, don't double count cell pairs nj = alln[ssnids[j]] # neuron j sj = celltype2int[nj.spiketype] rj = celltype2int[nj.rftype] rho = maxabsssrhos[i, j] if rho == 0: # ignore this cell pair's rho (they were never simultaneously active) so it # doesn't mess up the celltype stats continue # fill in the upper triangle of rhotype matrix: rhotype[si, sj].append(rho) rhotype[ri, rj].append(rho) # these cross terms should best be left disabled, because they conflate the # correlations between spiketype and rftype: #rhotype[ri, sj].append(rho) #rhotype[si, rj].append(rho) npairs += 1 rhotypemeans = np.zeros(rhotype.shape); rhotypemeans.fill(nan) rhotypestds = np.zeros(rhotype.shape); rhotypestds.fill(nan) rhotypeps = np.zeros(rhotype.shape); rhotypeps.fill(np.inf) rhotypesigmeans = np.zeros(rhotype.shape); rhotypesigmeans.fill(nan) # calculate rho stats for each combination of cell type: for i in range(8): for j in range(i, 8): # use only upper triangle, don't double count celltype stats if len(rhotype[i, j]) > 1: rhotypemeans[i, j] = np.mean(rhotype[i, j]) rhotypestds[i, j] = np.std(rhotype[i, j]) # 2-sided sample mean ttest relative to 0: t, p = ttest_1samp(rhotype[i, j], 0) rhotypeps[i, j] = p sigis = rhotypeps < alpha # indices of significant deviations of mean from 0 rhotypesigmeans[sigis] = rhotypemeans[sigis] #arrs = [rhotypemeans, rhotypestds, rhotypeps, rhotypesigmeans] #plottypes = ['mean', 'stdev', 'pval', 'sigmean'] arrs = [rhotypesigmeans] plottypes = ['sigmean'] if pool: if tracki < ntracks-1: continue # only plot once all tracks have been iterated over trackname = ', '.join(tracknames) for arr, plottype in zip(arrs, plottypes): # get symmetric arr by copying upper triangle, transposing to get lower triangle, # and adding to arr: symarr = nansum([arr, np.triu(arr, k=1).T], axis=0) thisvmin, thisvmax = nanmin(symarr), nanmax(symarr) vmin = min(vmin, thisvmin) # set to manual vmin at most vmax = max(vmax, thisvmax) # set to manual vmax at least if separatetypeplots: figure(figsize=(8, 3)) # plot spiketypes: subplot(121) imshow(symarr[:4, :4], vmin=vmin, vmax=vmax, origin='upper', cmap='jet') xticks(np.arange(4), spiketypelabels, rotation=90) yticks(np.arange(4), spiketypelabels) colorbar(ticks=(vmin, vmax), format='%.2f') # plot rftypes: subplot(122) imshow(symarr[4:, 4:], vmin=vmin, vmax=vmax, origin='upper', cmap='jet') xticks(np.arange(4), rftypelabels, rotation=90) yticks(np.arange(4), rftypelabels) colorbar(ticks=(vmin, vmax), format='%.2f') plottype += ' separate' else: # plot spike and rf types in the same matrix figure(figsize=(4, 4)) imshow(symarr, vmin=vmin, vmax=vmax, origin='upper', cmap='jet') xticks(np.arange(8), typelabels, rotation=90) yticks(np.arange(8), typelabels) colorbar(ticks=(vmin, vmax), format='%.2f') plottype += ' combined' titlestr = (trackname + ' psthcorrtype ' + plottype + ' alpha=%.4f, npairs=%d' % (alpha, npairs)) gcfm().window.setWindowTitle(titlestr) tight_layout(pad=0.4) if pool: # only return rhotype if pooling across all tracks insigis = np.logical_not(sigis) rhotype[insigis] = listarr(rhotype[insigis]) # set insig entries to empty lists return rhotype # only significant entires aren't empty
# build corresponding lists of recs and stranges, even entries are desynched, odd are synched: recs, stranges = [], [] # recs has repetitions, not unique for rec in urecs: # iterate over sorted unique recs tranges = REC2STATETRANGES[rec.absname] for trange in tranges: # desynched, then synched recs.append(rec) stranges.append(trange) nrecsec = len(recs) assert nrecsec == len(stranges) assert nrecsec % 2 == 0 # should always be an even number of recording sections stateis = [0, 1] * (nrecsec // 2) # allternating desynched and synched state indices fmts = ['b-', 'r-'] * (nrecsec // 2) # alternating plotting formats for desynched and synched # get active or all neuron ids for each section of each recording: recsecnids = get_ssnids(recs, stranges, kind='all')[1] ## TODO: this loop is a mess. It should have 3 nested loops (recording, state, neuron) ## instead of the current 2 (recording*state, neuron). That's why it has the messy ## "% 2 == 0" stuff. There's no need to use the get_ssnids() function if kind='all', ## which it always is. # calculate PSTHs for all sections of all recordings, collect data from each PSTH with at # least 1 detected peak: psthss, spiketss = [], [] rpsths = [[], []] # responsive PSTHs, indexed by state psthparamsrecsec = [] # params returned for each PSTH, for each recording section widthsrecsec = [] # peak widths, for each recording section tsrecsec = [] # peak times, for each recording section heightsrecsec = [] # peak heights, for each recording section peaknspikesrecsec = [] # spike counts of each peak, normalized by ntrials, for each rec section
RHOBINS = np.arange(RHOMIN, RHOMAX + 0.1, 0.1) # left edges + rightmost edge # build corresponding lists of recs and stranges, even entries are desynched, odd are synched: recs, stranges = [], [] # recs has repetitions, not unique for rec in urecs: # iterate over sorted unique recs tranges = REC2STATETRANGES[rec.absname] for trange in tranges: recs.append(rec) stranges.append(trange) nrecsec = len(recs) assert nrecsec == len(stranges) assert nrecsec % 2 == 0 # should always be an even number of recording sections states = ['desynch', 'synch'] * (nrecsec // 2) # alternating states # get active or all neuron ids for each section of each recording: recsecnids = core.get_ssnids(recs, stranges, kind=NIDSKIND)[1] # calculate responsive PSTHs: rts = {} # index into by [rec.absname][statei] rpsths = {} # index into by [rec.absname][statei][nid] for rec, nids, strange, state in zip(recs, recsecnids, stranges, states): print(rec.absname, state) statei = {'desynch': 0, 'synch': 1}[state] if rec.absname not in rts: rts[rec.absname] = [None, None] # init, index into using statei rpsths[rec.absname] = [{}, {}] # init, index into using statei t, psths, spikets = rec.psth(nids=nids, natexps=False, blank=BLANK, strange=strange, plot=False,
recs, stranges = [], [] # recs has repetitions, not unique for rec in urecs: # iterate over sorted unique recs tranges = REC2STATETRANGES[rec.absname] for trange in tranges: # desynched, then synched recs.append(rec) stranges.append(trange) nrecsec = len(recs) assert nrecsec == len(stranges) assert nrecsec % 2 == 0 # should always be an even number of recording sections stateis = [0, 1] * (nrecsec // 2 ) # allternating desynched and synched state indices fmts = ['b-', 'r-'] * ( nrecsec // 2) # alternating plotting formats for desynched and synched # get active or all neuron ids for each section of each recording: recsecnids = get_ssnids(recs, stranges, kind='all')[1] ## TODO: this loop is a mess. It should have 3 nested loops (recording, state, neuron) ## instead of the current 2 (recording*state, neuron). That's why it has the messy ## "% 2 == 0" stuff. There's no need to use the get_ssnids() function if kind='all', ## which it always is. # calculate PSTHs for all sections of all recordings, collect data from each PSTH with at # least 1 detected peak: psthss, spiketss = [], [] rpsths = [[], []] # responsive PSTHs, indexed by state psthparamsrecsec = [ ] # params returned for each PSTH, for each recording section widthsrecsec = [] # peak widths, for each recording section tsrecsec = [] # peak times, for each recording section heightsrecsec = [] # peak heights, for each recording section
def psthcorrtype(trackrecs, pool=False, alpha=ALPHA1, vmin=VMIN, vmax=VMAX, separatetypeplots=True): """Plot mean PSTH correlation (rho) 2D histograms, indexed by spike and RF type. Plot one for each set of recordings in trackrecs (ostensibly, one per track). If pool, plot only one rho celltype histogram pooled across all trackrecs. If pool, return rhotype matrix filled only with those distributions whose mean is significantly different from 0.""" ntracks = len(trackrecs) tracknames = [trackrec[0].tr.absname for trackrec in trackrecs] rhotype = listarr(np.empty((8, 8))) # init rho cell type 2D array of lists npairs = 0 # init npairs for tracki, recs in enumerate(trackrecs): track = recs[0].tr natexps = False trackname = recs[0].tr.absname if trackname == 'ptc15.tr7c': natexps = True ssnids, recsecnids = get_ssnids(recs) ssrhos = [] for rec in recs: ssrho = psthcorr(rec, nids=None, ssnids=ssnids, natexps=natexps, plot=False) ssrhos.append(ssrho) ssrhos = np.asarray(ssrhos) # convert to 3D array if pool == False: listarr(rhotype) # reset between tracks npairs = 0 # reset between tracks nn = len(ssnids) nanis = np.isnan(ssrhos) # indices of nan values ssrhos[nanis] = 0 # replace nans with 0s maxabsssrhos = core.maxabs( ssrhos, axis=0) # keep only the max rho of each cell pair alln = track.alln for i in range(nn): ni = alln[ssnids[i]] # neuron i si = celltype2int[ni.spiketype] ri = celltype2int[ni.rftype] for j in range( i + 1, nn ): # use only upper triangle, don't double count cell pairs nj = alln[ssnids[j]] # neuron j sj = celltype2int[nj.spiketype] rj = celltype2int[nj.rftype] rho = maxabsssrhos[i, j] if rho == 0: # ignore this cell pair's rho (they were never simultaneously active) so it # doesn't mess up the celltype stats continue # fill in the upper triangle of rhotype matrix: rhotype[si, sj].append(rho) rhotype[ri, rj].append(rho) # these cross terms should best be left disabled, because they conflate the # correlations between spiketype and rftype: #rhotype[ri, sj].append(rho) #rhotype[si, rj].append(rho) npairs += 1 rhotypemeans = np.zeros(rhotype.shape) rhotypemeans.fill(nan) rhotypestds = np.zeros(rhotype.shape) rhotypestds.fill(nan) rhotypeps = np.zeros(rhotype.shape) rhotypeps.fill(np.inf) rhotypesigmeans = np.zeros(rhotype.shape) rhotypesigmeans.fill(nan) # calculate rho stats for each combination of cell type: for i in range(8): for j in range( i, 8 ): # use only upper triangle, don't double count celltype stats if len(rhotype[i, j]) > 1: rhotypemeans[i, j] = np.mean(rhotype[i, j]) rhotypestds[i, j] = np.std(rhotype[i, j]) # 2-sided sample mean ttest relative to 0: t, p = ttest_1samp(rhotype[i, j], 0) rhotypeps[i, j] = p sigis = rhotypeps < alpha # indices of significant deviations of mean from 0 rhotypesigmeans[sigis] = rhotypemeans[sigis] #arrs = [rhotypemeans, rhotypestds, rhotypeps, rhotypesigmeans] #plottypes = ['mean', 'stdev', 'pval', 'sigmean'] arrs = [rhotypesigmeans] plottypes = ['sigmean'] if pool: if tracki < ntracks - 1: continue # only plot once all tracks have been iterated over trackname = ', '.join(tracknames) for arr, plottype in zip(arrs, plottypes): # get symmetric arr by copying upper triangle, transposing to get lower triangle, # and adding to arr: symarr = nansum([arr, np.triu(arr, k=1).T], axis=0) thisvmin, thisvmax = nanmin(symarr), nanmax(symarr) vmin = min(vmin, thisvmin) # set to manual vmin at most vmax = max(vmax, thisvmax) # set to manual vmax at least if separatetypeplots: figure(figsize=(8, 3)) # plot spiketypes: subplot(121) imshow(symarr[:4, :4], vmin=vmin, vmax=vmax, origin='upper', cmap='jet') xticks(np.arange(4), spiketypelabels, rotation=90) yticks(np.arange(4), spiketypelabels) colorbar(ticks=(vmin, vmax), format='%.2f') # plot rftypes: subplot(122) imshow(symarr[4:, 4:], vmin=vmin, vmax=vmax, origin='upper', cmap='jet') xticks(np.arange(4), rftypelabels, rotation=90) yticks(np.arange(4), rftypelabels) colorbar(ticks=(vmin, vmax), format='%.2f') plottype += ' separate' else: # plot spike and rf types in the same matrix figure(figsize=(4, 4)) imshow(symarr, vmin=vmin, vmax=vmax, origin='upper', cmap='jet') xticks(np.arange(8), typelabels, rotation=90) yticks(np.arange(8), typelabels) colorbar(ticks=(vmin, vmax), format='%.2f') plottype += ' combined' titlestr = (trackname + ' psthcorrtype ' + plottype + ' alpha=%.4f, npairs=%d' % (alpha, npairs)) gcfm().window.setWindowTitle(titlestr) tight_layout(pad=0.4) if pool: # only return rhotype if pooling across all tracks insigis = np.logical_not(sigis) rhotype[insigis] = listarr( rhotype[insigis]) # set insig entries to empty lists return rhotype # only significant entires aren't empty
ptc22tr1r10s = [ptc22.tr1.r10, ptc22.tr1.r10] strangesr10s = [ (0, 1400e6), # r10 synched, us (1480e6, np.inf) ] # r10 desynched, us, end is ~ 2300s ptc22tr1recs = [ptc22.tr1.r05, ptc22.tr1.r08, ptc22.tr1.r10, ptc22.tr1.r19] ptc22tr2recs = [ptc22.tr2.r28, ptc22.tr2.r33] # ptc15.tr7c: SEPMAX = 1675 # get superset of active nids for all natexps of both recs in ptc15tr7crecs: stranges = etrangesr74 + etrangesr95b # 8 stranges in total recs = [ptc15.tr7c.r74] * 4 + [ptc15.tr7c.r95b ] * 4 # 8 recs corresponding to 8 stranges ssnids, recsecnids = get_ssnids(recs, stranges) ssseps = get_seps(ssnids, ptc15.tr7c.alln) # get separate supersets of active nids for all 4 natexps in each recording: ptc15tr7crecsecnids = [ np.unique(np.hstack(recsecnids[:4])), np.unique(np.hstack(recsecnids[4:])) ] # do psthcorr plots and collect ssrho matrices: ssrhos = [] for rec, nids in zip(ptc15tr7crecs, ptc15tr7crecsecnids): ssrho = psthcorr(rec, nids=nids, ssnids=ssnids, ssseps=ssseps, natexps=True) # in sec ssrhos.append(ssrho)