fig2.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. # code for Figure 2 panels
  2. # import
  3. from matplotlib import pyplot as plt
  4. from matplotlib.ticker import ScalarFormatter, NullFormatter
  5. import numpy as np
  6. import pandas
  7. from scipy import stats
  8. from importlib import reload
  9. import spatint_utils
  10. import os
  11. # reload
  12. reload(spatint_utils)
  13. spatint_utils.plot_params()
  14. _, _, optocolor = spatint_utils.get_colors()
  15. class Fig2:
  16. """Class to for plotting panels for Fig.2"""
  17. def __init__(self):
  18. """Init class"""
  19. # read lgn size tuning dataframe
  20. parentdir = os. path. dirname(os. getcwd())
  21. filename = parentdir + '/data/lgn_sztun_df.pkl'
  22. self.lgn_sztun_df = pandas.read_pickle(
  23. filepath_or_buffer=filename)
  24. def ex_sztun_curve(self, figsize=(2.5, 2.5), ax=None):
  25. """Plot example dLGN size-tuning curve (Fig. 2h)
  26. Parameters
  27. -------
  28. figsize: tuple
  29. Figure size (width, height)
  30. ax: mpl axis
  31. axis for plot
  32. Returns
  33. -------
  34. ax: mpl axis
  35. axis for plot
  36. """
  37. if ax is None:
  38. # create figure
  39. f, ax = plt.subplots(figsize=figsize)
  40. # define example index
  41. ex_idx = 22
  42. # plot curves
  43. spatint_utils.plot_tun(means=self.lgn_sztun_df.loc[ex_idx]['tun_mean'],
  44. sems=self.lgn_sztun_df.loc[ex_idx]['tun_sem'],
  45. spons=self.lgn_sztun_df.loc[ex_idx]['tun_spon_mean'],
  46. xs=self.lgn_sztun_df.loc[ex_idx]['ti_axes'],
  47. c_fit=self.lgn_sztun_df.loc[ex_idx]['c_sz_fit'],
  48. op_fit=self.lgn_sztun_df.loc[ex_idx]['op_sz_fit'],
  49. c_prefsz=self.lgn_sztun_df.loc[ex_idx]['rfcs_76'][0],
  50. op_prefsz=self.lgn_sztun_df.loc[ex_idx]['rfcs_76'][1],
  51. ax=ax)
  52. f = plt.gcf()
  53. f.tight_layout()
  54. return ax
  55. def fit_norm_curves(self, ax=None, figsize=(2.5, 2.5)):
  56. """Plots normalized dLGN size-tuning curves (Fig. 2i)
  57. Parameters
  58. -------
  59. figsize: tuple
  60. Figure size (width, height)
  61. ax: mpl axis
  62. axis for plot
  63. Returns
  64. -------
  65. ax: mpl axis
  66. axis for plot
  67. """
  68. if ax is None:
  69. # create figure if ax is none
  70. f, ax = plt.subplots(figsize=figsize)
  71. # get ydata
  72. yconts = self.lgn_sztun_df.c_sz_fit.to_list()
  73. yoptos = self.lgn_sztun_df.op_sz_fit.to_list()
  74. # normalize
  75. ycont_norm = np.vstack([cont / np.nanmax(np.concatenate((cont, opto))) for cont,
  76. opto in zip(yconts, yoptos)])
  77. yopto_norm = np.vstack([opto / np.nanmax(np.concatenate((cont, opto))) for cont,
  78. opto in zip(yconts, yoptos)])
  79. # compute mean for both conditions
  80. cont_mean = np.nanmean(ycont_norm, axis=0)
  81. opto_mean = np.nanmean(yopto_norm, axis=0)
  82. # compute sem for both conditions
  83. cont_sem = stats.sem(ycont_norm, axis=0)
  84. opto_sem = stats.sem(yopto_norm, axis=0)
  85. # plot curves and sem
  86. x_eval = np.arange(76)
  87. ax.plot(x_eval, cont_mean, color='k', linestyle='-')
  88. ax.fill_between(x_eval, cont_mean - cont_sem, cont_mean + cont_sem, color='k',
  89. alpha=0.5, linewidth=0)
  90. ax.plot(x_eval, opto_mean, color=optocolor, linestyle='-')
  91. ax.fill_between(x_eval, opto_mean - opto_sem, opto_mean + opto_sem, color=optocolor,
  92. alpha=0.5, linewidth=0)
  93. # layout
  94. ax.set_ylabel('Normalized firing rate')
  95. ax.set_xlabel('Diameter ($\degree$)')
  96. ax.set_xticks((0, 25, 50, 75))
  97. ax.set_yticks((0, 0.5, 1))
  98. ax.spines['bottom'].set_bounds(0, 75)
  99. ax.spines['left'].set_bounds(0, 1)
  100. f = plt.gcf()
  101. f.tight_layout()
  102. return ax
  103. def scatter(self, figsize=(2.5, 2.5), ax=None, alys=None):
  104. """Plot scatterplots to compare dLGN spatial integration with V1 intact vs suppressed (
  105. Fig. 2j-m)
  106. Parameters
  107. -------
  108. figsize: tuple
  109. Figure size (width, height)
  110. ax: mpl axis
  111. axis for plot
  112. alys: string: 'ropt', 'rsupp', 'rfcs', 'si'
  113. determines which parameter to analyze: modelled response to optimal stimulus (
  114. ropt), modelled response to large stimulus (rsupp), preferred size (rfcs),
  115. suppression index (si)
  116. Returns
  117. -------
  118. ax: mpl axis
  119. axis for plot
  120. """
  121. if ax is None:
  122. # create figure if ax is none
  123. f, ax = plt.subplots(figsize=figsize)
  124. if alys == 'ropt':
  125. # compare modelled response to optimal stimulus
  126. # get data
  127. cont = self.lgn_sztun_df['r_opt_c_76'].values
  128. supp = self.lgn_sztun_df['r_opt_op_crfcs_76'].values
  129. # compute statistics
  130. cont_mean, supp_mean = spatint_utils.compute_stats(cont=cont, supp=supp, alys=alys)
  131. # set threshold for plotting
  132. min_thres = 4
  133. min_dist = 1
  134. max_dist = 43
  135. cont_plot = cont
  136. cont_plot[cont_plot > 30] = max_dist
  137. cont_plot[cont_plot < min_thres] = min_thres - min_dist
  138. supp_plot = supp
  139. supp_plot[supp_plot > 30] = max_dist
  140. supp_plot[supp_plot < min_thres] = min_thres - min_dist
  141. # layout
  142. titlestr = 'Small size\nresponse (sp/s)'
  143. ax.set_yscale('log')
  144. ax.set_xscale('log')
  145. for axis in [ax.xaxis, ax.yaxis]:
  146. axis.set_major_formatter(ScalarFormatter())
  147. axis.set_minor_formatter(NullFormatter())
  148. ax.set_title(titlestr)
  149. ax.set_xlim(min_thres - (min_dist * 2), max_dist)
  150. ax.set_ylim(min_thres - (min_dist * 2), max_dist)
  151. ax.plot((min_thres, 30), (min_thres, 30), linestyle='-', color='grey', zorder=-1,
  152. linewidth=0.35)
  153. ax.spines['left'].set_bounds(min_thres, 30)
  154. ax.spines['bottom'].set_bounds(min_thres, 30)
  155. ax.set_xticks((min_thres - min_dist, 10, 30, max_dist))
  156. ax.set_yticks((min_thres - min_dist, 10, 30, max_dist))
  157. ax.set_yticklabels(('<' + str(min_thres), 10, 30, '>30'))
  158. ax.set_xticklabels(('<' + str(min_thres), 10, 30, ' >30'))
  159. elif alys == 'rsupp':
  160. # compare modelled response to largest stimulus
  161. # get data
  162. cont = self.lgn_sztun_df['r_supp_201'].str[0].values
  163. supp = self.lgn_sztun_df['r_supp_201'].str[1].values
  164. # compute statistics
  165. cont_mean, supp_mean = spatint_utils.compute_stats(cont=cont, supp=supp, alys=alys)
  166. # set threshold for plotting
  167. min_thres = 4
  168. min_dist = 1
  169. max_dist = 43
  170. cont_plot = cont
  171. cont_plot[cont_plot > 30] = max_dist
  172. cont_plot[cont_plot < min_thres] = min_thres - min_dist
  173. supp_plot = supp
  174. supp_plot[supp_plot > 30] = max_dist
  175. supp_plot[supp_plot < min_thres] = min_thres - min_dist
  176. # layout
  177. titlestr = 'Large size\nresponse (sp/s)'
  178. ax.set_yscale('log')
  179. ax.set_xscale('log')
  180. for axis in [ax.xaxis, ax.yaxis]:
  181. axis.set_major_formatter(ScalarFormatter())
  182. axis.set_minor_formatter(NullFormatter())
  183. ax.set_title(titlestr)
  184. ax.set_xlim(min_thres - (min_dist * 2), max_dist)
  185. ax.set_ylim(min_thres - (min_dist * 2), max_dist)
  186. ax.plot((min_thres, 30), (min_thres, 30), linestyle='-', color='grey', zorder=-1,
  187. linewidth=0.35)
  188. ax.spines['left'].set_bounds(min_thres, 30)
  189. ax.spines['bottom'].set_bounds(min_thres, 30)
  190. ax.set_xticks((min_thres - min_dist, 10, 30, max_dist))
  191. ax.set_yticks((min_thres - min_dist, 10, 30, max_dist))
  192. ax.set_yticklabels(('<' + str(min_thres), 10, 30, '>30'))
  193. ax.set_xticklabels(('<' + str(min_thres), 10, 30, ' >30'))
  194. elif alys == 'rfcs':
  195. # compare preferred size
  196. # get data
  197. cont = self.lgn_sztun_df['rfcs_76'].str[0].values
  198. supp = self.lgn_sztun_df['rfcs_76'].str[1].values
  199. # compute and calculate stats
  200. cont_mean, supp_mean = spatint_utils.compute_stats(cont=cont, supp=supp, alys=alys)
  201. # set threshold for plotting
  202. cont_plot = cont
  203. cont_plot[cont_plot > 30] = 35
  204. supp_plot = supp
  205. supp_plot[supp_plot > 30] = 35
  206. # layout
  207. titlestr = 'Preferred size ($\degree$)'
  208. ax.set_title(titlestr)
  209. ax.set_xlim(-1.75, 35)
  210. ax.set_ylim(-1.75, 35)
  211. ax.plot((0, 30), (0, 30), linestyle='-', color='grey', zorder=-1, linewidth=0.35)
  212. ax.spines['left'].set_bounds(0, 30)
  213. ax.spines['bottom'].set_bounds(0, 30)
  214. ax.set_xticks((0, 15, 30, 35))
  215. ax.set_yticks((0, 15, 30, 35))
  216. ax.set_yticklabels((0, 15, 30, '>30'))
  217. ax.set_xticklabels((0, 15, 30, ' >30'))
  218. elif alys == 'si':
  219. # compare suppression indices
  220. # get data
  221. cont_plot = self.lgn_sztun_df['si_76'].str[0].values
  222. supp_plot = self.lgn_sztun_df['si_76'].str[1].values
  223. # compute and calculate stats
  224. cont_mean, supp_mean = spatint_utils.compute_stats(cont=cont_plot, supp=supp_plot,
  225. alys=alys)
  226. # layout
  227. titlestr = 'SI'
  228. ax.set_title(titlestr)
  229. ax.set_xlim(-0.05, 1.05)
  230. ax.set_ylim(-0.05, 1.05)
  231. ax.set_xticks((0, 0.5, 1))
  232. ax.set_yticks((0, 0.5, 1))
  233. ax.plot((0, 1), (0, 1), linestyle='-', color='grey', linewidth=0.35, zorder=-1)
  234. ax.spines['left'].set_bounds(0, 1)
  235. ax.spines['bottom'].set_bounds(0, 1)
  236. else:
  237. print('No proper analysis selected')
  238. return
  239. # general layout
  240. ax.set_title(titlestr)
  241. ax.scatter(cont_plot, supp_plot, s=15, facecolors='none', edgecolors='k',
  242. linewidth=0.5, clip_on=False)
  243. ax.plot(cont_mean, supp_mean, linestyle='', marker='.', color='goldenrod', ms=15)
  244. # plot example
  245. ax.plot(cont_plot[22], supp_plot[22], linestyle='', marker='.', color='deeppink',
  246. ms=15)
  247. ax.set_ylabel('V1 suppression')
  248. ax.yaxis.label.set_color(optocolor)
  249. ax.set_xlabel('Control')
  250. f = plt.gcf()
  251. f.tight_layout()
  252. return ax