fig5.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. """Figure 5 and 5S1 plots, use run -i fig5.py"""
  2. mi = pd.MultiIndex.from_product([mvimseustrs, ST8S, OPTOS], names=['mseu', 'st8', 'opto'])
  3. columns = ['trialis', 'rates', 'burstratios', 'meanrate', 'meanburstratio',
  4. 'spars', 'rel', 'meanpkw', 'snr']
  5. fig5 = pd.DataFrame(index=mi, columns=columns) # excludes kind and opto
  6. ## NOTE: make sure that rows are not overwritten due to temporarily enabling iteration
  7. ## over kind in any of the following loops!
  8. # tweak exactly how much horizontal space to use for raster plots and PSTHs:
  9. PLOTOFFSETS = -0.45, 0.45
  10. # plot movie rasters for each unit by kind, state and opto condition:
  11. # copied and slightly modified from fig1.py:
  12. showbursts = True
  13. trialiis = None #np.arange(120) # plot only these trials, None plots all trials
  14. for mseustr in mvimseu2exmpli: # mvimseustrs
  15. if mseustr != 'PVCre_2018_0003_s03_e03_u51': # plot only this one
  16. continue
  17. for kind in MVIKINDS:
  18. for st8 in ['run', 'sit']:
  19. for opto in OPTOS:
  20. dt = mviresp.loc[mseustr, kind, st8, opto]['dt'] # stimulus duration (s)
  21. #wdt = -PLOTOFFSETS[0] + dt + PLOTOFFSETS[1] # wide raster duration, sec
  22. tmin, tmax = 0 + PLOTOFFSETS[0], dt + PLOTOFFSETS[1]
  23. optotrange = mviresp.loc[mseustr, kind, st8, opto]['optotrange']
  24. raster = mviresp.loc[mseustr, kind, st8, opto]['wraster']
  25. if np.any(pd.isna(raster)): # no raster for this condition
  26. continue
  27. title = '%s movie %s %s %s raster' % (mseustr, kind, st8, opto)
  28. if trialiis is not None:
  29. raster = raster[trialiis]
  30. title += ' %dtrials' % len(trialiis)
  31. burstis = None
  32. if showbursts:
  33. wburstis = mviresp.loc[mseustr, kind, st8, opto]['wburstis']
  34. a = simpletraster(raster=raster, alpha=0.5, s=1, dt=dt, offsets=PLOTOFFSETS,
  35. title=title, inchespersec=1.5*RASTERSCALEX,
  36. inchespertrial=1/25*RASTERSCALEX,
  37. xaxis=True, burstis=wburstis)
  38. if opto:
  39. # plot horizontal line signifying opto ON period, just above axes:
  40. ton, toff = optotrange
  41. a.hlines(-5, ton, toff, colors=optoblue, lw=4, clip_on=False,
  42. in_layout=False)
  43. # plot horizontal line signifying stimulus period, just above axes:
  44. a.hlines(-2, 0, dt, colors='k', lw=4, clip_on=False, in_layout=False)
  45. # plot vertical coloured line just right of axes:
  46. #vlinexpos = dt + PLOTOFFSETS[1] + wdt*0.01
  47. #y0, y1 = a.get_ylim()
  48. #clr = st82clr[st8]
  49. #alpha = opto2alpha[opto]
  50. #a.vlines(vlinexpos, y0, y1, colors=clr, lw=4, alpha=alpha, clip_on=False,
  51. # in_layout=False)
  52. a.set_xlim(tmin, tmax)
  53. # plot movie PSTHs for each unit by kind, overplot state and opto combinations:
  54. # copied and slightly modified from fig1.py:
  55. for mseustr in mvimseu2exmpli: #mvimseustrs
  56. if mseustr != 'PVCre_2018_0003_s03_e03_u51': # plot only this one
  57. continue
  58. for kind in MVIKINDS:
  59. wt = mviresp.loc[mseustr, kind]['wt'] # DataFrame
  60. wpsth = mviresp.loc[mseustr, kind]['wpsth'] # DataFrame
  61. wbpsth = mviresp.loc[mseustr, kind]['wbpsth'] # DataFrame
  62. #t = mviresp.loc[mseustr, kind]['t'] # DataFrame
  63. psth = mviresp.loc[mseustr, kind]['psth'] # DataFrame
  64. if np.isnan(np.hstack(wpsth)).any(): # no PSTH for at least one condition for this mseu
  65. continue
  66. optorho, optorho_p = scipy.stats.pearsonr(psth['none', False], psth['none', True])
  67. runsitrho, runsitrho_p = scipy.stats.pearsonr(psth['run', False], psth['sit', False])
  68. skewoff = scipy.stats.skew(psth['none', False])
  69. skewon = scipy.stats.skew(psth['none', True])
  70. skewrun = scipy.stats.skew(psth['run', False])
  71. skewsit = scipy.stats.skew(psth['sit', False])
  72. _, optoKS_p = ks_2samp(psth['none', False], psth['none', True])
  73. _, runsitKS_p = ks_2samp(psth['run', False], psth['sit', False])
  74. print('%s example PSTH:\n'
  75. 'optorho=%g optorho_p=%g skewoff=%g skewon=%g optoKS_p=%g\n'
  76. 'runsitrho=%g runsitrho_p=%g skewrun=%g skewsit=%g runsitKS_p=%g'
  77. % (mseustr,
  78. optorho, optorho_p, skewoff, skewon, optoKS_p,
  79. runsitrho, runsitrho_p, skewrun, skewsit, runsitKS_p))
  80. for st8combo, optocombo in zip(ST8COMBOS, OPTOCOMBOS):
  81. st8combostr = ' '.join(st8combo)
  82. optocombostr = ' '.join([str(opto) for opto in optocombo])
  83. dt = mviresp.loc[mseustr, kind, 'none']['dt'].mean() # mean stimulus duration (s)
  84. wdt = -PLOTOFFSETS[0] + dt + PLOTOFFSETS[1] # wide raster duration, sec
  85. tmin, tmax = 0 + PLOTOFFSETS[0], dt + PLOTOFFSETS[1]
  86. #figsize = 0.872 + wdt*1.5*RASTERSCALEX, PSTHHEIGHT
  87. figsize = 0.95 + wdt*1.5*RASTERSCALEX, PSTHHEIGHT
  88. f, a = plt.subplots(figsize=figsize)
  89. title = '%s %s %s %s PSTH' % (mseustr, kind, st8combostr, optocombostr)
  90. wintitle(title)
  91. # subsample as in PSTH scatter plots, and plot all 4 st8/opto combinations:
  92. for st8 in st8combo:
  93. color = st82clr[st8]
  94. for opto in optocombo:
  95. if st8combo == ['run', 'sit'] and optocombo == [True]:
  96. optoalpha = 1
  97. else:
  98. optoalpha = opto2alpha[opto]
  99. if optocombo == [False]: # desaturate bursts by st8, not opto
  100. burstalpha = st82alpha[st8]
  101. else:
  102. burstalpha = opto2alpha[opto]
  103. c = desat(color, optoalpha) # do manual alpha mixing
  104. bc = desat(burstclr, burstalpha) # do manual alpha mixing
  105. fb = opto2fb[opto].title()
  106. if st8 == 'none':
  107. label = fb
  108. else:
  109. label = ', '.join([fb, st8.title()])
  110. a.plot(wt[st8, opto][::ssx], wpsth[st8, opto][::ssx],
  111. '-', color=c, label=label)
  112. #a.plot(t[st8, opto][::ssx], wbpsth[st8, opto][::ssx],
  113. # '-', color=bc, label=label+', Burst')
  114. l = a.legend(frameon=False)
  115. l.set_draggable(True)
  116. a.set_xlabel('Time (s)')
  117. a.set_ylabel('Firing rate (spk/s)')
  118. a.set_xlim(tmin, tmax)
  119. a.set_ylim(-2.75, 57)
  120. # plot horizontal line signifying stimulus period, just below data:
  121. ymin, ymax = a.get_ylim()
  122. a.hlines(-ymax*0.025, 0, dt, colors='k', lw=4, clip_on=False, in_layout=False)
  123. a.set_ylim(ymin, ymax) # restore y limits from before plotting the hline
  124. # scatter plot movie run vs sit meanrate, during feedback condition:
  125. figsize = DEFAULTFIGURESIZE[0]*1.05, DEFAULTFIGURESIZE[1] # tweak to make space for log units
  126. logmin, logmax = -2, 2
  127. logticks = np.array([-2, 0, 2])
  128. for kind in ['nat']:#MVIKINDS:
  129. for opto in OPTOS:
  130. f, a = plt.subplots(figsize=figsize)
  131. wintitle('runsit meanrate movie %s %s' % (kind, opto))
  132. rruns, rsits, sgnfs, exmplis, exmplmseustrs, normlis = [], [], [], [], [], []
  133. keptmseui = 0 # manually init and increment instead of using enumerate()
  134. for mseustr in mvimseustrs:
  135. meanrate = mviresp.loc[mseustr, kind, ST8S, opto]['meanrate']
  136. snr = mviresp.loc[mseustr, kind, ST8S, opto]['snr']
  137. if meanrate.isna().any(): # missing one or both meanrates
  138. continue
  139. if (snr < SNRTHRESH).all(): # neither condition has decent SNR
  140. continue
  141. rrun, rsit = meanrate.values
  142. rruns.append(rrun)
  143. rsits.append(rsit)
  144. trialis = mviresp.loc[mseustr, kind, ST8S, opto]['trialis']
  145. rates = mviresp.loc[mseustr, kind, ST8S, opto]['rates']
  146. runrates = rates.xs('run', level='st8').iloc[0]
  147. sitrates = rates.xs('sit', level='st8').iloc[0]
  148. _, pval = ttest_ind(runrates, sitrates, equal_var=False)
  149. sgnfs.append(pval < SCATTERPTHRESH) # bool
  150. fig5.loc[(mseustr, ST8S, opto), 'meanrate'] = rrun, rsit # save
  151. fig5.loc[(mseustr, ST8S, opto), 'trialis'] = trialis.values # for trial-wise joins
  152. fig5.loc[(mseustr, ST8S, opto), 'rates'] = rates.values # save trial-wise values
  153. if mvimseu2exmpli.get(mseustr) == fig5exmpli:
  154. exmplis.append(keptmseui)
  155. exmplmseustrs.append(mseustr)
  156. else:
  157. normlis.append(keptmseui)
  158. keptmseui += 1 # manually increment
  159. rruns = np.asarray(rruns)
  160. rsits = np.asarray(rsits)
  161. sgnfs = np.asarray(sgnfs)
  162. # replace off-scale low values with log0min, so the points remain visible:
  163. #pltrruns, pltrsits = rruns.copy(), rsits.copy()
  164. #pltrruns[pltrruns <= 10**logmin] = 10**log0min
  165. #pltrsits[pltrsits <= 10**logmin] = 10**log0min
  166. # plot y=x line:
  167. xyline = [10**logmin, 10**logmax], [10**logmin, 10**logmax]
  168. a.plot(xyline[0], xyline[1], '--', color='gray', zorder=-1)
  169. insgnfis, = np.where(sgnfs == False)
  170. sgnfis, = np.where(sgnfs == True)
  171. normlinsgnfis = np.intersect1d(normlis, insgnfis)
  172. normlsgnfis = np.intersect1d(normlis, sgnfis)
  173. # plot normal (non-example) insignificant points:
  174. c = desat(black, SGNF2ALPHA[False]) # do manual alpha mixing
  175. a.scatter(rsits[normlinsgnfis], rruns[normlinsgnfis], clip_on=False,
  176. marker='.', c='None', edgecolor=c, s=DEFSZ)
  177. # plot normal (non-example) significant points:
  178. c = desat(black, SGNF2ALPHA[True]) # do manual alpha mixing
  179. a.scatter(rsits[normlsgnfis], rruns[normlsgnfis], clip_on=False,
  180. marker='.', c='None', edgecolor=c, s=DEFSZ)
  181. # plot example points, one at a time:
  182. for exmpli, mseustr in zip(exmplis, exmplmseustrs):
  183. marker = exmpli2mrk[mvimseu2exmpli[mseustr]]
  184. c = exmpli2clr[mvimseu2exmpli[mseustr]]
  185. sz = exmpli2sz[mvimseu2exmpli[mseustr]]
  186. lw = exmpli2lw[mvimseu2exmpli[mseustr]]
  187. a.scatter(rsits[exmpli], rruns[exmpli], clip_on=False,
  188. marker=marker, c=c, s=sz, lw=lw)
  189. a.set_xlabel('Sit FR (spk/s)')
  190. a.set_ylabel('Run FR (spk/s)')
  191. a.set_xscale('log')
  192. a.set_yscale('log')
  193. a.set_xlim(10**logmin, 10**logmax)
  194. a.set_ylim(10**logmin, 10**logmax)
  195. a.set_xticks(10.0**logticks)
  196. a.set_yticks(a.get_xticks()) # make log scale y ticks the same as x ticks
  197. a.minorticks_off()
  198. axes_disable_scientific(a)
  199. a.set_aspect('equal')
  200. a.spines['left'].set_position(('outward', 4))
  201. a.spines['bottom'].set_position(('outward', 4))
  202. #t, p = ttest_rel(rsits, rruns) # paired t-test
  203. #a.add_artist(AnchoredText('p$=$%.2g' % p, loc='lower right', frameon=False))
  204. # scatter plot movie run vs sit burst ratio, during feedback condition:
  205. figsize = DEFAULTFIGURESIZE[0]*1.06, DEFAULTFIGURESIZE[1] # tweak to make space for log units
  206. logmin, logmax = -3.55, 0
  207. logticks = np.array([-3, -2, -1, 0])
  208. for kind in ['nat']:#MVIKINDS:
  209. for opto in OPTOS:
  210. f, a = plt.subplots(figsize=figsize)
  211. wintitle('runsit burst ratio movie %s %s' % (kind, opto))
  212. brruns, brsits, sgnfs, exmplis, exmplmseustrs, normlis = [], [], [], [], [], []
  213. keptmseui = 0 # manually init and increment instead of using enumerate()
  214. for mseustr in mvimseustrs:
  215. br = mviresp.loc[mseustr, kind, ST8S, opto]['meanburstratio']
  216. snr = mviresp.loc[mseustr, kind, ST8S, opto]['snr']
  217. if br.isna().any(): # missing one or both values
  218. continue
  219. if (snr < SNRTHRESH).all(): # neither condition has decent SNR
  220. continue
  221. brrun, brsit = br.values
  222. brruns.append(brrun)
  223. brsits.append(brsit)
  224. burstratios = mviresp.loc[mseustr, kind, ST8S, opto]['burstratios']
  225. runburstratios = burstratios.xs('run', level='st8').iloc[0]
  226. sitburstratios = burstratios.xs('sit', level='st8').iloc[0]
  227. _, pval = ttest_ind(runburstratios, sitburstratios, equal_var=False)
  228. sgnfs.append(pval < SCATTERPTHRESH) # bool
  229. fig5.loc[(mseustr, ST8S, opto), 'meanburstratio'] = brrun, brsit # save
  230. fig5.loc[(mseustr, ST8S, opto), 'burstratios'] = burstratios.values # save trial-wise
  231. if mvimseu2exmpli.get(mseustr) == fig5exmpli:
  232. exmplis.append(keptmseui)
  233. exmplmseustrs.append(mseustr)
  234. else:
  235. normlis.append(keptmseui)
  236. keptmseui += 1 # manually increment
  237. brruns = np.asarray(brruns)
  238. brsits = np.asarray(brsits)
  239. sgnfs = np.asarray(sgnfs)
  240. # plot y=x line:
  241. xyline = [10**logmin, 10**logmax], [10**logmin, 10**logmax]
  242. a.plot(xyline[0], xyline[1], '--', color='gray', zorder=-1)
  243. insgnfis, = np.where(sgnfs == False)
  244. sgnfis, = np.where(sgnfs == True)
  245. normlinsgnfis = np.intersect1d(normlis, insgnfis)
  246. normlsgnfis = np.intersect1d(normlis, sgnfis)
  247. # plot normal (non-example) insignificant points:
  248. c = desat(black, SGNF2ALPHA[False]) # do manual alpha mixing
  249. a.scatter(brsits[normlinsgnfis], brruns[normlinsgnfis], clip_on=True,
  250. marker='.', c='None', edgecolor=c, s=DEFSZ) # clip_on=False fails
  251. # plot normal (non-example) significant points:
  252. c = desat(black, SGNF2ALPHA[True]) # do manual alpha mixing
  253. a.scatter(brsits[normlsgnfis], brruns[normlsgnfis], clip_on=True,
  254. marker='.', c='None', edgecolor=c, s=DEFSZ) # clip_on=False fails
  255. # plot example points, one at a time:
  256. for exmpli, mseustr in zip(exmplis, exmplmseustrs):
  257. marker = exmpli2mrk[mvimseu2exmpli[mseustr]]
  258. c = exmpli2clr[mvimseu2exmpli[mseustr]]
  259. sz = exmpli2sz[mvimseu2exmpli[mseustr]]
  260. lw = exmpli2lw[mvimseu2exmpli[mseustr]]
  261. a.scatter(brsits[exmpli], brruns[exmpli], clip_on=False,
  262. marker=marker, c=c, s=sz, lw=lw)
  263. a.set_xlabel('Sit BR')
  264. a.set_ylabel('Run BR')
  265. a.set_xscale('log')
  266. a.set_yscale('log')
  267. a.set_xlim(10**logmin, 10**logmax)
  268. a.set_ylim(10**logmin, 10**logmax)
  269. a.set_xticks(10.0**logticks)
  270. a.set_yticks(a.get_xticks()) # make log scale y ticks the same as x ticks
  271. a.minorticks_off()
  272. axes_disable_scientific(a)
  273. a.set_aspect('equal')
  274. a.spines['left'].set_position(('outward', 4))
  275. a.spines['bottom'].set_position(('outward', 4))
  276. #t, p = ttest_rel(brsits, brruns) # paired t-test
  277. #a.add_artist(AnchoredText('p$=$%.2g' % p, loc='upper left', frameon=False))
  278. # scatter plot movie run vs sit sparseness, during feedback condition:
  279. figsize = DEFAULTFIGURESIZE
  280. linmin, linmax, linstep = 0, 1, 0.5
  281. ticks = np.arange(intround(linmin), intround(linmax)+linstep, linstep)
  282. for kind in ['nat']:#MVIKINDS:
  283. for opto in OPTOS:
  284. f, a = plt.subplots(figsize=figsize)
  285. wintitle('runsit sparseness movie %s %s' % (kind, opto))
  286. sparsruns, sparssits, exmplis, exmplmseustrs, normlis = [], [], [], [], []
  287. keptmseui = 0 # manually init and increment instead of using enumerate()
  288. for mseustr in mvimseustrs:
  289. spars = mviresp.loc[mseustr, kind, ST8S, opto]['spars']
  290. snr = mviresp.loc[mseustr, kind, ST8S, opto]['snr']
  291. if spars.isna().any(): # missing one or both values
  292. continue
  293. if (snr < SNRTHRESH).all(): # neither condition has decent SNR
  294. continue
  295. sparsrun, sparssit = spars.values
  296. sparsruns.append(sparsrun)
  297. sparssits.append(sparssit)
  298. fig5.loc[(mseustr, ST8S, opto), 'spars'] = sparsrun, sparssit # save
  299. if mvimseu2exmpli.get(mseustr) == fig5exmpli:
  300. exmplis.append(keptmseui)
  301. exmplmseustrs.append(mseustr)
  302. else:
  303. normlis.append(keptmseui)
  304. keptmseui += 1 # manually increment
  305. sparsruns = np.asarray(sparsruns)
  306. sparssits = np.asarray(sparssits)
  307. # plot y=x line:
  308. xyline = [linmin, linmax], [linmin, linmax]
  309. a.plot(xyline[0], xyline[1], '--', color='gray', zorder=-1)
  310. # plot normal (non-example) points:
  311. a.scatter(sparssits[normlis], sparsruns[normlis], clip_on=False,
  312. marker='.', c='None', edgecolor='black', s=DEFSZ)
  313. # plot example points, one at a time:
  314. for exmpli, mseustr in zip(exmplis, exmplmseustrs):
  315. marker = exmpli2mrk[mvimseu2exmpli[mseustr]]
  316. c = exmpli2clr[mvimseu2exmpli[mseustr]]
  317. sz = exmpli2sz[mvimseu2exmpli[mseustr]]
  318. lw = exmpli2lw[mvimseu2exmpli[mseustr]]
  319. a.scatter(sparssits[exmpli], sparsruns[exmpli], clip_on=False,
  320. marker=marker, c=c, s=sz, lw=lw)
  321. a.set_xlabel('Sit sparseness')
  322. a.set_ylabel('Run sparseness')
  323. a.set_xlim(linmin, linmax)
  324. a.set_ylim(linmin, linmax)
  325. a.set_xticks(ticks)
  326. a.set_yticks(ticks)
  327. a.set_aspect('equal')
  328. a.spines['left'].set_position(('outward', 4))
  329. a.spines['bottom'].set_position(('outward', 4))
  330. #t, p = ttest_rel(sparssits, sparsruns) # paired t-test
  331. #a.add_artist(AnchoredText('p$=$%.2g' % p, loc='upper left', frameon=False))
  332. # scatter plot movie run vs sit reliability, during feedback condition:
  333. figsize = DEFAULTFIGURESIZE[0]*0.98, DEFAULTFIGURESIZE[1] # tweak down to match others
  334. linmin, linmax = 0, 0.63
  335. ticks = 0, 0.5
  336. for kind in ['nat']:#MVIKINDS:
  337. for opto in OPTOS:
  338. f, a = plt.subplots(figsize=figsize)
  339. wintitle('runsit reliability movie %s %s' % (kind, opto))
  340. relruns, relsits, sgnfs, exmplis, exmplmseustrs, normlis = [], [], [], [], [], []
  341. keptmseui = 0 # manually init and increment instead of using enumerate()
  342. for mseustr in mvimseustrs:
  343. rel = mviresp.loc[mseustr, kind, ST8S, opto]['rel']
  344. snr = mviresp.loc[mseustr, kind, ST8S, opto]['snr']
  345. if rel.isna().any(): # missing one or both values
  346. continue
  347. if (snr < SNRTHRESH).all(): # neither condition has decent SNR
  348. continue
  349. relrun, relsit = rel.values
  350. relruns.append(relrun)
  351. relsits.append(relsit)
  352. rhos = mviresp.loc[mseustr, kind, ST8S, opto]['rhos']
  353. runrhos = rhos.xs('run', level='st8').iloc[0]
  354. sitrhos = rhos.xs('sit', level='st8').iloc[0]
  355. _, pval = ttest_ind(runrhos, sitrhos, equal_var=False)
  356. sgnfs.append(pval < SCATTERPTHRESH) # bool
  357. fig5.loc[(mseustr, ST8S, opto), 'rel'] = relrun, relsit # save
  358. if mvimseu2exmpli.get(mseustr) == fig5exmpli:
  359. exmplis.append(keptmseui)
  360. exmplmseustrs.append(mseustr)
  361. else:
  362. normlis.append(keptmseui)
  363. keptmseui += 1 # manually increment
  364. relruns = np.asarray(relruns)
  365. relsits = np.asarray(relsits)
  366. sgnfs = np.asarray(sgnfs)
  367. # plot y=x line:
  368. xyline = [linmin, linmax], [linmin, linmax]
  369. a.plot(xyline[0], xyline[1], '--', color='gray', zorder=-1)
  370. insgnfis, = np.where(sgnfs == False)
  371. sgnfis, = np.where(sgnfs == True)
  372. normlinsgnfis = np.intersect1d(normlis, insgnfis)
  373. normlsgnfis = np.intersect1d(normlis, sgnfis)
  374. # plot normal (non-example) insignificant points:
  375. c = desat(black, SGNF2ALPHA[False]) # do manual alpha mixing
  376. a.scatter(relsits[normlinsgnfis], relruns[normlinsgnfis], clip_on=False,
  377. marker='.', c='None', edgecolor=c, s=DEFSZ)
  378. # plot normal (non-example) significant points:
  379. c = desat(black, SGNF2ALPHA[True]) # do manual alpha mixing
  380. a.scatter(relsits[normlsgnfis], relruns[normlsgnfis], clip_on=False,
  381. marker='.', c='None', edgecolor=c, s=DEFSZ)
  382. # plot example points, one at a time:
  383. for exmpli, mseustr in zip(exmplis, exmplmseustrs):
  384. marker = exmpli2mrk[mvimseu2exmpli[mseustr]]
  385. c = exmpli2clr[mvimseu2exmpli[mseustr]]
  386. sz = exmpli2sz[mvimseu2exmpli[mseustr]]
  387. lw = exmpli2lw[mvimseu2exmpli[mseustr]]
  388. a.scatter(relsits[exmpli], relruns[exmpli], clip_on=False,
  389. marker=marker, c=c, s=sz, lw=lw)
  390. a.set_xlabel('Sit reliability')
  391. a.set_ylabel('Run reliability')
  392. a.set_xlim(linmin, linmax)
  393. a.set_ylim(linmin, linmax)
  394. a.set_xticks(ticks)
  395. a.set_yticks(ticks)
  396. a.set_aspect('equal')
  397. a.spines['left'].set_position(('outward', 4))
  398. a.spines['bottom'].set_position(('outward', 4))
  399. #t, p = ttest_rel(relsits, relruns) # paired t-test
  400. #a.add_artist(AnchoredText('p$=$%.2g' % p, loc='upper left', frameon=False))
  401. # scatter plot movie sit vs. run SNR:
  402. figsize = DEFAULTFIGURESIZE
  403. linmin, linmax = 0, 0.65
  404. ticks = 0, 0.5
  405. for kind in ['nat']:#MVIKINDS:
  406. for opto in OPTOS:
  407. f, a = plt.subplots(figsize=figsize)
  408. wintitle('runsit SNR movie %s %s' % (kind, opto))
  409. snrruns, snrsits, exmplis, exmplmseustrs, normlis = [], [], [], [], []
  410. keptmseui = 0 # manually init and increment instead of using enumerate()
  411. for mseustr in mvimseustrs:
  412. snr = mviresp.loc[mseustr, kind, ST8S, opto]['snr']
  413. if snr.isna().any(): # missing one or both values
  414. continue
  415. if (snr < SNRTHRESH).all(): # neither condition has decent SNR
  416. continue
  417. snrrun, snrsit = snr.values
  418. snrruns.append(snrrun)
  419. snrsits.append(snrsit)
  420. fig5.loc[(mseustr, ST8S, opto), 'snr'] = snrrun, snrsit # save
  421. if mvimseu2exmpli.get(mseustr) == fig5exmpli:
  422. exmplis.append(keptmseui)
  423. exmplmseustrs.append(mseustr)
  424. else:
  425. normlis.append(keptmseui)
  426. keptmseui += 1 # manually increment
  427. snrruns = np.asarray(snrruns)
  428. snrsits = np.asarray(snrsits)
  429. # plot y=x line:
  430. xyline = [linmin, linmax], [linmin, linmax]
  431. a.plot(xyline[0], xyline[1], '--', color='gray', zorder=-1)
  432. # plot normal (non-example) points:
  433. a.scatter(snrsits[normlis], snrruns[normlis], clip_on=False,
  434. marker='.', c='None', edgecolor='black', s=DEFSZ)
  435. # plot example points, one at a time:
  436. for exmpli, mseustr in zip(exmplis, exmplmseustrs):
  437. marker = exmpli2mrk[mvimseu2exmpli[mseustr]]
  438. c = exmpli2clr[mvimseu2exmpli[mseustr]]
  439. sz = exmpli2sz[mvimseu2exmpli[mseustr]]
  440. lw = exmpli2lw[mvimseu2exmpli[mseustr]]
  441. a.scatter(snrsits[exmpli], snrruns[exmpli], clip_on=False,
  442. marker=marker, c=c, s=sz, lw=lw)
  443. a.set_xlabel('Sit SNR')
  444. a.set_ylabel('Run SNR')
  445. a.set_xlim(linmin, linmax)
  446. a.set_ylim(linmin, linmax)
  447. a.set_xticks(ticks)
  448. a.set_yticks(ticks)
  449. a.set_aspect('equal')
  450. a.spines['left'].set_position(('outward', 4))
  451. a.spines['bottom'].set_position(('outward', 4))
  452. #t, p = ttest_rel(snrsits, snrruns) # paired t-test
  453. #a.add_artist(AnchoredText('p$=$%.2g' % p, loc='upper left', frameon=False))
  454. # scatter plot movie run vs sit mean peak widths, during feedback condition:
  455. figsize = DEFAULTFIGURESIZE[0]*1.05, DEFAULTFIGURESIZE[1] # tweak to make space for log units
  456. linmin, linmax = 0.025, 0.2
  457. ticks = 0.05, 0.1, 0.2
  458. for kind in ['nat']:#MVIKINDS:
  459. for opto in OPTOS:
  460. f, a = plt.subplots(figsize=figsize)
  461. wintitle('runsit mean peak width movie %s %s' % (kind, opto))
  462. meanpkwruns, meanpkwsits, exmplis, exmplmseustrs, normlis = [], [], [], [], []
  463. keptmseui = 0 # manually init and increment instead of using enumerate()
  464. for mseustr in mvimseustrs:
  465. meanpkw = mviresp.loc[mseustr, kind, ST8S, opto]['meanpkw']
  466. snr = mviresp.loc[mseustr, kind, ST8S, opto]['snr']
  467. if meanpkw.isna().any(): # missing one or both values
  468. continue
  469. if (snr < SNRTHRESH).all(): # neither condition has decent SNR
  470. continue
  471. meanpkwrun, meanpkwsit = meanpkw.values
  472. meanpkwruns.append(meanpkwrun)
  473. meanpkwsits.append(meanpkwsit)
  474. fig5.loc[(mseustr, ST8S, opto), 'meanpkw'] = meanpkwrun, meanpkwsit # save
  475. if mvimseu2exmpli.get(mseustr) == fig5exmpli:
  476. exmplis.append(keptmseui)
  477. exmplmseustrs.append(mseustr)
  478. else:
  479. normlis.append(keptmseui)
  480. keptmseui += 1 # manually increment
  481. meanpkwruns = np.asarray(meanpkwruns)
  482. meanpkwsits = np.asarray(meanpkwsits)
  483. # plot y=x line:
  484. xyline = [linmin, linmax], [linmin, linmax]
  485. a.plot(xyline[0], xyline[1], '--', color='gray', zorder=-1)
  486. # plot normal (non-example) points:
  487. a.scatter(meanpkwsits[normlis], meanpkwruns[normlis], clip_on=False,
  488. marker='.', c='None', edgecolor='black', s=DEFSZ)
  489. # plot example points, one at a time:
  490. for exmpli, mseustr in zip(exmplis, exmplmseustrs):
  491. marker = exmpli2mrk[mvimseu2exmpli[mseustr]]
  492. c = exmpli2clr[mvimseu2exmpli[mseustr]]
  493. sz = exmpli2sz[mvimseu2exmpli[mseustr]]
  494. lw = exmpli2lw[mvimseu2exmpli[mseustr]]
  495. a.scatter(meanpkwsits[exmpli], meanpkwruns[exmpli], clip_on=False,
  496. marker=marker, c=c, s=sz, lw=lw)
  497. a.set_xscale('log')
  498. a.set_yscale('log')
  499. a.set_xlabel('Sit peak width (s)')
  500. a.set_ylabel('Run peak width (s)')
  501. a.set_xlim(linmin, linmax)
  502. a.set_ylim(linmin, linmax)
  503. a.set_xticks(ticks)
  504. a.set_yticks(a.get_xticks()) # make log scale y ticks the same as x ticks
  505. a.minorticks_off()
  506. axes_disable_scientific(a)
  507. a.set_aspect('equal')
  508. a.spines['left'].set_position(('outward', 4))
  509. a.spines['bottom'].set_position(('outward', 4))
  510. #t, p = ttest_rel(meanpkwsits, meanpkwruns) # paired t-test
  511. #a.add_artist(AnchoredText('p$=$%.2g' % p, loc='lower right', frameon=False))
  512. # scatter plot RMI of all movie measures vs meanrate RMI:
  513. figsize = DEFAULTFIGURESIZE
  514. linmin, linmax, linstep = -1, 1, 1
  515. ticks = np.arange(linmin, linmax+linstep, linstep)
  516. for kind in ['nat']:#MVIKINDS:
  517. for opto in [False]:#OPTOS:
  518. for measure in modmeasuresnoblank:
  519. if measure.startswith('meanrate'):
  520. continue # don't bother plotting meanrate* against meanrate
  521. axislabel = measure2axislabel[measure]
  522. rrmis, msrrmis = [], []
  523. exmplis, exmplmseustrs, normlis = [], [], []
  524. keptmseui = 0 # manually init and increment instead of using enumerate()
  525. for mseustr in mvimseustrs:
  526. rrmi = mviRMI.loc[mseustr, opto]['meanrate']
  527. msrrmi = mviRMI.loc[mseustr, opto][measure]
  528. if pd.isna(rrmi) or pd.isna(msrrmi): # missing at least one RMI value
  529. continue
  530. rrmis.append(rrmi)
  531. msrrmis.append(msrrmi)
  532. if mvimseu2exmpli.get(mseustr) == fig1exmpli:
  533. exmplis.append(keptmseui)
  534. exmplmseustrs.append(mseustr)
  535. else:
  536. normlis.append(keptmseui)
  537. keptmseui += 1 # manually increment
  538. rrmis, msrrmis = np.asarray(rrmis), np.asarray(msrrmis)
  539. assert len(rrmis) == len(msrrmis)
  540. print('%s vs meanrate: nobservations=%d' % (measure, len(rrmis)))
  541. ## scatter plot RMIs:
  542. f, a = plt.subplots(figsize=figsize)
  543. wintitle('opto RMI %s vs RMI rate %s %s' % (measure, kind, opto))
  544. # plot x=0 and y=0 lines:
  545. a.axhline(y=0, ls='--', marker='', color='lightgray', zorder=-np.inf)
  546. a.axvline(x=0, ls='--', marker='', color='lightgray', zorder=-np.inf)
  547. # plot normal (non-example) points:
  548. a.scatter(rrmis[normlis], msrrmis[normlis], clip_on=False,
  549. marker='.', c='None', edgecolor=opto2clr[opto], s=DEFSZ)
  550. # plot example points, one at a time:
  551. for exmpli, mseustr in zip(exmplis, exmplmseustrs):
  552. marker = exmpli2mrk[mvimseu2exmpli[mseustr]]
  553. c = exmpli2clr[mvimseu2exmpli[mseustr]]
  554. sz = exmpli2sz[mvimseu2exmpli[mseustr]]
  555. lw = exmpli2lw[mvimseu2exmpli[mseustr]]
  556. a.scatter(rrmis[exmpli], msrrmis[exmpli], clip_on=False,
  557. marker=marker, c=c, s=sz, lw=lw)
  558. # get fname of appropriate LMM .cvs file:
  559. if measure == 'meanburstratio': # use Steffen's LMM linregress fit, for fig5S1
  560. fname = os.path.join('stats', 'figure_5S1c_coefs.csv')
  561. elif measure == 'spars': # use Steffen's LMM linregress fit, for fig5S1
  562. fname = os.path.join('stats', 'figure_5S1d_coefs.csv')
  563. elif measure == 'rel': # use Steffen's LMM linregress fit, for fig5S1
  564. fname = os.path.join('stats', 'figure_5S1e_coefs.csv')
  565. elif measure == 'snr': # use Steffen's LMM linregress fit, for fig5S1
  566. fname = os.path.join('stats', 'figure_5S1f_coefs.csv')
  567. elif measure == 'meanpkw': # use Steffen's LMM linregress fit, for fig5S1
  568. fname = os.path.join('stats', 'figure_5S1g_coefs.csv')
  569. else:
  570. print("WARNING: No LMM stats for %s measure" % measure)
  571. fname = None
  572. # fetch LMM linregress fit params from .csv:
  573. if fname:
  574. try:
  575. df = pd.read_csv(fname)
  576. foundregression = True
  577. except FileNotFoundError:
  578. print('Missing file: %s' % fname)
  579. foundregression = False
  580. if foundregression:
  581. mm = df['slope'][0]
  582. b = df['intercept'][0]
  583. x = np.array([rrmis.min(), rrmis.max()])
  584. y = mm * x + b
  585. a.plot(x, y, '-', color='red') # plot linregress fit
  586. a.set_xlabel('Firing rate RMI')
  587. if axislabel.islower():
  588. axislabel = axislabel.capitalize()
  589. ylabel = '%s RMI' % axislabel
  590. a.set_ylabel(ylabel)
  591. a.set_xlim(linmin, linmax)
  592. a.set_ylim(linmin, linmax)
  593. a.set_xticks(ticks)
  594. a.set_yticks(ticks)
  595. a.minorticks_off()
  596. a.set_aspect('equal')
  597. a.spines['left'].set_position(('outward', 4))
  598. a.spines['bottom'].set_position(('outward', 4))
  599. # scatter plot movie vs grating RMI for applicable measures:
  600. figsize = DEFAULTFIGURESIZE
  601. linmin, linmax, linstep = -1, 1, 1
  602. for measure in ['meanrate', 'meanburstratio']: # only 2 measures applicable to both mvi & grt
  603. axislabel = measure2axislabel[measure]
  604. for opto in OPTOS:
  605. f, a = plt.subplots(figsize=figsize)
  606. wintitle('maxRMI %s movie grating %s' % (measure, opto))
  607. mvimods, grtmods, exmplis, exmplmsustrs, normlis = [], [], [], [], []
  608. keptmsui = 0 # manually init and increment instead of using enumerate()
  609. for msustr in mvigrtmsustrs:
  610. mod = maxRMI[measure][msustr, opto]
  611. if mod.isna().any(): # missing one or both mod values
  612. continue
  613. mvimods.append(mod['mvi'])
  614. grtmods.append(mod['grt'])
  615. if msu2exmpli.get(msustr) == fig5exmpli:
  616. exmplis.append(keptmsui)
  617. exmplmsustrs.append(msustr)
  618. else:
  619. normlis.append(keptmsui)
  620. keptmsui += 1 # manually increment
  621. mvimods = np.asarray(mvimods)
  622. grtmods = np.asarray(grtmods)
  623. # plot y=x line:
  624. xyline = [linmin, linmax], [linmin, linmax]
  625. a.plot(xyline[0], xyline[1], '--', color='gray', zorder=-1)
  626. # plot normal (non-example) points:
  627. c = desat('black', opto2alpha[opto]) # do manual alpha mixing
  628. a.scatter(grtmods[normlis], mvimods[normlis], clip_on=False,
  629. marker='.', c='None', edgecolor=c, s=DEFSZ)
  630. # plot example points, one at a time:
  631. for exmpli, msustr in zip(exmplis, exmplmsustrs):
  632. marker = exmpli2mrk[msu2exmpli[msustr]]
  633. c = exmpli2clr[msu2exmpli[msustr]]
  634. sz = exmpli2sz[msu2exmpli[msustr]]
  635. lw = exmpli2lw[msu2exmpli[msustr]]
  636. a.scatter(grtmods[exmpli], mvimods[exmpli], clip_on=False,
  637. marker=marker, c=c, s=sz, lw=lw)
  638. a.set_xlabel('Grating %s RMI' % axislabel)
  639. a.set_ylabel('Movie %s RMI' % axislabel)
  640. a.set_xlim(linmin, linmax)
  641. a.set_ylim(linmin, linmax)
  642. a.set_xticks(np.arange(linmin, linmax+linstep, linstep))
  643. a.set_yticks(a.get_xticks()) # make log scale y ticks the same as x ticks
  644. a.minorticks_off()
  645. a.set_aspect('equal')
  646. a.spines['left'].set_position(('outward', 4))
  647. a.spines['bottom'].set_position(('outward', 4))
  648. #t, p = ttest_rel(grtmods, mvimods) # paired t-test
  649. #a.add_artist(AnchoredText('$\mathregular{p=%.2g}$' % p,
  650. # loc='upper left', frameon=False))