axes_grid.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. from __future__ import (absolute_import, division, print_function,
  2. unicode_literals)
  3. import six
  4. import matplotlib.axes as maxes
  5. import matplotlib.cbook as cbook
  6. import matplotlib.ticker as ticker
  7. from matplotlib.gridspec import SubplotSpec
  8. from .axes_divider import Size, SubplotDivider, LocatableAxes, Divider
  9. from .colorbar import Colorbar
  10. def _extend_axes_pad(value):
  11. # Check whether a list/tuple/array or scalar has been passed
  12. ret = value
  13. if not hasattr(ret, "__getitem__"):
  14. ret = (value, value)
  15. return ret
  16. def _tick_only(ax, bottom_on, left_on):
  17. bottom_off = not bottom_on
  18. left_off = not left_on
  19. # [l.set_visible(bottom_off) for l in ax.get_xticklabels()]
  20. # [l.set_visible(left_off) for l in ax.get_yticklabels()]
  21. # ax.xaxis.label.set_visible(bottom_off)
  22. # ax.yaxis.label.set_visible(left_off)
  23. ax.axis["bottom"].toggle(ticklabels=bottom_off, label=bottom_off)
  24. ax.axis["left"].toggle(ticklabels=left_off, label=left_off)
  25. class CbarAxesBase(object):
  26. def colorbar(self, mappable, **kwargs):
  27. locator = kwargs.pop("locator", None)
  28. if locator is None:
  29. if "ticks" not in kwargs:
  30. kwargs["ticks"] = ticker.MaxNLocator(5)
  31. if locator is not None:
  32. if "ticks" in kwargs:
  33. raise ValueError("Either *locator* or *ticks* need" +
  34. " to be given, not both")
  35. else:
  36. kwargs["ticks"] = locator
  37. self._hold = True
  38. if self.orientation in ["top", "bottom"]:
  39. orientation = "horizontal"
  40. else:
  41. orientation = "vertical"
  42. cb = Colorbar(self, mappable, orientation=orientation, **kwargs)
  43. self._config_axes()
  44. def on_changed(m):
  45. cb.set_cmap(m.get_cmap())
  46. cb.set_clim(m.get_clim())
  47. cb.update_bruteforce(m)
  48. self.cbid = mappable.callbacksSM.connect('changed', on_changed)
  49. mappable.colorbar = cb
  50. self.locator = cb.cbar_axis.get_major_locator()
  51. return cb
  52. def _config_axes(self):
  53. '''
  54. Make an axes patch and outline.
  55. '''
  56. ax = self
  57. ax.set_navigate(False)
  58. ax.axis[:].toggle(all=False)
  59. b = self._default_label_on
  60. ax.axis[self.orientation].toggle(all=b)
  61. # for axis in ax.axis.values():
  62. # axis.major_ticks.set_visible(False)
  63. # axis.minor_ticks.set_visible(False)
  64. # axis.major_ticklabels.set_visible(False)
  65. # axis.minor_ticklabels.set_visible(False)
  66. # axis.label.set_visible(False)
  67. # axis = ax.axis[self.orientation]
  68. # axis.major_ticks.set_visible(True)
  69. # axis.minor_ticks.set_visible(True)
  70. #axis.major_ticklabels.set_size(
  71. # int(axis.major_ticklabels.get_size()*.9))
  72. #axis.major_tick_pad = 3
  73. # axis.major_ticklabels.set_visible(b)
  74. # axis.minor_ticklabels.set_visible(b)
  75. # axis.label.set_visible(b)
  76. def toggle_label(self, b):
  77. self._default_label_on = b
  78. axis = self.axis[self.orientation]
  79. axis.toggle(ticklabels=b, label=b)
  80. #axis.major_ticklabels.set_visible(b)
  81. #axis.minor_ticklabels.set_visible(b)
  82. #axis.label.set_visible(b)
  83. class CbarAxes(CbarAxesBase, LocatableAxes):
  84. def __init__(self, *kl, **kwargs):
  85. orientation = kwargs.pop("orientation", None)
  86. if orientation is None:
  87. raise ValueError("orientation must be specified")
  88. self.orientation = orientation
  89. self._default_label_on = True
  90. self.locator = None
  91. super(LocatableAxes, self).__init__(*kl, **kwargs)
  92. def cla(self):
  93. super(LocatableAxes, self).cla()
  94. self._config_axes()
  95. class Grid(object):
  96. """
  97. A class that creates a grid of Axes. In matplotlib, the axes
  98. location (and size) is specified in the normalized figure
  99. coordinates. This may not be ideal for images that needs to be
  100. displayed with a given aspect ratio. For example, displaying
  101. images of a same size with some fixed padding between them cannot
  102. be easily done in matplotlib. AxesGrid is used in such case.
  103. """
  104. _defaultLocatableAxesClass = LocatableAxes
  105. def __init__(self, fig,
  106. rect,
  107. nrows_ncols,
  108. ngrids=None,
  109. direction="row",
  110. axes_pad=0.02,
  111. add_all=True,
  112. share_all=False,
  113. share_x=True,
  114. share_y=True,
  115. #aspect=True,
  116. label_mode="L",
  117. axes_class=None,
  118. ):
  119. """
  120. Build an :class:`Grid` instance with a grid nrows*ncols
  121. :class:`~matplotlib.axes.Axes` in
  122. :class:`~matplotlib.figure.Figure` *fig* with
  123. *rect=[left, bottom, width, height]* (in
  124. :class:`~matplotlib.figure.Figure` coordinates) or
  125. the subplot position code (e.g., "121").
  126. Optional keyword arguments:
  127. ================ ======== =========================================
  128. Keyword Default Description
  129. ================ ======== =========================================
  130. direction "row" [ "row" | "column" ]
  131. axes_pad 0.02 float| pad between axes given in inches
  132. or tuple-like of floats,
  133. (horizontal padding, vertical padding)
  134. add_all True bool
  135. share_all False bool
  136. share_x True bool
  137. share_y True bool
  138. label_mode "L" [ "L" | "1" | "all" ]
  139. axes_class None a type object which must be a subclass
  140. of :class:`~matplotlib.axes.Axes`
  141. ================ ======== =========================================
  142. """
  143. self._nrows, self._ncols = nrows_ncols
  144. if ngrids is None:
  145. ngrids = self._nrows * self._ncols
  146. else:
  147. if (ngrids > self._nrows * self._ncols) or (ngrids <= 0):
  148. raise Exception("")
  149. self.ngrids = ngrids
  150. self._init_axes_pad(axes_pad)
  151. if direction not in ["column", "row"]:
  152. raise Exception("")
  153. self._direction = direction
  154. if axes_class is None:
  155. axes_class = self._defaultLocatableAxesClass
  156. axes_class_args = {}
  157. else:
  158. if (type(axes_class)) == type and \
  159. issubclass(axes_class,
  160. self._defaultLocatableAxesClass.Axes):
  161. axes_class_args = {}
  162. else:
  163. axes_class, axes_class_args = axes_class
  164. self.axes_all = []
  165. self.axes_column = [[] for _ in range(self._ncols)]
  166. self.axes_row = [[] for _ in range(self._nrows)]
  167. h = []
  168. v = []
  169. if isinstance(rect, six.string_types) or cbook.is_numlike(rect):
  170. self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v,
  171. aspect=False)
  172. elif isinstance(rect, SubplotSpec):
  173. self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v,
  174. aspect=False)
  175. elif len(rect) == 3:
  176. kw = dict(horizontal=h, vertical=v, aspect=False)
  177. self._divider = SubplotDivider(fig, *rect, **kw)
  178. elif len(rect) == 4:
  179. self._divider = Divider(fig, rect, horizontal=h, vertical=v,
  180. aspect=False)
  181. else:
  182. raise Exception("")
  183. rect = self._divider.get_position()
  184. # reference axes
  185. self._column_refax = [None for _ in range(self._ncols)]
  186. self._row_refax = [None for _ in range(self._nrows)]
  187. self._refax = None
  188. for i in range(self.ngrids):
  189. col, row = self._get_col_row(i)
  190. if share_all:
  191. sharex = self._refax
  192. sharey = self._refax
  193. else:
  194. if share_x:
  195. sharex = self._column_refax[col]
  196. else:
  197. sharex = None
  198. if share_y:
  199. sharey = self._row_refax[row]
  200. else:
  201. sharey = None
  202. ax = axes_class(fig, rect, sharex=sharex, sharey=sharey,
  203. **axes_class_args)
  204. if share_all:
  205. if self._refax is None:
  206. self._refax = ax
  207. else:
  208. if sharex is None:
  209. self._column_refax[col] = ax
  210. if sharey is None:
  211. self._row_refax[row] = ax
  212. self.axes_all.append(ax)
  213. self.axes_column[col].append(ax)
  214. self.axes_row[row].append(ax)
  215. self.axes_llc = self.axes_column[0][-1]
  216. self._update_locators()
  217. if add_all:
  218. for ax in self.axes_all:
  219. fig.add_axes(ax)
  220. self.set_label_mode(label_mode)
  221. def _init_axes_pad(self, axes_pad):
  222. axes_pad = _extend_axes_pad(axes_pad)
  223. self._axes_pad = axes_pad
  224. self._horiz_pad_size = Size.Fixed(axes_pad[0])
  225. self._vert_pad_size = Size.Fixed(axes_pad[1])
  226. def _update_locators(self):
  227. h = []
  228. h_ax_pos = []
  229. for _ in self._column_refax:
  230. #if h: h.append(Size.Fixed(self._axes_pad))
  231. if h:
  232. h.append(self._horiz_pad_size)
  233. h_ax_pos.append(len(h))
  234. sz = Size.Scaled(1)
  235. h.append(sz)
  236. v = []
  237. v_ax_pos = []
  238. for _ in self._row_refax[::-1]:
  239. #if v: v.append(Size.Fixed(self._axes_pad))
  240. if v:
  241. v.append(self._vert_pad_size)
  242. v_ax_pos.append(len(v))
  243. sz = Size.Scaled(1)
  244. v.append(sz)
  245. for i in range(self.ngrids):
  246. col, row = self._get_col_row(i)
  247. locator = self._divider.new_locator(nx=h_ax_pos[col],
  248. ny=v_ax_pos[self._nrows - 1 - row])
  249. self.axes_all[i].set_axes_locator(locator)
  250. self._divider.set_horizontal(h)
  251. self._divider.set_vertical(v)
  252. def _get_col_row(self, n):
  253. if self._direction == "column":
  254. col, row = divmod(n, self._nrows)
  255. else:
  256. row, col = divmod(n, self._ncols)
  257. return col, row
  258. # Good to propagate __len__ if we have __getitem__
  259. def __len__(self):
  260. return len(self.axes_all)
  261. def __getitem__(self, i):
  262. return self.axes_all[i]
  263. def get_geometry(self):
  264. """
  265. get geometry of the grid. Returns a tuple of two integer,
  266. representing number of rows and number of columns.
  267. """
  268. return self._nrows, self._ncols
  269. def set_axes_pad(self, axes_pad):
  270. "set axes_pad"
  271. self._axes_pad = axes_pad
  272. # These two lines actually differ from ones in _init_axes_pad
  273. self._horiz_pad_size.fixed_size = axes_pad[0]
  274. self._vert_pad_size.fixed_size = axes_pad[1]
  275. def get_axes_pad(self):
  276. """
  277. get axes_pad
  278. Returns
  279. -------
  280. tuple
  281. Padding in inches, (horizontal pad, vertical pad)
  282. """
  283. return self._axes_pad
  284. def set_aspect(self, aspect):
  285. "set aspect"
  286. self._divider.set_aspect(aspect)
  287. def get_aspect(self):
  288. "get aspect"
  289. return self._divider.get_aspect()
  290. def set_label_mode(self, mode):
  291. "set label_mode"
  292. if mode == "all":
  293. for ax in self.axes_all:
  294. _tick_only(ax, False, False)
  295. elif mode == "L":
  296. # left-most axes
  297. for ax in self.axes_column[0][:-1]:
  298. _tick_only(ax, bottom_on=True, left_on=False)
  299. # lower-left axes
  300. ax = self.axes_column[0][-1]
  301. _tick_only(ax, bottom_on=False, left_on=False)
  302. for col in self.axes_column[1:]:
  303. # axes with no labels
  304. for ax in col[:-1]:
  305. _tick_only(ax, bottom_on=True, left_on=True)
  306. # bottom
  307. ax = col[-1]
  308. _tick_only(ax, bottom_on=False, left_on=True)
  309. elif mode == "1":
  310. for ax in self.axes_all:
  311. _tick_only(ax, bottom_on=True, left_on=True)
  312. ax = self.axes_llc
  313. _tick_only(ax, bottom_on=False, left_on=False)
  314. def get_divider(self):
  315. return self._divider
  316. def set_axes_locator(self, locator):
  317. self._divider.set_locator(locator)
  318. def get_axes_locator(self):
  319. return self._divider.get_locator()
  320. def get_vsize_hsize(self):
  321. return self._divider.get_vsize_hsize()
  322. # from axes_size import AddList
  323. # vsize = AddList(self._divider.get_vertical())
  324. # hsize = AddList(self._divider.get_horizontal())
  325. # return vsize, hsize
  326. class ImageGrid(Grid):
  327. """
  328. A class that creates a grid of Axes. In matplotlib, the axes
  329. location (and size) is specified in the normalized figure
  330. coordinates. This may not be ideal for images that needs to be
  331. displayed with a given aspect ratio. For example, displaying
  332. images of a same size with some fixed padding between them cannot
  333. be easily done in matplotlib. ImageGrid is used in such case.
  334. """
  335. _defaultCbarAxesClass = CbarAxes
  336. def __init__(self, fig,
  337. rect,
  338. nrows_ncols,
  339. ngrids=None,
  340. direction="row",
  341. axes_pad=0.02,
  342. add_all=True,
  343. share_all=False,
  344. aspect=True,
  345. label_mode="L",
  346. cbar_mode=None,
  347. cbar_location="right",
  348. cbar_pad=None,
  349. cbar_size="5%",
  350. cbar_set_cax=True,
  351. axes_class=None,
  352. ):
  353. """
  354. Build an :class:`ImageGrid` instance with a grid nrows*ncols
  355. :class:`~matplotlib.axes.Axes` in
  356. :class:`~matplotlib.figure.Figure` *fig* with
  357. *rect=[left, bottom, width, height]* (in
  358. :class:`~matplotlib.figure.Figure` coordinates) or
  359. the subplot position code (e.g., "121").
  360. Optional keyword arguments:
  361. ================ ======== =========================================
  362. Keyword Default Description
  363. ================ ======== =========================================
  364. direction "row" [ "row" | "column" ]
  365. axes_pad 0.02 float| pad between axes given in inches
  366. or tuple-like of floats,
  367. (horizontal padding, vertical padding)
  368. add_all True bool
  369. share_all False bool
  370. aspect True bool
  371. label_mode "L" [ "L" | "1" | "all" ]
  372. cbar_mode None [ "each" | "single" | "edge" ]
  373. cbar_location "right" [ "left" | "right" | "bottom" | "top" ]
  374. cbar_pad None
  375. cbar_size "5%"
  376. cbar_set_cax True bool
  377. axes_class None a type object which must be a subclass
  378. of axes_grid's subclass of
  379. :class:`~matplotlib.axes.Axes`
  380. ================ ======== =========================================
  381. *cbar_set_cax* : if True, each axes in the grid has a cax
  382. attribute that is bind to associated cbar_axes.
  383. """
  384. self._nrows, self._ncols = nrows_ncols
  385. if ngrids is None:
  386. ngrids = self._nrows * self._ncols
  387. else:
  388. if not 0 < ngrids <= self._nrows * self._ncols:
  389. raise Exception
  390. self.ngrids = ngrids
  391. axes_pad = _extend_axes_pad(axes_pad)
  392. self._axes_pad = axes_pad
  393. self._colorbar_mode = cbar_mode
  394. self._colorbar_location = cbar_location
  395. if cbar_pad is None:
  396. # horizontal or vertical arrangement?
  397. if cbar_location in ("left", "right"):
  398. self._colorbar_pad = axes_pad[0]
  399. else:
  400. self._colorbar_pad = axes_pad[1]
  401. else:
  402. self._colorbar_pad = cbar_pad
  403. self._colorbar_size = cbar_size
  404. self._init_axes_pad(axes_pad)
  405. if direction not in ["column", "row"]:
  406. raise Exception("")
  407. self._direction = direction
  408. if axes_class is None:
  409. axes_class = self._defaultLocatableAxesClass
  410. axes_class_args = {}
  411. else:
  412. if isinstance(axes_class, maxes.Axes):
  413. axes_class_args = {}
  414. else:
  415. axes_class, axes_class_args = axes_class
  416. self.axes_all = []
  417. self.axes_column = [[] for _ in range(self._ncols)]
  418. self.axes_row = [[] for _ in range(self._nrows)]
  419. self.cbar_axes = []
  420. h = []
  421. v = []
  422. if isinstance(rect, six.string_types) or cbook.is_numlike(rect):
  423. self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v,
  424. aspect=aspect)
  425. elif isinstance(rect, SubplotSpec):
  426. self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v,
  427. aspect=aspect)
  428. elif len(rect) == 3:
  429. kw = dict(horizontal=h, vertical=v, aspect=aspect)
  430. self._divider = SubplotDivider(fig, *rect, **kw)
  431. elif len(rect) == 4:
  432. self._divider = Divider(fig, rect, horizontal=h, vertical=v,
  433. aspect=aspect)
  434. else:
  435. raise Exception("")
  436. rect = self._divider.get_position()
  437. # reference axes
  438. self._column_refax = [None for _ in range(self._ncols)]
  439. self._row_refax = [None for _ in range(self._nrows)]
  440. self._refax = None
  441. for i in range(self.ngrids):
  442. col, row = self._get_col_row(i)
  443. if share_all:
  444. if self.axes_all:
  445. sharex = self.axes_all[0]
  446. sharey = self.axes_all[0]
  447. else:
  448. sharex = None
  449. sharey = None
  450. else:
  451. sharex = self._column_refax[col]
  452. sharey = self._row_refax[row]
  453. ax = axes_class(fig, rect, sharex=sharex, sharey=sharey,
  454. **axes_class_args)
  455. self.axes_all.append(ax)
  456. self.axes_column[col].append(ax)
  457. self.axes_row[row].append(ax)
  458. if share_all:
  459. if self._refax is None:
  460. self._refax = ax
  461. if sharex is None:
  462. self._column_refax[col] = ax
  463. if sharey is None:
  464. self._row_refax[row] = ax
  465. cax = self._defaultCbarAxesClass(fig, rect,
  466. orientation=self._colorbar_location)
  467. self.cbar_axes.append(cax)
  468. self.axes_llc = self.axes_column[0][-1]
  469. self._update_locators()
  470. if add_all:
  471. for ax in self.axes_all+self.cbar_axes:
  472. fig.add_axes(ax)
  473. if cbar_set_cax:
  474. if self._colorbar_mode == "single":
  475. for ax in self.axes_all:
  476. ax.cax = self.cbar_axes[0]
  477. elif self._colorbar_mode == "edge":
  478. for index, ax in enumerate(self.axes_all):
  479. col, row = self._get_col_row(index)
  480. if self._colorbar_location in ("left", "right"):
  481. ax.cax = self.cbar_axes[row]
  482. else:
  483. ax.cax = self.cbar_axes[col]
  484. else:
  485. for ax, cax in zip(self.axes_all, self.cbar_axes):
  486. ax.cax = cax
  487. self.set_label_mode(label_mode)
  488. def _update_locators(self):
  489. h = []
  490. v = []
  491. h_ax_pos = []
  492. h_cb_pos = []
  493. if (self._colorbar_mode == "single" and
  494. self._colorbar_location in ('left', 'bottom')):
  495. if self._colorbar_location == "left":
  496. #sz = Size.Fraction(Size.AxesX(self.axes_llc), self._nrows)
  497. sz = Size.Fraction(self._nrows, Size.AxesX(self.axes_llc))
  498. h.append(Size.from_any(self._colorbar_size, sz))
  499. h.append(Size.from_any(self._colorbar_pad, sz))
  500. locator = self._divider.new_locator(nx=0, ny=0, ny1=-1)
  501. elif self._colorbar_location == "bottom":
  502. #sz = Size.Fraction(Size.AxesY(self.axes_llc), self._ncols)
  503. sz = Size.Fraction(self._ncols, Size.AxesY(self.axes_llc))
  504. v.append(Size.from_any(self._colorbar_size, sz))
  505. v.append(Size.from_any(self._colorbar_pad, sz))
  506. locator = self._divider.new_locator(nx=0, nx1=-1, ny=0)
  507. for i in range(self.ngrids):
  508. self.cbar_axes[i].set_visible(False)
  509. self.cbar_axes[0].set_axes_locator(locator)
  510. self.cbar_axes[0].set_visible(True)
  511. for col, ax in enumerate(self.axes_row[0]):
  512. if h:
  513. h.append(self._horiz_pad_size) # Size.Fixed(self._axes_pad))
  514. if ax:
  515. sz = Size.AxesX(ax, aspect="axes", ref_ax=self.axes_all[0])
  516. else:
  517. sz = Size.AxesX(self.axes_all[0],
  518. aspect="axes", ref_ax=self.axes_all[0])
  519. if (self._colorbar_mode == "each" or
  520. (self._colorbar_mode == 'edge' and
  521. col == 0)) and self._colorbar_location == "left":
  522. h_cb_pos.append(len(h))
  523. h.append(Size.from_any(self._colorbar_size, sz))
  524. h.append(Size.from_any(self._colorbar_pad, sz))
  525. h_ax_pos.append(len(h))
  526. h.append(sz)
  527. if ((self._colorbar_mode == "each" or
  528. (self._colorbar_mode == 'edge' and
  529. col == self._ncols - 1)) and
  530. self._colorbar_location == "right"):
  531. h.append(Size.from_any(self._colorbar_pad, sz))
  532. h_cb_pos.append(len(h))
  533. h.append(Size.from_any(self._colorbar_size, sz))
  534. v_ax_pos = []
  535. v_cb_pos = []
  536. for row, ax in enumerate(self.axes_column[0][::-1]):
  537. if v:
  538. v.append(self._vert_pad_size) # Size.Fixed(self._axes_pad))
  539. if ax:
  540. sz = Size.AxesY(ax, aspect="axes", ref_ax=self.axes_all[0])
  541. else:
  542. sz = Size.AxesY(self.axes_all[0],
  543. aspect="axes", ref_ax=self.axes_all[0])
  544. if (self._colorbar_mode == "each" or
  545. (self._colorbar_mode == 'edge' and
  546. row == 0)) and self._colorbar_location == "bottom":
  547. v_cb_pos.append(len(v))
  548. v.append(Size.from_any(self._colorbar_size, sz))
  549. v.append(Size.from_any(self._colorbar_pad, sz))
  550. v_ax_pos.append(len(v))
  551. v.append(sz)
  552. if ((self._colorbar_mode == "each" or
  553. (self._colorbar_mode == 'edge' and
  554. row == self._nrows - 1)) and
  555. self._colorbar_location == "top"):
  556. v.append(Size.from_any(self._colorbar_pad, sz))
  557. v_cb_pos.append(len(v))
  558. v.append(Size.from_any(self._colorbar_size, sz))
  559. for i in range(self.ngrids):
  560. col, row = self._get_col_row(i)
  561. #locator = self._divider.new_locator(nx=4*col,
  562. # ny=2*(self._nrows - row - 1))
  563. locator = self._divider.new_locator(nx=h_ax_pos[col],
  564. ny=v_ax_pos[self._nrows-1-row])
  565. self.axes_all[i].set_axes_locator(locator)
  566. if self._colorbar_mode == "each":
  567. if self._colorbar_location in ("right", "left"):
  568. locator = self._divider.new_locator(
  569. nx=h_cb_pos[col], ny=v_ax_pos[self._nrows - 1 - row])
  570. elif self._colorbar_location in ("top", "bottom"):
  571. locator = self._divider.new_locator(
  572. nx=h_ax_pos[col], ny=v_cb_pos[self._nrows - 1 - row])
  573. self.cbar_axes[i].set_axes_locator(locator)
  574. elif self._colorbar_mode == 'edge':
  575. if ((self._colorbar_location == 'left' and col == 0) or
  576. (self._colorbar_location == 'right'
  577. and col == self._ncols-1)):
  578. locator = self._divider.new_locator(
  579. nx=h_cb_pos[0], ny=v_ax_pos[self._nrows -1 - row])
  580. self.cbar_axes[row].set_axes_locator(locator)
  581. elif ((self._colorbar_location == 'bottom' and
  582. row == self._nrows - 1) or
  583. (self._colorbar_location == 'top' and row == 0)):
  584. locator = self._divider.new_locator(nx=h_ax_pos[col],
  585. ny=v_cb_pos[0])
  586. self.cbar_axes[col].set_axes_locator(locator)
  587. if self._colorbar_mode == "single":
  588. if self._colorbar_location == "right":
  589. #sz = Size.Fraction(Size.AxesX(self.axes_llc), self._nrows)
  590. sz = Size.Fraction(self._nrows, Size.AxesX(self.axes_llc))
  591. h.append(Size.from_any(self._colorbar_pad, sz))
  592. h.append(Size.from_any(self._colorbar_size, sz))
  593. locator = self._divider.new_locator(nx=-2, ny=0, ny1=-1)
  594. elif self._colorbar_location == "top":
  595. #sz = Size.Fraction(Size.AxesY(self.axes_llc), self._ncols)
  596. sz = Size.Fraction(self._ncols, Size.AxesY(self.axes_llc))
  597. v.append(Size.from_any(self._colorbar_pad, sz))
  598. v.append(Size.from_any(self._colorbar_size, sz))
  599. locator = self._divider.new_locator(nx=0, nx1=-1, ny=-2)
  600. if self._colorbar_location in ("right", "top"):
  601. for i in range(self.ngrids):
  602. self.cbar_axes[i].set_visible(False)
  603. self.cbar_axes[0].set_axes_locator(locator)
  604. self.cbar_axes[0].set_visible(True)
  605. elif self._colorbar_mode == "each":
  606. for i in range(self.ngrids):
  607. self.cbar_axes[i].set_visible(True)
  608. elif self._colorbar_mode == "edge":
  609. if self._colorbar_location in ('right', 'left'):
  610. count = self._nrows
  611. else:
  612. count = self._ncols
  613. for i in range(count):
  614. self.cbar_axes[i].set_visible(True)
  615. for j in range(i + 1, self.ngrids):
  616. self.cbar_axes[j].set_visible(False)
  617. else:
  618. for i in range(self.ngrids):
  619. self.cbar_axes[i].set_visible(False)
  620. self.cbar_axes[i].set_position([1., 1., 0.001, 0.001],
  621. which="active")
  622. self._divider.set_horizontal(h)
  623. self._divider.set_vertical(v)
  624. AxesGrid = ImageGrid