fig3.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. # code to plot modelled data in figure 3
  2. # import libs
  3. import numpy as np
  4. import matplotlib.pyplot as plt
  5. import matplotlib.patches as patch
  6. import scipy.stats as stats
  7. from importlib import reload
  8. import spatint_utils
  9. import sim_edog
  10. # reload modules
  11. reload(spatint_utils)
  12. # load params
  13. spatint_utils.plot_params()
  14. _, _, optocolor = spatint_utils.get_colors()
  15. cmpin = 2.54
  16. class Fig3:
  17. """Class for plotting Figure 3"""
  18. def __init__(self, figsize=np.array((18.3, 8)), edog=None, inhib_fb=(1, 3, 9, 40)):
  19. """Init class
  20. Parameters
  21. -----
  22. figsize: tuple len 2
  23. figuresize (width, heigth)
  24. edog: class object
  25. edog with simulated data
  26. inhib_fb: tuple
  27. example inhibitory feedback kernel widths to be plotted
  28. """
  29. # store init parameters
  30. self.figsize = figsize / cmpin # figure size
  31. self.sids = edog.sids # change in suppression indices
  32. self.rfcsds = edog.rfcsds # change in preferred size
  33. self.smallrateds = edog.smallrateds # change in response to small stim
  34. self.largerateds = edog.largerateds # change in response to large stim
  35. self.lowbounds = edog.lowbounds # dict with low bounds for matching
  36. self.highbounds = edog.highbounds # dict with high bounds for matching
  37. self.inhib_fb = inhib_fb # ex inhibitory fb kernel widths
  38. self.start = edog.start # first inhib fb kernel width
  39. self.stop = edog.stop # last inhib fb kernel width
  40. self.inhib_fbi = np.array(inhib_fb) - edog.start # index for example kernels
  41. def plot(self):
  42. """Plot figure"""
  43. # init figure
  44. f = plt.figure(figsize=self.figsize)
  45. # init plotting variables
  46. interplotspace = 0.5 / cmpin / self.figsize[0]
  47. axdict = {}
  48. axdict['b'] = 3 / cmpin / self.figsize[1]
  49. axdict['h'] = 1.5 / cmpin / self.figsize[1]
  50. axdict['w'] = 1.5 / cmpin / self.figsize[0]
  51. l = 5 / cmpin / self.figsize[0]
  52. # plot modelled size tuning curves
  53. inhib_fbs = self.inhib_fb
  54. inhib_fbi = self.inhib_fbi
  55. start = self.start
  56. stop = self.stop
  57. edog_model = sim_edog.SimEdog()
  58. sb_label = False
  59. # get color for inhib kernels
  60. cmap = plt.cm.get_cmap('Reds_r')
  61. coli = np.linspace(0, 0.5, 4)
  62. # loop over example inhibitory width
  63. for i, inhib_fb in enumerate(inhib_fbs):
  64. # add axis
  65. ax = f.add_axes([l, axdict['b'], axdict['w'], axdict['h']])
  66. # add curves
  67. edog_model.plot(ax=ax, inhib_fb=inhib_fb)
  68. # add kernel schemas
  69. self._plot_kernel(inhib_fb=inhib_fb, l=l, f=f, col=cmap(coli[i]), i=i,
  70. sb_label=sb_label)
  71. # label according to panel position
  72. if i > 0:
  73. # remove labels
  74. ax.set_ylabel('')
  75. ax.set_yticklabels('')
  76. ax.set_xlabel('')
  77. ax.set_xticklabels('')
  78. if i < (len(inhib_fbs) - 1):
  79. # add length
  80. l += interplotspace + axdict['w']
  81. if i == (len(inhib_fbs) - 2):
  82. # add sb_label
  83. sb_label = True
  84. elif i == (len(inhib_fbs) - 1):
  85. ax.text(10, 0.35, 'FB weight = 1', color='k')
  86. ax.text(10, 0.15, 'FB weight = 0', color=optocolor)
  87. # get x values
  88. x = np.arange(start, stop, 1)
  89. # define markersize
  90. ms = 8
  91. # add change in receptive field center size
  92. # prepare axis
  93. interplotspace = 1.5 / cmpin / self.figsize[0]
  94. axdict['h'] = 1.2 / cmpin / self.figsize[1]
  95. axdict['w'] = 1.2 / cmpin / self.figsize[0]
  96. l += axdict['w'] + interplotspace + 0.02
  97. ax = f.add_axes([l, axdict['b'], axdict['w'], axdict['h']])
  98. # add plot
  99. ax.plot(x, self.rfcsds, c='k')
  100. # edit layout
  101. xlims = ax.get_xlim()
  102. ax.hlines(0, xlims[0], xlims[1], colors='grey', linestyle='--', linewidth=0.5)
  103. ax.set_xticks((1, 20, 40))
  104. ax.set_yticks((0, -5, -10))
  105. ax.spines['bottom'].set_bounds(1, 40)
  106. ax.spines['left'].set_bounds(-10, 0)
  107. ax.set_ylabel('$\Delta$ preferred\nsize (%)')
  108. ax.set_xlabel('Inh FB kernel width ($\degree$)')
  109. # add quality rectangles
  110. ylims = ax.get_ylim()
  111. bottom = ylims[0]
  112. height = ylims[1] - bottom
  113. width_qual = self.highbounds['all'] - self.lowbounds['all']
  114. # overall
  115. rect_all = patch.Rectangle((self.lowbounds['all'], bottom), width_qual, height,
  116. facecolor='gold', alpha=0.7, zorder=0)
  117. ax.add_patch(rect_all)
  118. # preferred size specific
  119. rfcs_width = self.highbounds['rfcsds'] - self.lowbounds['rfcsds']
  120. rect_rfcs = patch.Rectangle((self.lowbounds['rfcsds'], bottom), rfcs_width, height,
  121. facecolor='gold', alpha=0.2, zorder=0)
  122. ax.add_patch(rect_rfcs)
  123. # add example points
  124. ax.scatter(inhib_fbs, np.array(self.rfcsds)[inhib_fbi], c=np.array(cmap(coli)), s=ms,
  125. zorder=3)
  126. # add changes in suppression index
  127. # prepare axis
  128. l += axdict['w'] + interplotspace
  129. ax = f.add_axes([l, axdict['b'], axdict['w'], axdict['h']])
  130. # add plot
  131. ax.plot(x, self.sids, c='k')
  132. # edit layout
  133. xlims = ax.get_xlim()
  134. ax.hlines(0, xlims[0], xlims[1], colors='grey', linestyle='--', linewidth=0.5)
  135. ax.set_xticks((1, 20, 40))
  136. ax.set_yticks((0, 100, 200))
  137. ax.spines['bottom'].set_bounds(1, 40)
  138. ax.spines['left'].set_bounds(0, 200)
  139. ax.set_ylabel('$\Delta$ suppression\nindex (%)')
  140. # add quality rectangle
  141. ylims = ax.get_ylim()
  142. bottom = ylims[0]
  143. height = ylims[1] - bottom
  144. # overall
  145. rect_all = patch.Rectangle((self.lowbounds['all'], bottom), width_qual, height,
  146. facecolor='gold', alpha=0.7, zorder=0)
  147. ax.add_patch(rect_all)
  148. # si specific
  149. si_width = self.highbounds['sids'] - self.lowbounds['sids']
  150. rect_si = patch.Rectangle((self.lowbounds['sids'], bottom), si_width, height,
  151. facecolor='gold', alpha=0.2, zorder=0)
  152. ax.add_patch(rect_si)
  153. # add example points
  154. ax.scatter(inhib_fbs, np.array(self.sids)[inhib_fbi], c=np.array(cmap(coli)), s=ms,
  155. zorder=3)
  156. # add changes in smallrates
  157. # prepare axis
  158. axdict['b'] += axdict['h'] + (1.5 / cmpin / self.figsize[0])
  159. l -= axdict['w'] + interplotspace
  160. ax = f.add_axes([l, axdict['b'], axdict['w'], axdict['h']])
  161. # add plot
  162. ax.plot(x, self.smallrateds, c='k')
  163. # layout
  164. xlims = ax.get_xlim()
  165. ax.hlines(0, xlims[0], xlims[1], colors='grey', linestyle='--', linewidth=0.5)
  166. ax.set_xticks((1, 20, 40))
  167. ax.set_xticklabels('')
  168. ax.set_yticks((-25, 0, 25))
  169. ax.spines['bottom'].set_bounds(1, 40)
  170. ylims = ax.get_ylim()
  171. ax.spines['left'].set_bounds(-25, ylims[1])
  172. ax.set_ylabel('$\Delta$ response to\npreferred size (%)')
  173. # add quality rectangle
  174. ylims = ax.get_ylim()
  175. bottom = ylims[0]
  176. height = ylims[1] - bottom
  177. # overall
  178. rect_all = patch.Rectangle((self.lowbounds['all'], bottom), width_qual, height,
  179. facecolor='gold', alpha=0.7, zorder=0)
  180. ax.add_patch(rect_all)
  181. # smallrate specific
  182. smallrate_width = self.highbounds['smallrateds'] - self.lowbounds['smallrateds']
  183. rect_smallrate = patch.Rectangle((self.lowbounds['smallrateds'], bottom),
  184. smallrate_width, height, facecolor='gold',
  185. alpha=0.2, zorder=0)
  186. ax.add_patch(rect_smallrate)
  187. # add example points
  188. ax.scatter(inhib_fbs, np.array(self.smallrateds)[inhib_fbi], c=np.array(cmap(coli)),
  189. s=ms, zorder=3)
  190. # add changes in large rates
  191. # add axis
  192. l += axdict['w'] + interplotspace
  193. ax = f.add_axes([l, axdict['b'], axdict['w'], axdict['h']])
  194. # add plot
  195. ax.plot(x, self.largerateds, c='k')
  196. # edit layout
  197. xlims = ax.get_xlim()
  198. ax.hlines(0, xlims[0], xlims[1], colors='grey', linestyle='--', linewidth=0.5)
  199. ax.set_xticks((1, 20, 40))
  200. ax.set_xticklabels('')
  201. ax.set_yticks((-20, 0))
  202. ax.spines['bottom'].set_bounds(1, 40)
  203. ylims = ax.get_ylim()
  204. ax.spines['left'].set_bounds(ylims)
  205. ax.set_ylabel('$\Delta$ response to\n largest size (%)')
  206. # add quality rectangle
  207. ylims = ax.get_ylim()
  208. bottom = ylims[0]
  209. height = ylims[1] - bottom
  210. # overall
  211. rect_all = patch.Rectangle((self.lowbounds['all'], bottom), width_qual, height,
  212. facecolor='gold', alpha=0.7, zorder=0)
  213. ax.add_patch(rect_all)
  214. # largerate specific
  215. largerate_width = self.highbounds['largerateds'] - self.lowbounds['largerateds']
  216. rect_largerate = patch.Rectangle((self.lowbounds['largerateds'], bottom),
  217. largerate_width, height, facecolor='gold', alpha=0.2,
  218. zorder=0)
  219. ax.add_patch(rect_largerate)
  220. # add example points
  221. ax.scatter(inhib_fbs, np.array(self.largerateds)[inhib_fbi], c=np.array(cmap(coli)),
  222. s=ms, zorder=3)
  223. def _plot_kernel(self, inhib_fb, l, f, col, i, sb_label=True):
  224. """plot schematic kernels
  225. Parameters
  226. -----
  227. inhib_fb: int
  228. widht of inhibitory feedback kernel
  229. l: float
  230. left edge of plot
  231. f: mpl figure
  232. figure
  233. col: tuple
  234. color for inhibitory kernel
  235. i: int
  236. panel index
  237. sb_label: bool
  238. if true plot scalebar
  239. """
  240. # define axis for inhibitory gaussian
  241. b = 5.65 / cmpin / self.figsize[1]
  242. h = 0.2 / cmpin / self.figsize[1]
  243. w = 2 / cmpin / self.figsize[0]
  244. l -= 0.2 / cmpin / self.figsize[0]
  245. zz = 0.1
  246. xlims = (-40, 40)
  247. # compute inhibtory gaussian
  248. x = np.arange(-30, 31, 1)
  249. mu = 0
  250. sigma_c = inhib_fb
  251. amp_c = -0.6
  252. normdist = stats.norm.pdf(x, mu, sigma_c)
  253. y_inhib = normdist * amp_c
  254. # plot inhibitory gaussian
  255. ax = f.add_axes([l, b, w, h])
  256. ax.plot(x,y_inhib, color=col, clip_on=False)
  257. ax.set_ylim((0, zz))
  258. ax.set_xlim(xlims)
  259. plt.axis('off')
  260. # add x axis label
  261. if i == 0:
  262. ax.text(-45, -0.1, 'inh', rotation='vertical', c='r')
  263. # define axis for excitatory gaussian
  264. b = 6 / cmpin / self.figsize[1]
  265. # compute excitatory gaussian
  266. mu = 0
  267. sigma_c = 1
  268. amp_c = 0.3
  269. normdist = stats.norm.pdf(x, mu, sigma_c)
  270. y_ex = normdist * amp_c
  271. # plot excitatory gaussian
  272. ax = f.add_axes([l, b, w, h])
  273. ax.plot(x, y_ex, color='g', clip_on=False)
  274. ax.set_ylim((0, zz))
  275. ax.set_xlim(xlims)
  276. plt.axis('off')
  277. # add x axis label
  278. if i == 0:
  279. ax.text(-45, 0, 'exc', rotation='vertical', c='g')
  280. # add scalebar
  281. x1 = 20
  282. x2 = 30
  283. xdiff = np.abs(x2 - x1)
  284. ax.plot((x1, x2), (0.13, 0.13), color='k', clip_on=False)
  285. if sb_label:
  286. scalebar = '%d$\degree$' % xdiff
  287. ax.text(x1, 0.18, scalebar, color='k', clip_on=False)
  288. # define axis for sum of gaussians
  289. b = 5 / cmpin / self.figsize[1]
  290. # compute sum of two gaussians
  291. y_sum = y_ex + y_inhib
  292. # plot sum of gaussians
  293. ax = f.add_axes([l, b, w, h])
  294. ax.plot(x, y_sum, color='k', clip_on=False)
  295. ax.set_ylim((0, zz))
  296. ax.set_xlim(xlims)
  297. plt.axis('off')
  298. # add x axis label
  299. if i == 0:
  300. ax.text(-45, 0, 'sum', rotation='vertical')
  301. ax.text(-70, 0, 'CT feedback\n kernel ($K_{RC}$)', rotation='vertical')