summaryrefslogtreecommitdiffstats
path: root/contrib/python/matplotlib/py2/mpl_toolkits
diff options
context:
space:
mode:
authormaxim-yurchuk <[email protected]>2025-02-11 13:26:52 +0300
committermaxim-yurchuk <[email protected]>2025-02-11 13:57:59 +0300
commitf895bba65827952ed934b2b46f9a45e30a191fd2 (patch)
tree03260c906d9ec41cdc03e2a496b15d407459cec0 /contrib/python/matplotlib/py2/mpl_toolkits
parent5f7060466f7b9707818c2091e1a25c14f33c3474 (diff)
Remove deps on pandas
<https://github.com/ydb-platform/ydb/pull/14418> <https://github.com/ydb-platform/ydb/pull/14419> \-- аналогичные правки в gh Хочу залить в обход синка, чтобы посмотреть удалится ли pandas в нашей gh репе через piglet commit_hash:abca127aa37d4dbb94b07e1e18cdb8eb5b711860
Diffstat (limited to 'contrib/python/matplotlib/py2/mpl_toolkits')
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/__init__.py4
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/ChangeLog13
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/__init__.py15
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/anchored_artists.py9
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/angle_helper.py4
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_divider.py8
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_grid.py30
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_rgb.py11
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_size.py4
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axis_artist.py4
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axisline_style.py4
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axislines.py4
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/clip_path.py4
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/colorbar.py5
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/floating_axes.py4
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/grid_finder.py4
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/grid_helper_curvelinear.py4
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/inset_locator.py7
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/parasite_axes.py18
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/__init__.py12
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/anchored_artists.py376
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_divider.py975
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_grid.py771
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_rgb.py228
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_size.py323
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/colorbar.py836
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/inset_locator.py659
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/mpl_axes.py154
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/parasite_axes.py486
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axisartist/__init__.py26
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axisartist/angle_helper.py416
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axes_divider.py9
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axes_grid.py30
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axes_rgb.py11
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axis_artist.py1527
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axisline_style.py168
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axislines.py828
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axisartist/clip_path.py135
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axisartist/floating_axes.py544
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axisartist/grid_finder.py340
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axisartist/grid_helper_curvelinear.py475
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/axisartist/parasite_axes.py18
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/__init__.py6
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/art3d.py774
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/axes3d.py2958
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/axis3d.py484
-rw-r--r--contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/proj3d.py203
47 files changed, 0 insertions, 13928 deletions
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/__init__.py b/contrib/python/matplotlib/py2/mpl_toolkits/__init__.py
deleted file mode 100644
index 8d9942e652d..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-try:
- __import__('pkg_resources').declare_namespace(__name__)
-except ImportError:
- pass # must not have setuptools
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/ChangeLog b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/ChangeLog
deleted file mode 100644
index 79cc01cfdf4..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/ChangeLog
+++ /dev/null
@@ -1,13 +0,0 @@
-2009-06-01 Jae-Joon Lee <[email protected]>
-
- * axislines.py (Axes.toggle_axisline): fix broken spine support.
- (AxisArtistHelper): Initial support for curvelinear grid and ticks.
-
-2009-05-04 Jae-Joon Lee <[email protected]>
-
- * inset_locator.py (inset_axes, zoomed_inset_axes): axes_class support
-
- * axislines.py : Better support for tick (tick label) color
- handling
- (Axes.get_children): fix typo
-
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/__init__.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/__init__.py
deleted file mode 100644
index c10e89bd62b..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/__init__.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from . import axes_size as Size
-from .axes_divider import Divider, SubplotDivider, LocatableAxes, \
- make_axes_locatable
-from .axes_grid import Grid, ImageGrid, AxesGrid
-#from axes_divider import make_axes_locatable
-from matplotlib.cbook import warn_deprecated
-warn_deprecated(since='2.1',
- name='mpl_toolkits.axes_grid',
- alternative='mpl_toolkits.axes_grid1 and'
- ' mpl_toolkits.axisartist provies the same'
- ' functionality',
- obj_type='module')
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/anchored_artists.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/anchored_artists.py
deleted file mode 100644
index 14b661497d8..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/anchored_artists.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from matplotlib.offsetbox import AnchoredOffsetbox, AuxTransformBox, VPacker,\
- TextArea, AnchoredText, DrawingArea, AnnotationBbox
-
-from mpl_toolkits.axes_grid1.anchored_artists import \
- AnchoredDrawingArea, AnchoredAuxTransformBox, \
- AnchoredEllipse, AnchoredSizeBar
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/angle_helper.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/angle_helper.py
deleted file mode 100644
index f0f877d9136..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/angle_helper.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from mpl_toolkits.axisartist.angle_helper import *
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_divider.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_divider.py
deleted file mode 100644
index 25694ecf5ec..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_divider.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from mpl_toolkits.axes_grid1.axes_divider import Divider, AxesLocator, SubplotDivider, \
- AxesDivider, locatable_axes_factory, make_axes_locatable
-
-from mpl_toolkits.axes_grid.axislines import Axes
-LocatableAxes = locatable_axes_factory(Axes)
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_grid.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_grid.py
deleted file mode 100644
index 58212ac89c4..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_grid.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import mpl_toolkits.axes_grid1.axes_grid as axes_grid_orig
-from .axes_divider import LocatableAxes
-
-class CbarAxes(axes_grid_orig.CbarAxesBase, LocatableAxes):
- def __init__(self, *kl, **kwargs):
- orientation=kwargs.pop("orientation", None)
- if orientation is None:
- raise ValueError("orientation must be specified")
- self.orientation = orientation
- self._default_label_on = False
- self.locator = None
-
- super(LocatableAxes, self).__init__(*kl, **kwargs)
-
- def cla(self):
- super(LocatableAxes, self).cla()
- self._config_axes()
-
-
-class Grid(axes_grid_orig.Grid):
- _defaultLocatableAxesClass = LocatableAxes
-
-class ImageGrid(axes_grid_orig.ImageGrid):
- _defaultLocatableAxesClass = LocatableAxes
- _defaultCbarAxesClass = CbarAxes
-
-AxesGrid = ImageGrid
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_rgb.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_rgb.py
deleted file mode 100644
index bfd4bb98ad7..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_rgb.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-#from mpl_toolkits.axes_grid1.axes_rgb import *
-from mpl_toolkits.axes_grid1.axes_rgb import make_rgb_axes, imshow_rgb, RGBAxesBase
-
-#import mpl_toolkits.axes_grid1.axes_rgb as axes_rgb_orig
-from .axislines import Axes
-
-class RGBAxes(RGBAxesBase):
- _defaultAxesClass = Axes
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_size.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_size.py
deleted file mode 100644
index 998b5e3c871..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_size.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from mpl_toolkits.axes_grid1.axes_size import *
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axis_artist.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axis_artist.py
deleted file mode 100644
index 92f0538ceba..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axis_artist.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from mpl_toolkits.axisartist.axis_artist import *
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axisline_style.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axisline_style.py
deleted file mode 100644
index 2eef3b8b344..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axisline_style.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from mpl_toolkits.axisartist.axisline_style import *
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axislines.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axislines.py
deleted file mode 100644
index 9653aa17020..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axislines.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from mpl_toolkits.axisartist.axislines import *
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/clip_path.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/clip_path.py
deleted file mode 100644
index bafe568fb1a..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/clip_path.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from mpl_toolkits.axisartist.clip_path import *
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/colorbar.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/colorbar.py
deleted file mode 100644
index cc5c252da89..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/colorbar.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from mpl_toolkits.axes_grid1.colorbar import (
- make_axes_kw_doc, colormap_kw_doc, colorbar_doc,
- CbarAxesLocator, ColorbarBase, Colorbar,
- make_axes, colorbar
-)
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/floating_axes.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/floating_axes.py
deleted file mode 100644
index 3f30d57c3a8..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/floating_axes.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from mpl_toolkits.axisartist.floating_axes import *
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/grid_finder.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/grid_finder.py
deleted file mode 100644
index ffa3db76cf8..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/grid_finder.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from mpl_toolkits.axisartist.grid_finder import *
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/grid_helper_curvelinear.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/grid_helper_curvelinear.py
deleted file mode 100644
index 325ddd6af22..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/grid_helper_curvelinear.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from mpl_toolkits.axisartist.grid_helper_curvelinear import *
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/inset_locator.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/inset_locator.py
deleted file mode 100644
index a9ed77beda3..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/inset_locator.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from mpl_toolkits.axes_grid1.inset_locator import InsetPosition, \
- AnchoredSizeLocator, \
- AnchoredZoomLocator, BboxPatch, BboxConnector, BboxConnectorPatch, \
- inset_axes, zoomed_inset_axes, mark_inset
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/parasite_axes.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/parasite_axes.py
deleted file mode 100644
index cad56e43a22..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/parasite_axes.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from mpl_toolkits.axes_grid1.parasite_axes import (
- host_axes_class_factory, parasite_axes_class_factory,
- parasite_axes_auxtrans_class_factory, subplot_class_factory)
-
-from .axislines import Axes
-
-
-ParasiteAxes = parasite_axes_class_factory(Axes)
-
-ParasiteAxesAuxTrans = \
- parasite_axes_auxtrans_class_factory(axes_class=ParasiteAxes)
-
-HostAxes = host_axes_class_factory(axes_class=Axes)
-
-SubplotHost = subplot_class_factory(HostAxes)
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/__init__.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/__init__.py
deleted file mode 100644
index 3e225ba9f0c..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/__init__.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-
-from . import axes_size as Size
-from .axes_divider import Divider, SubplotDivider, LocatableAxes, \
- make_axes_locatable
-from .axes_grid import Grid, ImageGrid, AxesGrid
-#from axes_divider import make_axes_locatable
-
-from .parasite_axes import host_subplot, host_axes
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/anchored_artists.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/anchored_artists.py
deleted file mode 100644
index 5b492858e8d..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/anchored_artists.py
+++ /dev/null
@@ -1,376 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-import six
-
-from matplotlib import docstring
-from matplotlib.offsetbox import (AnchoredOffsetbox, AuxTransformBox,
- DrawingArea, TextArea, VPacker)
-from matplotlib.patches import Rectangle, Ellipse
-
-
-__all__ = ['AnchoredDrawingArea', 'AnchoredAuxTransformBox',
- 'AnchoredEllipse', 'AnchoredSizeBar']
-
-
-class AnchoredDrawingArea(AnchoredOffsetbox):
- @docstring.dedent
- def __init__(self, width, height, xdescent, ydescent,
- loc, pad=0.4, borderpad=0.5, prop=None, frameon=True,
- **kwargs):
- """
- An anchored container with a fixed size and fillable DrawingArea.
-
- Artists added to the *drawing_area* will have their coordinates
- interpreted as pixels. Any transformations set on the artists will be
- overridden.
-
- Parameters
- ----------
- width, height : int or float
- width and height of the container, in pixels.
-
- xdescent, ydescent : int or float
- descent of the container in the x- and y- direction, in pixels.
-
- loc : int
- Location of this artist. Valid location codes are::
-
- 'upper right' : 1,
- 'upper left' : 2,
- 'lower left' : 3,
- 'lower right' : 4,
- 'right' : 5,
- 'center left' : 6,
- 'center right' : 7,
- 'lower center' : 8,
- 'upper center' : 9,
- 'center' : 10
-
- pad : int or float, optional
- Padding around the child objects, in fraction of the font
- size. Defaults to 0.4.
-
- borderpad : int or float, optional
- Border padding, in fraction of the font size.
- Defaults to 0.5.
-
- prop : `matplotlib.font_manager.FontProperties`, optional
- Font property used as a reference for paddings.
-
- frameon : bool, optional
- If True, draw a box around this artists. Defaults to True.
-
- **kwargs :
- Keyworded arguments to pass to
- :class:`matplotlib.offsetbox.AnchoredOffsetbox`.
-
- Attributes
- ----------
- drawing_area : `matplotlib.offsetbox.DrawingArea`
- A container for artists to display.
-
- Examples
- --------
- To display blue and red circles of different sizes in the upper right
- of an axes *ax*:
-
- >>> ada = AnchoredDrawingArea(20, 20, 0, 0, loc=1, frameon=False)
- >>> ada.drawing_area.add_artist(Circle((10, 10), 10, fc="b"))
- >>> ada.drawing_area.add_artist(Circle((30, 10), 5, fc="r"))
- >>> ax.add_artist(ada)
- """
- self.da = DrawingArea(width, height, xdescent, ydescent)
- self.drawing_area = self.da
-
- super(AnchoredDrawingArea, self).__init__(
- loc, pad=pad, borderpad=borderpad, child=self.da, prop=None,
- frameon=frameon, **kwargs
- )
-
-
-class AnchoredAuxTransformBox(AnchoredOffsetbox):
- @docstring.dedent
- def __init__(self, transform, loc,
- pad=0.4, borderpad=0.5, prop=None, frameon=True, **kwargs):
- """
- An anchored container with transformed coordinates.
-
- Artists added to the *drawing_area* are scaled according to the
- coordinates of the transformation used. The dimensions of this artist
- will scale to contain the artists added.
-
- Parameters
- ----------
- transform : `matplotlib.transforms.Transform`
- The transformation object for the coordinate system in use, i.e.,
- :attr:`matplotlib.axes.Axes.transData`.
-
- loc : int
- Location of this artist. Valid location codes are::
-
- 'upper right' : 1,
- 'upper left' : 2,
- 'lower left' : 3,
- 'lower right' : 4,
- 'right' : 5,
- 'center left' : 6,
- 'center right' : 7,
- 'lower center' : 8,
- 'upper center' : 9,
- 'center' : 10
-
- pad : int or float, optional
- Padding around the child objects, in fraction of the font
- size. Defaults to 0.4.
-
- borderpad : int or float, optional
- Border padding, in fraction of the font size.
- Defaults to 0.5.
-
- prop : `matplotlib.font_manager.FontProperties`, optional
- Font property used as a reference for paddings.
-
- frameon : bool, optional
- If True, draw a box around this artists. Defaults to True.
-
- **kwargs :
- Keyworded arguments to pass to
- :class:`matplotlib.offsetbox.AnchoredOffsetbox`.
-
- Attributes
- ----------
- drawing_area : `matplotlib.offsetbox.AuxTransformBox`
- A container for artists to display.
-
- Examples
- --------
- To display an ellipse in the upper left, with a width of 0.1 and
- height of 0.4 in data coordinates:
-
- >>> box = AnchoredAuxTransformBox(ax.transData, loc=2)
- >>> el = Ellipse((0,0), width=0.1, height=0.4, angle=30)
- >>> box.drawing_area.add_artist(el)
- >>> ax.add_artist(box)
- """
- self.drawing_area = AuxTransformBox(transform)
-
- AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad,
- child=self.drawing_area,
- prop=prop,
- frameon=frameon,
- **kwargs)
-
-
-class AnchoredEllipse(AnchoredOffsetbox):
- @docstring.dedent
- def __init__(self, transform, width, height, angle, loc,
- pad=0.1, borderpad=0.1, prop=None, frameon=True, **kwargs):
- """
- Draw an anchored ellipse of a given size.
-
- Parameters
- ----------
- transform : `matplotlib.transforms.Transform`
- The transformation object for the coordinate system in use, i.e.,
- :attr:`matplotlib.axes.Axes.transData`.
-
- width, height : int or float
- Width and height of the ellipse, given in coordinates of
- *transform*.
-
- angle : int or float
- Rotation of the ellipse, in degrees, anti-clockwise.
-
- loc : int
- Location of this size bar. Valid location codes are::
-
- 'upper right' : 1,
- 'upper left' : 2,
- 'lower left' : 3,
- 'lower right' : 4,
- 'right' : 5,
- 'center left' : 6,
- 'center right' : 7,
- 'lower center' : 8,
- 'upper center' : 9,
- 'center' : 10
-
- pad : int or float, optional
- Padding around the ellipse, in fraction of the font size. Defaults
- to 0.1.
-
- borderpad : int or float, optional
- Border padding, in fraction of the font size. Defaults to 0.1.
-
- frameon : bool, optional
- If True, draw a box around the ellipse. Defaults to True.
-
- prop : `matplotlib.font_manager.FontProperties`, optional
- Font property used as a reference for paddings.
-
- **kwargs :
- Keyworded arguments to pass to
- :class:`matplotlib.offsetbox.AnchoredOffsetbox`.
-
- Attributes
- ----------
- ellipse : `matplotlib.patches.Ellipse`
- Ellipse patch drawn.
- """
- self._box = AuxTransformBox(transform)
- self.ellipse = Ellipse((0, 0), width, height, angle)
- self._box.add_artist(self.ellipse)
-
- AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad,
- child=self._box,
- prop=prop,
- frameon=frameon, **kwargs)
-
-
-class AnchoredSizeBar(AnchoredOffsetbox):
- @docstring.dedent
- def __init__(self, transform, size, label, loc,
- pad=0.1, borderpad=0.1, sep=2,
- frameon=True, size_vertical=0, color='black',
- label_top=False, fontproperties=None, fill_bar=None,
- **kwargs):
- """
- Draw a horizontal scale bar with a center-aligned label underneath.
-
- Parameters
- ----------
- transform : `matplotlib.transforms.Transform`
- The transformation object for the coordinate system in use, i.e.,
- :attr:`matplotlib.axes.Axes.transData`.
-
- size : int or float
- Horizontal length of the size bar, given in coordinates of
- *transform*.
-
- label : str
- Label to display.
-
- loc : int
- Location of this size bar. Valid location codes are::
-
- 'upper right' : 1,
- 'upper left' : 2,
- 'lower left' : 3,
- 'lower right' : 4,
- 'right' : 5,
- 'center left' : 6,
- 'center right' : 7,
- 'lower center' : 8,
- 'upper center' : 9,
- 'center' : 10
-
- pad : int or float, optional
- Padding around the label and size bar, in fraction of the font
- size. Defaults to 0.1.
-
- borderpad : int or float, optional
- Border padding, in fraction of the font size.
- Defaults to 0.1.
-
- sep : int or float, optional
- Separation between the label and the size bar, in points.
- Defaults to 2.
-
- frameon : bool, optional
- If True, draw a box around the horizontal bar and label.
- Defaults to True.
-
- size_vertical : int or float, optional
- Vertical length of the size bar, given in coordinates of
- *transform*. Defaults to 0.
-
- color : str, optional
- Color for the size bar and label.
- Defaults to black.
-
- label_top : bool, optional
- If True, the label will be over the size bar.
- Defaults to False.
-
- fontproperties : `matplotlib.font_manager.FontProperties`, optional
- Font properties for the label text.
-
- fill_bar : bool, optional
- If True and if size_vertical is nonzero, the size bar will
- be filled in with the color specified by the size bar.
- Defaults to True if `size_vertical` is greater than
- zero and False otherwise.
-
- **kwargs :
- Keyworded arguments to pass to
- :class:`matplotlib.offsetbox.AnchoredOffsetbox`.
-
- Attributes
- ----------
- size_bar : `matplotlib.offsetbox.AuxTransformBox`
- Container for the size bar.
-
- txt_label : `matplotlib.offsetbox.TextArea`
- Container for the label of the size bar.
-
- Notes
- -----
- If *prop* is passed as a keyworded argument, but *fontproperties* is
- not, then *prop* is be assumed to be the intended *fontproperties*.
- Using both *prop* and *fontproperties* is not supported.
-
- Examples
- --------
- >>> import matplotlib.pyplot as plt
- >>> import numpy as np
- >>> from mpl_toolkits.axes_grid1.anchored_artists import \
-AnchoredSizeBar
- >>> fig, ax = plt.subplots()
- >>> ax.imshow(np.random.random((10,10)))
- >>> bar = AnchoredSizeBar(ax.transData, 3, '3 data units', 4)
- >>> ax.add_artist(bar)
- >>> fig.show()
-
- Using all the optional parameters
-
- >>> import matplotlib.font_manager as fm
- >>> fontprops = fm.FontProperties(size=14, family='monospace')
- >>> bar = AnchoredSizeBar(ax.transData, 3, '3 units', 4, pad=0.5, \
-sep=5, borderpad=0.5, frameon=False, \
-size_vertical=0.5, color='white', \
-fontproperties=fontprops)
- """
- if fill_bar is None:
- fill_bar = size_vertical > 0
-
- self.size_bar = AuxTransformBox(transform)
- self.size_bar.add_artist(Rectangle((0, 0), size, size_vertical,
- fill=fill_bar, facecolor=color,
- edgecolor=color))
-
- if fontproperties is None and 'prop' in kwargs:
- fontproperties = kwargs.pop('prop')
-
- if fontproperties is None:
- textprops = {'color': color}
- else:
- textprops = {'color': color, 'fontproperties': fontproperties}
-
- self.txt_label = TextArea(
- label,
- minimumdescent=False,
- textprops=textprops)
-
- if label_top:
- _box_children = [self.txt_label, self.size_bar]
- else:
- _box_children = [self.size_bar, self.txt_label]
-
- self._box = VPacker(children=_box_children,
- align="center",
- pad=0, sep=sep)
-
- AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad,
- child=self._box,
- prop=fontproperties,
- frameon=frameon, **kwargs)
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_divider.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_divider.py
deleted file mode 100644
index b238e73cc5e..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_divider.py
+++ /dev/null
@@ -1,975 +0,0 @@
-"""
-The axes_divider module provides helper classes to adjust the positions of
-multiple axes at drawing time.
-
- Divider: this is the class that is used to calculate the axes
- position. It divides the given rectangular area into several sub
- rectangles. You initialize the divider by setting the horizontal
- and vertical lists of sizes that the division will be based on. You
- then use the new_locator method, whose return value is a callable
- object that can be used to set the axes_locator of the axes.
-
-"""
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-from six.moves import map
-
-import matplotlib.transforms as mtransforms
-
-from matplotlib.axes import SubplotBase
-
-from . import axes_size as Size
-
-
-class Divider(object):
- """
- This class calculates the axes position. It
- divides the given rectangular area into several
- sub-rectangles. You initialize the divider by setting the
- horizontal and vertical lists of sizes
- (:mod:`mpl_toolkits.axes_grid.axes_size`) that the division will
- be based on. You then use the new_locator method to create a
- callable object that can be used as the axes_locator of the
- axes.
- """
-
- def __init__(self, fig, pos, horizontal, vertical,
- aspect=None, anchor="C"):
- """
- Parameters
- ----------
- fig : Figure
- pos : tuple of 4 floats
- position of the rectangle that will be divided
- horizontal : list of :mod:`~mpl_toolkits.axes_grid.axes_size`
- sizes for horizontal division
- vertical : list of :mod:`~mpl_toolkits.axes_grid.axes_size`
- sizes for vertical division
- aspect : bool
- if True, the overall rectangular area is reduced
- so that the relative part of the horizontal and
- vertical scales have the same scale.
- anchor : {'C', 'SW', 'S', 'SE', 'E', 'NE', 'N', 'NW', 'W'}
- placement of the reduced rectangle when *aspect* is True
- """
-
- self._fig = fig
- self._pos = pos
- self._horizontal = horizontal
- self._vertical = vertical
- self._anchor = anchor
- self._aspect = aspect
- self._xrefindex = 0
- self._yrefindex = 0
- self._locator = None
-
- def get_horizontal_sizes(self, renderer):
- return [s.get_size(renderer) for s in self.get_horizontal()]
-
- def get_vertical_sizes(self, renderer):
- return [s.get_size(renderer) for s in self.get_vertical()]
-
- def get_vsize_hsize(self):
-
- from .axes_size import AddList
-
- vsize = AddList(self.get_vertical())
- hsize = AddList(self.get_horizontal())
-
- return vsize, hsize
-
- @staticmethod
- def _calc_k(l, total_size):
-
- rs_sum, as_sum = 0., 0.
-
- for _rs, _as in l:
- rs_sum += _rs
- as_sum += _as
-
- if rs_sum != 0.:
- k = (total_size - as_sum) / rs_sum
- return k
- else:
- return 0.
-
- @staticmethod
- def _calc_offsets(l, k):
-
- offsets = [0.]
-
- #for s in l:
- for _rs, _as in l:
- #_rs, _as = s.get_size(renderer)
- offsets.append(offsets[-1] + _rs*k + _as)
-
- return offsets
-
- def set_position(self, pos):
- """
- set the position of the rectangle.
-
- Parameters
- ----------
- pos : tuple of 4 floats
- position of the rectangle that will be divided
- """
- self._pos = pos
-
- def get_position(self):
- "return the position of the rectangle."
- return self._pos
-
- def set_anchor(self, anchor):
- """
- Parameters
- ----------
- anchor : {'C', 'SW', 'S', 'SE', 'E', 'NE', 'N', 'NW', 'W'}
- anchor position
-
- ===== ============
- value description
- ===== ============
- 'C' Center
- 'SW' bottom left
- 'S' bottom
- 'SE' bottom right
- 'E' right
- 'NE' top right
- 'N' top
- 'NW' top left
- 'W' left
- ===== ============
-
- """
- if anchor in mtransforms.Bbox.coefs or len(anchor) == 2:
- self._anchor = anchor
- else:
- raise ValueError('argument must be among %s' %
- ', '.join(mtransforms.BBox.coefs))
-
- def get_anchor(self):
- "return the anchor"
- return self._anchor
-
- def set_horizontal(self, h):
- """
- Parameters
- ----------
- h : list of :mod:`~mpl_toolkits.axes_grid.axes_size`
- sizes for horizontal division
- """
- self._horizontal = h
-
- def get_horizontal(self):
- "return horizontal sizes"
- return self._horizontal
-
- def set_vertical(self, v):
- """
- Parameters
- ----------
- v : list of :mod:`~mpl_toolkits.axes_grid.axes_size`
- sizes for vertical division
- """
- self._vertical = v
-
- def get_vertical(self):
- "return vertical sizes"
- return self._vertical
-
- def set_aspect(self, aspect=False):
- """
- Parameters
- ----------
- aspect : bool
- """
- self._aspect = aspect
-
- def get_aspect(self):
- "return aspect"
- return self._aspect
-
- def set_locator(self, _locator):
- self._locator = _locator
-
- def get_locator(self):
- return self._locator
-
- def get_position_runtime(self, ax, renderer):
- if self._locator is None:
- return self.get_position()
- else:
- return self._locator(ax, renderer).bounds
-
- def locate(self, nx, ny, nx1=None, ny1=None, axes=None, renderer=None):
- """
- Parameters
- ----------
- nx, nx1 : int
- Integers specifying the column-position of the
- cell. When *nx1* is None, a single *nx*-th column is
- specified. Otherwise location of columns spanning between *nx*
- to *nx1* (but excluding *nx1*-th column) is specified.
- ny, ny1 : int
- Same as *nx* and *nx1*, but for row positions.
- axes
- renderer
- """
-
- figW, figH = self._fig.get_size_inches()
- x, y, w, h = self.get_position_runtime(axes, renderer)
-
- hsizes = self.get_horizontal_sizes(renderer)
- vsizes = self.get_vertical_sizes(renderer)
- k_h = self._calc_k(hsizes, figW*w)
- k_v = self._calc_k(vsizes, figH*h)
-
- if self.get_aspect():
- k = min(k_h, k_v)
- ox = self._calc_offsets(hsizes, k)
- oy = self._calc_offsets(vsizes, k)
-
- ww = (ox[-1] - ox[0])/figW
- hh = (oy[-1] - oy[0])/figH
- pb = mtransforms.Bbox.from_bounds(x, y, w, h)
- pb1 = mtransforms.Bbox.from_bounds(x, y, ww, hh)
- pb1_anchored = pb1.anchored(self.get_anchor(), pb)
- x0, y0 = pb1_anchored.x0, pb1_anchored.y0
-
- else:
- ox = self._calc_offsets(hsizes, k_h)
- oy = self._calc_offsets(vsizes, k_v)
- x0, y0 = x, y
-
- if nx1 is None:
- nx1 = nx+1
- if ny1 is None:
- ny1 = ny+1
-
- x1, w1 = x0 + ox[nx]/figW, (ox[nx1] - ox[nx])/figW
- y1, h1 = y0 + oy[ny]/figH, (oy[ny1] - oy[ny])/figH
-
- return mtransforms.Bbox.from_bounds(x1, y1, w1, h1)
-
- def new_locator(self, nx, ny, nx1=None, ny1=None):
- """
- Returns a new locator
- (:class:`mpl_toolkits.axes_grid.axes_divider.AxesLocator`) for
- specified cell.
-
- Parameters
- ----------
- nx, nx1 : int
- Integers specifying the column-position of the
- cell. When *nx1* is None, a single *nx*-th column is
- specified. Otherwise location of columns spanning between *nx*
- to *nx1* (but excluding *nx1*-th column) is specified.
- ny, ny1 : int
- Same as *nx* and *nx1*, but for row positions.
- """
- return AxesLocator(self, nx, ny, nx1, ny1)
-
- def append_size(self, position, size):
-
- if position == "left":
- self._horizontal.insert(0, size)
- self._xrefindex += 1
- elif position == "right":
- self._horizontal.append(size)
- elif position == "bottom":
- self._vertical.insert(0, size)
- self._yrefindex += 1
- elif position == "top":
- self._vertical.append(size)
- else:
- raise ValueError("the position must be one of left," +
- " right, bottom, or top")
-
- def add_auto_adjustable_area(self,
- use_axes, pad=0.1,
- adjust_dirs=None,
- ):
- if adjust_dirs is None:
- adjust_dirs = ["left", "right", "bottom", "top"]
- from .axes_size import Padded, SizeFromFunc, GetExtentHelper
- for d in adjust_dirs:
- helper = GetExtentHelper(use_axes, d)
- size = SizeFromFunc(helper)
- padded_size = Padded(size, pad) # pad in inch
- self.append_size(d, padded_size)
-
-
-class AxesLocator(object):
- """
- A simple callable object, initialized with AxesDivider class,
- returns the position and size of the given cell.
- """
- def __init__(self, axes_divider, nx, ny, nx1=None, ny1=None):
- """
- Parameters
- ----------
- axes_divider : AxesDivider
- nx, nx1 : int
- Integers specifying the column-position of the
- cell. When *nx1* is None, a single *nx*-th column is
- specified. Otherwise location of columns spanning between *nx*
- to *nx1* (but excluding *nx1*-th column) is specified.
- ny, ny1 : int
- Same as *nx* and *nx1*, but for row positions.
- """
- self._axes_divider = axes_divider
-
- _xrefindex = axes_divider._xrefindex
- _yrefindex = axes_divider._yrefindex
-
- self._nx, self._ny = nx - _xrefindex, ny - _yrefindex
-
- if nx1 is None:
- nx1 = nx+1
- if ny1 is None:
- ny1 = ny+1
-
- self._nx1 = nx1 - _xrefindex
- self._ny1 = ny1 - _yrefindex
-
- def __call__(self, axes, renderer):
-
- _xrefindex = self._axes_divider._xrefindex
- _yrefindex = self._axes_divider._yrefindex
-
- return self._axes_divider.locate(self._nx + _xrefindex,
- self._ny + _yrefindex,
- self._nx1 + _xrefindex,
- self._ny1 + _yrefindex,
- axes,
- renderer)
-
- def get_subplotspec(self):
- if hasattr(self._axes_divider, "get_subplotspec"):
- return self._axes_divider.get_subplotspec()
- else:
- return None
-
-
-from matplotlib.gridspec import SubplotSpec, GridSpec
-
-
-class SubplotDivider(Divider):
- """
- The Divider class whose rectangle area is specified as a subplot geometry.
- """
-
- def __init__(self, fig, *args, **kwargs):
- """
- Parameters
- ----------
- fig : :class:`matplotlib.figure.Figure`
- args : tuple (*numRows*, *numCols*, *plotNum*)
- The array of subplots in the figure has dimensions *numRows*,
- *numCols*, and *plotNum* is the number of the subplot
- being created. *plotNum* starts at 1 in the upper left
- corner and increases to the right.
-
- If *numRows* <= *numCols* <= *plotNum* < 10, *args* can be the
- decimal integer *numRows* * 100 + *numCols* * 10 + *plotNum*.
- """
-
- self.figure = fig
-
- if len(args) == 1:
- if isinstance(args[0], SubplotSpec):
- self._subplotspec = args[0]
- else:
- try:
- s = str(int(args[0]))
- rows, cols, num = map(int, s)
- except ValueError:
- raise ValueError(
- 'Single argument to subplot must be a 3-digit integer')
- self._subplotspec = GridSpec(rows, cols)[num-1]
- # num - 1 for converting from MATLAB to python indexing
- elif len(args) == 3:
- rows, cols, num = args
- rows = int(rows)
- cols = int(cols)
- if isinstance(num, tuple) and len(num) == 2:
- num = [int(n) for n in num]
- self._subplotspec = GridSpec(rows, cols)[num[0]-1:num[1]]
- else:
- self._subplotspec = GridSpec(rows, cols)[int(num)-1]
- # num - 1 for converting from MATLAB to python indexing
- else:
- raise ValueError('Illegal argument(s) to subplot: %s' % (args,))
-
- # total = rows*cols
- # num -= 1 # convert from matlab to python indexing
- # # i.e., num in range(0,total)
- # if num >= total:
- # raise ValueError( 'Subplot number exceeds total subplots')
- # self._rows = rows
- # self._cols = cols
- # self._num = num
-
- # self.update_params()
-
- # sets self.fixbox
- self.update_params()
-
- pos = self.figbox.bounds
-
- horizontal = kwargs.pop("horizontal", [])
- vertical = kwargs.pop("vertical", [])
- aspect = kwargs.pop("aspect", None)
- anchor = kwargs.pop("anchor", "C")
-
- if kwargs:
- raise Exception("")
-
- Divider.__init__(self, fig, pos, horizontal, vertical,
- aspect=aspect, anchor=anchor)
-
- def get_position(self):
- "return the bounds of the subplot box"
-
- self.update_params() # update self.figbox
- return self.figbox.bounds
-
- # def update_params(self):
- # 'update the subplot position from fig.subplotpars'
-
- # rows = self._rows
- # cols = self._cols
- # num = self._num
-
- # pars = self.figure.subplotpars
- # left = pars.left
- # right = pars.right
- # bottom = pars.bottom
- # top = pars.top
- # wspace = pars.wspace
- # hspace = pars.hspace
- # totWidth = right-left
- # totHeight = top-bottom
-
- # figH = totHeight/(rows + hspace*(rows-1))
- # sepH = hspace*figH
-
- # figW = totWidth/(cols + wspace*(cols-1))
- # sepW = wspace*figW
-
- # rowNum, colNum = divmod(num, cols)
-
- # figBottom = top - (rowNum+1)*figH - rowNum*sepH
- # figLeft = left + colNum*(figW + sepW)
-
- # self.figbox = mtransforms.Bbox.from_bounds(figLeft, figBottom,
- # figW, figH)
-
- def update_params(self):
- 'update the subplot position from fig.subplotpars'
-
- self.figbox = self.get_subplotspec().get_position(self.figure)
-
- def get_geometry(self):
- 'get the subplot geometry, e.g., 2,2,3'
- rows, cols, num1, num2 = self.get_subplotspec().get_geometry()
- return rows, cols, num1+1 # for compatibility
-
- # COVERAGE NOTE: Never used internally or from examples
- def change_geometry(self, numrows, numcols, num):
- 'change subplot geometry, e.g., from 1,1,1 to 2,2,3'
- self._subplotspec = GridSpec(numrows, numcols)[num-1]
- self.update_params()
- self.set_position(self.figbox)
-
- def get_subplotspec(self):
- 'get the SubplotSpec instance'
- return self._subplotspec
-
- def set_subplotspec(self, subplotspec):
- 'set the SubplotSpec instance'
- self._subplotspec = subplotspec
-
-
-class AxesDivider(Divider):
- """
- Divider based on the pre-existing axes.
- """
-
- def __init__(self, axes, xref=None, yref=None):
- """
- Parameters
- ----------
- axes : :class:`~matplotlib.axes.Axes`
- xref
- yref
- """
- self._axes = axes
- if xref is None:
- self._xref = Size.AxesX(axes)
- else:
- self._xref = xref
- if yref is None:
- self._yref = Size.AxesY(axes)
- else:
- self._yref = yref
-
- Divider.__init__(self, fig=axes.get_figure(), pos=None,
- horizontal=[self._xref], vertical=[self._yref],
- aspect=None, anchor="C")
-
- def _get_new_axes(self, **kwargs):
- axes = self._axes
-
- axes_class = kwargs.pop("axes_class", None)
-
- if axes_class is None:
- if isinstance(axes, SubplotBase):
- axes_class = axes._axes_class
- else:
- axes_class = type(axes)
-
- ax = axes_class(axes.get_figure(),
- axes.get_position(original=True), **kwargs)
-
- return ax
-
- def new_horizontal(self, size, pad=None, pack_start=False, **kwargs):
- """
- Add a new axes on the right (or left) side of the main axes.
-
- Parameters
- ----------
- size : :mod:`~mpl_toolkits.axes_grid.axes_size` or float or string
- A width of the axes. If float or string is given, *from_any*
- function is used to create the size, with *ref_size* set to AxesX
- instance of the current axes.
- pad : :mod:`~mpl_toolkits.axes_grid.axes_size` or float or string
- Pad between the axes. It takes same argument as *size*.
- pack_start : bool
- If False, the new axes is appended at the end
- of the list, i.e., it became the right-most axes. If True, it is
- inserted at the start of the list, and becomes the left-most axes.
- kwargs
- All extra keywords arguments are passed to the created axes.
- If *axes_class* is given, the new axes will be created as an
- instance of the given class. Otherwise, the same class of the
- main axes will be used.
- """
-
- if pad:
- if not isinstance(pad, Size._Base):
- pad = Size.from_any(pad,
- fraction_ref=self._xref)
- if pack_start:
- self._horizontal.insert(0, pad)
- self._xrefindex += 1
- else:
- self._horizontal.append(pad)
-
- if not isinstance(size, Size._Base):
- size = Size.from_any(size,
- fraction_ref=self._xref)
-
- if pack_start:
- self._horizontal.insert(0, size)
- self._xrefindex += 1
- locator = self.new_locator(nx=0, ny=self._yrefindex)
- else:
- self._horizontal.append(size)
- locator = self.new_locator(nx=len(self._horizontal)-1, ny=self._yrefindex)
-
- ax = self._get_new_axes(**kwargs)
- ax.set_axes_locator(locator)
-
- return ax
-
- def new_vertical(self, size, pad=None, pack_start=False, **kwargs):
- """
- Add a new axes on the top (or bottom) side of the main axes.
-
- Parameters
- ----------
- size : :mod:`~mpl_toolkits.axes_grid.axes_size` or float or string
- A height of the axes. If float or string is given, *from_any*
- function is used to create the size, with *ref_size* set to AxesX
- instance of the current axes.
- pad : :mod:`~mpl_toolkits.axes_grid.axes_size` or float or string
- Pad between the axes. It takes same argument as *size*.
- pack_start : bool
- If False, the new axes is appended at the end
- of the list, i.e., it became the right-most axes. If True, it is
- inserted at the start of the list, and becomes the left-most axes.
- kwargs
- All extra keywords arguments are passed to the created axes.
- If *axes_class* is given, the new axes will be created as an
- instance of the given class. Otherwise, the same class of the
- main axes will be used.
- """
-
- if pad:
- if not isinstance(pad, Size._Base):
- pad = Size.from_any(pad,
- fraction_ref=self._yref)
- if pack_start:
- self._vertical.insert(0, pad)
- self._yrefindex += 1
- else:
- self._vertical.append(pad)
-
- if not isinstance(size, Size._Base):
- size = Size.from_any(size,
- fraction_ref=self._yref)
-
- if pack_start:
- self._vertical.insert(0, size)
- self._yrefindex += 1
- locator = self.new_locator(nx=self._xrefindex, ny=0)
- else:
- self._vertical.append(size)
- locator = self.new_locator(nx=self._xrefindex, ny=len(self._vertical)-1)
-
- ax = self._get_new_axes(**kwargs)
- ax.set_axes_locator(locator)
-
- return ax
-
- def append_axes(self, position, size, pad=None, add_to_figure=True,
- **kwargs):
- """
- create an axes at the given *position* with the same height
- (or width) of the main axes.
-
- *position*
- ["left"|"right"|"bottom"|"top"]
-
- *size* and *pad* should be axes_grid.axes_size compatible.
- """
-
- if position == "left":
- ax = self.new_horizontal(size, pad, pack_start=True, **kwargs)
- elif position == "right":
- ax = self.new_horizontal(size, pad, pack_start=False, **kwargs)
- elif position == "bottom":
- ax = self.new_vertical(size, pad, pack_start=True, **kwargs)
- elif position == "top":
- ax = self.new_vertical(size, pad, pack_start=False, **kwargs)
- else:
- raise ValueError("the position must be one of left," +
- " right, bottom, or top")
-
- if add_to_figure:
- self._fig.add_axes(ax)
- return ax
-
- def get_aspect(self):
- if self._aspect is None:
- aspect = self._axes.get_aspect()
- if aspect == "auto":
- return False
- else:
- return True
- else:
- return self._aspect
-
- def get_position(self):
- if self._pos is None:
- bbox = self._axes.get_position(original=True)
- return bbox.bounds
- else:
- return self._pos
-
- def get_anchor(self):
- if self._anchor is None:
- return self._axes.get_anchor()
- else:
- return self._anchor
-
- def get_subplotspec(self):
- if hasattr(self._axes, "get_subplotspec"):
- return self._axes.get_subplotspec()
- else:
- return None
-
-
-class HBoxDivider(SubplotDivider):
-
- def __init__(self, fig, *args, **kwargs):
- SubplotDivider.__init__(self, fig, *args, **kwargs)
-
- @staticmethod
- def _determine_karray(equivalent_sizes, appended_sizes,
- max_equivalent_size,
- total_appended_size):
-
- n = len(equivalent_sizes)
- import numpy as np
- A = np.mat(np.zeros((n+1, n+1), dtype="d"))
- B = np.zeros((n+1), dtype="d")
- # AxK = B
-
- # populated A
- for i, (r, a) in enumerate(equivalent_sizes):
- A[i, i] = r
- A[i, -1] = -1
- B[i] = -a
- A[-1, :-1] = [r for r, a in appended_sizes]
- B[-1] = total_appended_size - sum([a for rs, a in appended_sizes])
-
- karray_H = (A.I*np.mat(B).T).A1
- karray = karray_H[:-1]
- H = karray_H[-1]
-
- if H > max_equivalent_size:
- karray = ((max_equivalent_size -
- np.array([a for r, a in equivalent_sizes]))
- / np.array([r for r, a in equivalent_sizes]))
- return karray
-
- @staticmethod
- def _calc_offsets(appended_sizes, karray):
- offsets = [0.]
-
- #for s in l:
- for (r, a), k in zip(appended_sizes, karray):
- offsets.append(offsets[-1] + r*k + a)
-
- return offsets
-
- def new_locator(self, nx, nx1=None):
- """
- returns a new locator
- (:class:`mpl_toolkits.axes_grid.axes_divider.AxesLocator`) for
- specified cell.
-
- Parameters
- ----------
- nx, nx1 : int
- Integers specifying the column-position of the
- cell. When *nx1* is None, a single *nx*-th column is
- specified. Otherwise location of columns spanning between *nx*
- to *nx1* (but excluding *nx1*-th column) is specified.
- ny, ny1 : int
- Same as *nx* and *nx1*, but for row positions.
- """
- return AxesLocator(self, nx, 0, nx1, None)
-
- def _locate(self, x, y, w, h,
- y_equivalent_sizes, x_appended_sizes,
- figW, figH):
- """
- Parameters
- ----------
- x
- y
- w
- h
- y_equivalent_sizes
- x_appended_sizes
- figW
- figH
- """
-
- equivalent_sizes = y_equivalent_sizes
- appended_sizes = x_appended_sizes
-
- max_equivalent_size = figH*h
- total_appended_size = figW*w
- karray = self._determine_karray(equivalent_sizes, appended_sizes,
- max_equivalent_size,
- total_appended_size)
-
- ox = self._calc_offsets(appended_sizes, karray)
-
- ww = (ox[-1] - ox[0])/figW
- ref_h = equivalent_sizes[0]
- hh = (karray[0]*ref_h[0] + ref_h[1])/figH
- pb = mtransforms.Bbox.from_bounds(x, y, w, h)
- pb1 = mtransforms.Bbox.from_bounds(x, y, ww, hh)
- pb1_anchored = pb1.anchored(self.get_anchor(), pb)
- x0, y0 = pb1_anchored.x0, pb1_anchored.y0
-
- return x0, y0, ox, hh
-
- def locate(self, nx, ny, nx1=None, ny1=None, axes=None, renderer=None):
- """
- Parameters
- ----------
- axes_divider : AxesDivider
- nx, nx1 : int
- Integers specifying the column-position of the
- cell. When *nx1* is None, a single *nx*-th column is
- specified. Otherwise location of columns spanning between *nx*
- to *nx1* (but excluding *nx1*-th column) is specified.
- ny, ny1 : int
- Same as *nx* and *nx1*, but for row positions.
- axes
- renderer
- """
-
- figW, figH = self._fig.get_size_inches()
- x, y, w, h = self.get_position_runtime(axes, renderer)
-
- y_equivalent_sizes = self.get_vertical_sizes(renderer)
- x_appended_sizes = self.get_horizontal_sizes(renderer)
- x0, y0, ox, hh = self._locate(x, y, w, h,
- y_equivalent_sizes, x_appended_sizes,
- figW, figH)
- if nx1 is None:
- nx1 = nx+1
-
- x1, w1 = x0 + ox[nx]/figW, (ox[nx1] - ox[nx])/figW
- y1, h1 = y0, hh
-
- return mtransforms.Bbox.from_bounds(x1, y1, w1, h1)
-
-
-class VBoxDivider(HBoxDivider):
- """
- The Divider class whose rectangle area is specified as a subplot geometry.
- """
-
- def new_locator(self, ny, ny1=None):
- """
- returns a new locator
- (:class:`mpl_toolkits.axes_grid.axes_divider.AxesLocator`) for
- specified cell.
-
- Parameters
- ----------
- ny, ny1 : int
- Integers specifying the row-position of the
- cell. When *ny1* is None, a single *ny*-th row is
- specified. Otherwise location of rows spanning between *ny*
- to *ny1* (but excluding *ny1*-th row) is specified.
- """
- return AxesLocator(self, 0, ny, None, ny1)
-
- def locate(self, nx, ny, nx1=None, ny1=None, axes=None, renderer=None):
- """
- Parameters
- ----------
- axes_divider : AxesDivider
- nx, nx1 : int
- Integers specifying the column-position of the
- cell. When *nx1* is None, a single *nx*-th column is
- specified. Otherwise location of columns spanning between *nx*
- to *nx1* (but excluding *nx1*-th column) is specified.
- ny, ny1 : int
- Same as *nx* and *nx1*, but for row positions.
- axes
- renderer
- """
-
- figW, figH = self._fig.get_size_inches()
- x, y, w, h = self.get_position_runtime(axes, renderer)
-
- x_equivalent_sizes = self.get_horizontal_sizes(renderer)
- y_appended_sizes = self.get_vertical_sizes(renderer)
-
- y0, x0, oy, ww = self._locate(y, x, h, w,
- x_equivalent_sizes, y_appended_sizes,
- figH, figW)
- if ny1 is None:
- ny1 = ny+1
-
- x1, w1 = x0, ww
- y1, h1 = y0 + oy[ny]/figH, (oy[ny1] - oy[ny])/figH
-
- return mtransforms.Bbox.from_bounds(x1, y1, w1, h1)
-
-
-class LocatableAxesBase(object):
- def __init__(self, *kl, **kw):
-
- self._axes_class.__init__(self, *kl, **kw)
-
- self._locator = None
- self._locator_renderer = None
-
- def set_axes_locator(self, locator):
- self._locator = locator
-
- def get_axes_locator(self):
- return self._locator
-
- def apply_aspect(self, position=None):
-
- if self.get_axes_locator() is None:
- self._axes_class.apply_aspect(self, position)
- else:
- pos = self.get_axes_locator()(self, self._locator_renderer)
- self._axes_class.apply_aspect(self, position=pos)
-
- def draw(self, renderer=None, inframe=False):
-
- self._locator_renderer = renderer
-
- self._axes_class.draw(self, renderer, inframe)
-
- def _make_twin_axes(self, *kl, **kwargs):
- """
- Need to overload so that twinx/twiny will work with
- these axes.
- """
- if 'sharex' in kwargs and 'sharey' in kwargs:
- raise ValueError("Twinned Axes may share only one axis.")
- ax2 = type(self)(self.figure, self.get_position(True), *kl, **kwargs)
- ax2.set_axes_locator(self.get_axes_locator())
- self.figure.add_axes(ax2)
- self.set_adjustable('datalim')
- ax2.set_adjustable('datalim')
- self._twinned_axes.join(self, ax2)
- return ax2
-
-_locatableaxes_classes = {}
-
-
-def locatable_axes_factory(axes_class):
-
- new_class = _locatableaxes_classes.get(axes_class)
- if new_class is None:
- new_class = type(str("Locatable%s" % (axes_class.__name__)),
- (LocatableAxesBase, axes_class),
- {'_axes_class': axes_class})
-
- _locatableaxes_classes[axes_class] = new_class
-
- return new_class
-
-#if hasattr(maxes.Axes, "get_axes_locator"):
-# LocatableAxes = maxes.Axes
-#else:
-
-
-def make_axes_locatable(axes):
- if not hasattr(axes, "set_axes_locator"):
- new_class = locatable_axes_factory(type(axes))
- axes.__class__ = new_class
-
- divider = AxesDivider(axes)
- locator = divider.new_locator(nx=0, ny=0)
- axes.set_axes_locator(locator)
-
- return divider
-
-
-def make_axes_area_auto_adjustable(ax,
- use_axes=None, pad=0.1,
- adjust_dirs=None):
- if adjust_dirs is None:
- adjust_dirs = ["left", "right", "bottom", "top"]
- divider = make_axes_locatable(ax)
-
- if use_axes is None:
- use_axes = ax
-
- divider.add_auto_adjustable_area(use_axes=use_axes, pad=pad,
- adjust_dirs=adjust_dirs)
-
-#from matplotlib.axes import Axes
-from .mpl_axes import Axes
-LocatableAxes = locatable_axes_factory(Axes)
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_grid.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_grid.py
deleted file mode 100644
index d7e4fa8768c..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_grid.py
+++ /dev/null
@@ -1,771 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-
-import matplotlib.axes as maxes
-import matplotlib.cbook as cbook
-import matplotlib.ticker as ticker
-from matplotlib.gridspec import SubplotSpec
-
-from .axes_divider import Size, SubplotDivider, LocatableAxes, Divider
-from .colorbar import Colorbar
-
-
-def _extend_axes_pad(value):
- # Check whether a list/tuple/array or scalar has been passed
- ret = value
- if not hasattr(ret, "__getitem__"):
- ret = (value, value)
- return ret
-
-
-def _tick_only(ax, bottom_on, left_on):
- bottom_off = not bottom_on
- left_off = not left_on
- # [l.set_visible(bottom_off) for l in ax.get_xticklabels()]
- # [l.set_visible(left_off) for l in ax.get_yticklabels()]
- # ax.xaxis.label.set_visible(bottom_off)
- # ax.yaxis.label.set_visible(left_off)
- ax.axis["bottom"].toggle(ticklabels=bottom_off, label=bottom_off)
- ax.axis["left"].toggle(ticklabels=left_off, label=left_off)
-
-
-class CbarAxesBase(object):
-
- def colorbar(self, mappable, **kwargs):
- locator = kwargs.pop("locator", None)
-
- if locator is None:
- if "ticks" not in kwargs:
- kwargs["ticks"] = ticker.MaxNLocator(5)
- if locator is not None:
- if "ticks" in kwargs:
- raise ValueError("Either *locator* or *ticks* need" +
- " to be given, not both")
- else:
- kwargs["ticks"] = locator
-
- self._hold = True
- if self.orientation in ["top", "bottom"]:
- orientation = "horizontal"
- else:
- orientation = "vertical"
-
- cb = Colorbar(self, mappable, orientation=orientation, **kwargs)
- self._config_axes()
-
- def on_changed(m):
- cb.set_cmap(m.get_cmap())
- cb.set_clim(m.get_clim())
- cb.update_bruteforce(m)
-
- self.cbid = mappable.callbacksSM.connect('changed', on_changed)
- mappable.colorbar = cb
-
- self.locator = cb.cbar_axis.get_major_locator()
-
- return cb
-
- def _config_axes(self):
- '''
- Make an axes patch and outline.
- '''
- ax = self
- ax.set_navigate(False)
-
- ax.axis[:].toggle(all=False)
- b = self._default_label_on
- ax.axis[self.orientation].toggle(all=b)
-
- # for axis in ax.axis.values():
- # axis.major_ticks.set_visible(False)
- # axis.minor_ticks.set_visible(False)
- # axis.major_ticklabels.set_visible(False)
- # axis.minor_ticklabels.set_visible(False)
- # axis.label.set_visible(False)
-
- # axis = ax.axis[self.orientation]
- # axis.major_ticks.set_visible(True)
- # axis.minor_ticks.set_visible(True)
-
- #axis.major_ticklabels.set_size(
- # int(axis.major_ticklabels.get_size()*.9))
- #axis.major_tick_pad = 3
-
- # axis.major_ticklabels.set_visible(b)
- # axis.minor_ticklabels.set_visible(b)
- # axis.label.set_visible(b)
-
- def toggle_label(self, b):
- self._default_label_on = b
- axis = self.axis[self.orientation]
- axis.toggle(ticklabels=b, label=b)
- #axis.major_ticklabels.set_visible(b)
- #axis.minor_ticklabels.set_visible(b)
- #axis.label.set_visible(b)
-
-
-class CbarAxes(CbarAxesBase, LocatableAxes):
- def __init__(self, *kl, **kwargs):
- orientation = kwargs.pop("orientation", None)
- if orientation is None:
- raise ValueError("orientation must be specified")
- self.orientation = orientation
- self._default_label_on = True
- self.locator = None
-
- super(LocatableAxes, self).__init__(*kl, **kwargs)
-
- def cla(self):
- super(LocatableAxes, self).cla()
- self._config_axes()
-
-
-class Grid(object):
- """
- A class that creates a grid of Axes. In matplotlib, the axes
- location (and size) is specified in the normalized figure
- coordinates. This may not be ideal for images that needs to be
- displayed with a given aspect ratio. For example, displaying
- images of a same size with some fixed padding between them cannot
- be easily done in matplotlib. AxesGrid is used in such case.
- """
-
- _defaultLocatableAxesClass = LocatableAxes
-
- def __init__(self, fig,
- rect,
- nrows_ncols,
- ngrids=None,
- direction="row",
- axes_pad=0.02,
- add_all=True,
- share_all=False,
- share_x=True,
- share_y=True,
- #aspect=True,
- label_mode="L",
- axes_class=None,
- ):
- """
- Build an :class:`Grid` instance with a grid nrows*ncols
- :class:`~matplotlib.axes.Axes` in
- :class:`~matplotlib.figure.Figure` *fig* with
- *rect=[left, bottom, width, height]* (in
- :class:`~matplotlib.figure.Figure` coordinates) or
- the subplot position code (e.g., "121").
-
- Optional keyword arguments:
-
- ================ ======== =========================================
- Keyword Default Description
- ================ ======== =========================================
- direction "row" [ "row" | "column" ]
- axes_pad 0.02 float| pad between axes given in inches
- or tuple-like of floats,
- (horizontal padding, vertical padding)
- add_all True bool
- share_all False bool
- share_x True bool
- share_y True bool
- label_mode "L" [ "L" | "1" | "all" ]
- axes_class None a type object which must be a subclass
- of :class:`~matplotlib.axes.Axes`
- ================ ======== =========================================
- """
- self._nrows, self._ncols = nrows_ncols
-
- if ngrids is None:
- ngrids = self._nrows * self._ncols
- else:
- if (ngrids > self._nrows * self._ncols) or (ngrids <= 0):
- raise Exception("")
-
- self.ngrids = ngrids
-
- self._init_axes_pad(axes_pad)
-
- if direction not in ["column", "row"]:
- raise Exception("")
-
- self._direction = direction
-
- if axes_class is None:
- axes_class = self._defaultLocatableAxesClass
- axes_class_args = {}
- else:
- if (type(axes_class)) == type and \
- issubclass(axes_class,
- self._defaultLocatableAxesClass.Axes):
- axes_class_args = {}
- else:
- axes_class, axes_class_args = axes_class
-
- self.axes_all = []
- self.axes_column = [[] for _ in range(self._ncols)]
- self.axes_row = [[] for _ in range(self._nrows)]
-
- h = []
- v = []
- if isinstance(rect, six.string_types) or cbook.is_numlike(rect):
- self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v,
- aspect=False)
- elif isinstance(rect, SubplotSpec):
- self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v,
- aspect=False)
- elif len(rect) == 3:
- kw = dict(horizontal=h, vertical=v, aspect=False)
- self._divider = SubplotDivider(fig, *rect, **kw)
- elif len(rect) == 4:
- self._divider = Divider(fig, rect, horizontal=h, vertical=v,
- aspect=False)
- else:
- raise Exception("")
-
- rect = self._divider.get_position()
-
- # reference axes
- self._column_refax = [None for _ in range(self._ncols)]
- self._row_refax = [None for _ in range(self._nrows)]
- self._refax = None
-
- for i in range(self.ngrids):
-
- col, row = self._get_col_row(i)
-
- if share_all:
- sharex = self._refax
- sharey = self._refax
- else:
- if share_x:
- sharex = self._column_refax[col]
- else:
- sharex = None
-
- if share_y:
- sharey = self._row_refax[row]
- else:
- sharey = None
-
- ax = axes_class(fig, rect, sharex=sharex, sharey=sharey,
- **axes_class_args)
-
- if share_all:
- if self._refax is None:
- self._refax = ax
- else:
- if sharex is None:
- self._column_refax[col] = ax
- if sharey is None:
- self._row_refax[row] = ax
-
- self.axes_all.append(ax)
- self.axes_column[col].append(ax)
- self.axes_row[row].append(ax)
-
- self.axes_llc = self.axes_column[0][-1]
-
- self._update_locators()
-
- if add_all:
- for ax in self.axes_all:
- fig.add_axes(ax)
-
- self.set_label_mode(label_mode)
-
- def _init_axes_pad(self, axes_pad):
- axes_pad = _extend_axes_pad(axes_pad)
- self._axes_pad = axes_pad
-
- self._horiz_pad_size = Size.Fixed(axes_pad[0])
- self._vert_pad_size = Size.Fixed(axes_pad[1])
-
- def _update_locators(self):
-
- h = []
-
- h_ax_pos = []
-
- for _ in self._column_refax:
- #if h: h.append(Size.Fixed(self._axes_pad))
- if h:
- h.append(self._horiz_pad_size)
-
- h_ax_pos.append(len(h))
-
- sz = Size.Scaled(1)
- h.append(sz)
-
- v = []
-
- v_ax_pos = []
- for _ in self._row_refax[::-1]:
- #if v: v.append(Size.Fixed(self._axes_pad))
- if v:
- v.append(self._vert_pad_size)
-
- v_ax_pos.append(len(v))
- sz = Size.Scaled(1)
- v.append(sz)
-
- for i in range(self.ngrids):
- col, row = self._get_col_row(i)
- locator = self._divider.new_locator(nx=h_ax_pos[col],
- ny=v_ax_pos[self._nrows - 1 - row])
- self.axes_all[i].set_axes_locator(locator)
-
- self._divider.set_horizontal(h)
- self._divider.set_vertical(v)
-
- def _get_col_row(self, n):
- if self._direction == "column":
- col, row = divmod(n, self._nrows)
- else:
- row, col = divmod(n, self._ncols)
-
- return col, row
-
- # Good to propagate __len__ if we have __getitem__
- def __len__(self):
- return len(self.axes_all)
-
- def __getitem__(self, i):
- return self.axes_all[i]
-
- def get_geometry(self):
- """
- get geometry of the grid. Returns a tuple of two integer,
- representing number of rows and number of columns.
- """
- return self._nrows, self._ncols
-
- def set_axes_pad(self, axes_pad):
- "set axes_pad"
- self._axes_pad = axes_pad
-
- # These two lines actually differ from ones in _init_axes_pad
- self._horiz_pad_size.fixed_size = axes_pad[0]
- self._vert_pad_size.fixed_size = axes_pad[1]
-
- def get_axes_pad(self):
- """
- get axes_pad
-
- Returns
- -------
- tuple
- Padding in inches, (horizontal pad, vertical pad)
- """
- return self._axes_pad
-
- def set_aspect(self, aspect):
- "set aspect"
- self._divider.set_aspect(aspect)
-
- def get_aspect(self):
- "get aspect"
- return self._divider.get_aspect()
-
- def set_label_mode(self, mode):
- "set label_mode"
- if mode == "all":
- for ax in self.axes_all:
- _tick_only(ax, False, False)
- elif mode == "L":
- # left-most axes
- for ax in self.axes_column[0][:-1]:
- _tick_only(ax, bottom_on=True, left_on=False)
- # lower-left axes
- ax = self.axes_column[0][-1]
- _tick_only(ax, bottom_on=False, left_on=False)
-
- for col in self.axes_column[1:]:
- # axes with no labels
- for ax in col[:-1]:
- _tick_only(ax, bottom_on=True, left_on=True)
-
- # bottom
- ax = col[-1]
- _tick_only(ax, bottom_on=False, left_on=True)
-
- elif mode == "1":
- for ax in self.axes_all:
- _tick_only(ax, bottom_on=True, left_on=True)
-
- ax = self.axes_llc
- _tick_only(ax, bottom_on=False, left_on=False)
-
- def get_divider(self):
- return self._divider
-
- def set_axes_locator(self, locator):
- self._divider.set_locator(locator)
-
- def get_axes_locator(self):
- return self._divider.get_locator()
-
- def get_vsize_hsize(self):
-
- return self._divider.get_vsize_hsize()
-# from axes_size import AddList
-
-# vsize = AddList(self._divider.get_vertical())
-# hsize = AddList(self._divider.get_horizontal())
-
-# return vsize, hsize
-
-
-class ImageGrid(Grid):
- """
- A class that creates a grid of Axes. In matplotlib, the axes
- location (and size) is specified in the normalized figure
- coordinates. This may not be ideal for images that needs to be
- displayed with a given aspect ratio. For example, displaying
- images of a same size with some fixed padding between them cannot
- be easily done in matplotlib. ImageGrid is used in such case.
- """
-
- _defaultCbarAxesClass = CbarAxes
-
- def __init__(self, fig,
- rect,
- nrows_ncols,
- ngrids=None,
- direction="row",
- axes_pad=0.02,
- add_all=True,
- share_all=False,
- aspect=True,
- label_mode="L",
- cbar_mode=None,
- cbar_location="right",
- cbar_pad=None,
- cbar_size="5%",
- cbar_set_cax=True,
- axes_class=None,
- ):
- """
- Build an :class:`ImageGrid` instance with a grid nrows*ncols
- :class:`~matplotlib.axes.Axes` in
- :class:`~matplotlib.figure.Figure` *fig* with
- *rect=[left, bottom, width, height]* (in
- :class:`~matplotlib.figure.Figure` coordinates) or
- the subplot position code (e.g., "121").
-
- Optional keyword arguments:
-
- ================ ======== =========================================
- Keyword Default Description
- ================ ======== =========================================
- direction "row" [ "row" | "column" ]
- axes_pad 0.02 float| pad between axes given in inches
- or tuple-like of floats,
- (horizontal padding, vertical padding)
- add_all True bool
- share_all False bool
- aspect True bool
- label_mode "L" [ "L" | "1" | "all" ]
- cbar_mode None [ "each" | "single" | "edge" ]
- cbar_location "right" [ "left" | "right" | "bottom" | "top" ]
- cbar_pad None
- cbar_size "5%"
- cbar_set_cax True bool
- axes_class None a type object which must be a subclass
- of axes_grid's subclass of
- :class:`~matplotlib.axes.Axes`
- ================ ======== =========================================
-
- *cbar_set_cax* : if True, each axes in the grid has a cax
- attribute that is bind to associated cbar_axes.
- """
- self._nrows, self._ncols = nrows_ncols
-
- if ngrids is None:
- ngrids = self._nrows * self._ncols
- else:
- if not 0 < ngrids <= self._nrows * self._ncols:
- raise Exception
-
- self.ngrids = ngrids
-
- axes_pad = _extend_axes_pad(axes_pad)
- self._axes_pad = axes_pad
-
- self._colorbar_mode = cbar_mode
- self._colorbar_location = cbar_location
- if cbar_pad is None:
- # horizontal or vertical arrangement?
- if cbar_location in ("left", "right"):
- self._colorbar_pad = axes_pad[0]
- else:
- self._colorbar_pad = axes_pad[1]
- else:
- self._colorbar_pad = cbar_pad
-
- self._colorbar_size = cbar_size
-
- self._init_axes_pad(axes_pad)
-
- if direction not in ["column", "row"]:
- raise Exception("")
-
- self._direction = direction
-
- if axes_class is None:
- axes_class = self._defaultLocatableAxesClass
- axes_class_args = {}
- else:
- if isinstance(axes_class, maxes.Axes):
- axes_class_args = {}
- else:
- axes_class, axes_class_args = axes_class
-
- self.axes_all = []
- self.axes_column = [[] for _ in range(self._ncols)]
- self.axes_row = [[] for _ in range(self._nrows)]
-
- self.cbar_axes = []
-
- h = []
- v = []
- if isinstance(rect, six.string_types) or cbook.is_numlike(rect):
- self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v,
- aspect=aspect)
- elif isinstance(rect, SubplotSpec):
- self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v,
- aspect=aspect)
- elif len(rect) == 3:
- kw = dict(horizontal=h, vertical=v, aspect=aspect)
- self._divider = SubplotDivider(fig, *rect, **kw)
- elif len(rect) == 4:
- self._divider = Divider(fig, rect, horizontal=h, vertical=v,
- aspect=aspect)
- else:
- raise Exception("")
-
- rect = self._divider.get_position()
-
- # reference axes
- self._column_refax = [None for _ in range(self._ncols)]
- self._row_refax = [None for _ in range(self._nrows)]
- self._refax = None
-
- for i in range(self.ngrids):
-
- col, row = self._get_col_row(i)
-
- if share_all:
- if self.axes_all:
- sharex = self.axes_all[0]
- sharey = self.axes_all[0]
- else:
- sharex = None
- sharey = None
- else:
- sharex = self._column_refax[col]
- sharey = self._row_refax[row]
-
- ax = axes_class(fig, rect, sharex=sharex, sharey=sharey,
- **axes_class_args)
-
- self.axes_all.append(ax)
- self.axes_column[col].append(ax)
- self.axes_row[row].append(ax)
-
- if share_all:
- if self._refax is None:
- self._refax = ax
- if sharex is None:
- self._column_refax[col] = ax
- if sharey is None:
- self._row_refax[row] = ax
-
- cax = self._defaultCbarAxesClass(fig, rect,
- orientation=self._colorbar_location)
- self.cbar_axes.append(cax)
-
- self.axes_llc = self.axes_column[0][-1]
-
- self._update_locators()
-
- if add_all:
- for ax in self.axes_all+self.cbar_axes:
- fig.add_axes(ax)
-
- if cbar_set_cax:
- if self._colorbar_mode == "single":
- for ax in self.axes_all:
- ax.cax = self.cbar_axes[0]
- elif self._colorbar_mode == "edge":
- for index, ax in enumerate(self.axes_all):
- col, row = self._get_col_row(index)
- if self._colorbar_location in ("left", "right"):
- ax.cax = self.cbar_axes[row]
- else:
- ax.cax = self.cbar_axes[col]
- else:
- for ax, cax in zip(self.axes_all, self.cbar_axes):
- ax.cax = cax
-
- self.set_label_mode(label_mode)
-
- def _update_locators(self):
-
- h = []
- v = []
-
- h_ax_pos = []
- h_cb_pos = []
- if (self._colorbar_mode == "single" and
- self._colorbar_location in ('left', 'bottom')):
- if self._colorbar_location == "left":
- #sz = Size.Fraction(Size.AxesX(self.axes_llc), self._nrows)
- sz = Size.Fraction(self._nrows, Size.AxesX(self.axes_llc))
- h.append(Size.from_any(self._colorbar_size, sz))
- h.append(Size.from_any(self._colorbar_pad, sz))
- locator = self._divider.new_locator(nx=0, ny=0, ny1=-1)
- elif self._colorbar_location == "bottom":
- #sz = Size.Fraction(Size.AxesY(self.axes_llc), self._ncols)
- sz = Size.Fraction(self._ncols, Size.AxesY(self.axes_llc))
- v.append(Size.from_any(self._colorbar_size, sz))
- v.append(Size.from_any(self._colorbar_pad, sz))
- locator = self._divider.new_locator(nx=0, nx1=-1, ny=0)
- for i in range(self.ngrids):
- self.cbar_axes[i].set_visible(False)
- self.cbar_axes[0].set_axes_locator(locator)
- self.cbar_axes[0].set_visible(True)
-
- for col, ax in enumerate(self.axes_row[0]):
- if h:
- h.append(self._horiz_pad_size) # Size.Fixed(self._axes_pad))
-
- if ax:
- sz = Size.AxesX(ax, aspect="axes", ref_ax=self.axes_all[0])
- else:
- sz = Size.AxesX(self.axes_all[0],
- aspect="axes", ref_ax=self.axes_all[0])
-
- if (self._colorbar_mode == "each" or
- (self._colorbar_mode == 'edge' and
- col == 0)) and self._colorbar_location == "left":
- h_cb_pos.append(len(h))
- h.append(Size.from_any(self._colorbar_size, sz))
- h.append(Size.from_any(self._colorbar_pad, sz))
-
- h_ax_pos.append(len(h))
-
- h.append(sz)
-
- if ((self._colorbar_mode == "each" or
- (self._colorbar_mode == 'edge' and
- col == self._ncols - 1)) and
- self._colorbar_location == "right"):
- h.append(Size.from_any(self._colorbar_pad, sz))
- h_cb_pos.append(len(h))
- h.append(Size.from_any(self._colorbar_size, sz))
-
- v_ax_pos = []
- v_cb_pos = []
- for row, ax in enumerate(self.axes_column[0][::-1]):
- if v:
- v.append(self._vert_pad_size) # Size.Fixed(self._axes_pad))
-
- if ax:
- sz = Size.AxesY(ax, aspect="axes", ref_ax=self.axes_all[0])
- else:
- sz = Size.AxesY(self.axes_all[0],
- aspect="axes", ref_ax=self.axes_all[0])
-
- if (self._colorbar_mode == "each" or
- (self._colorbar_mode == 'edge' and
- row == 0)) and self._colorbar_location == "bottom":
- v_cb_pos.append(len(v))
- v.append(Size.from_any(self._colorbar_size, sz))
- v.append(Size.from_any(self._colorbar_pad, sz))
-
- v_ax_pos.append(len(v))
- v.append(sz)
-
- if ((self._colorbar_mode == "each" or
- (self._colorbar_mode == 'edge' and
- row == self._nrows - 1)) and
- self._colorbar_location == "top"):
- v.append(Size.from_any(self._colorbar_pad, sz))
- v_cb_pos.append(len(v))
- v.append(Size.from_any(self._colorbar_size, sz))
-
- for i in range(self.ngrids):
- col, row = self._get_col_row(i)
- #locator = self._divider.new_locator(nx=4*col,
- # ny=2*(self._nrows - row - 1))
- locator = self._divider.new_locator(nx=h_ax_pos[col],
- ny=v_ax_pos[self._nrows-1-row])
- self.axes_all[i].set_axes_locator(locator)
-
- if self._colorbar_mode == "each":
- if self._colorbar_location in ("right", "left"):
- locator = self._divider.new_locator(
- nx=h_cb_pos[col], ny=v_ax_pos[self._nrows - 1 - row])
-
- elif self._colorbar_location in ("top", "bottom"):
- locator = self._divider.new_locator(
- nx=h_ax_pos[col], ny=v_cb_pos[self._nrows - 1 - row])
-
- self.cbar_axes[i].set_axes_locator(locator)
- elif self._colorbar_mode == 'edge':
- if ((self._colorbar_location == 'left' and col == 0) or
- (self._colorbar_location == 'right'
- and col == self._ncols-1)):
- locator = self._divider.new_locator(
- nx=h_cb_pos[0], ny=v_ax_pos[self._nrows -1 - row])
- self.cbar_axes[row].set_axes_locator(locator)
- elif ((self._colorbar_location == 'bottom' and
- row == self._nrows - 1) or
- (self._colorbar_location == 'top' and row == 0)):
- locator = self._divider.new_locator(nx=h_ax_pos[col],
- ny=v_cb_pos[0])
- self.cbar_axes[col].set_axes_locator(locator)
-
- if self._colorbar_mode == "single":
- if self._colorbar_location == "right":
- #sz = Size.Fraction(Size.AxesX(self.axes_llc), self._nrows)
- sz = Size.Fraction(self._nrows, Size.AxesX(self.axes_llc))
- h.append(Size.from_any(self._colorbar_pad, sz))
- h.append(Size.from_any(self._colorbar_size, sz))
- locator = self._divider.new_locator(nx=-2, ny=0, ny1=-1)
- elif self._colorbar_location == "top":
- #sz = Size.Fraction(Size.AxesY(self.axes_llc), self._ncols)
- sz = Size.Fraction(self._ncols, Size.AxesY(self.axes_llc))
- v.append(Size.from_any(self._colorbar_pad, sz))
- v.append(Size.from_any(self._colorbar_size, sz))
- locator = self._divider.new_locator(nx=0, nx1=-1, ny=-2)
- if self._colorbar_location in ("right", "top"):
- for i in range(self.ngrids):
- self.cbar_axes[i].set_visible(False)
- self.cbar_axes[0].set_axes_locator(locator)
- self.cbar_axes[0].set_visible(True)
- elif self._colorbar_mode == "each":
- for i in range(self.ngrids):
- self.cbar_axes[i].set_visible(True)
- elif self._colorbar_mode == "edge":
- if self._colorbar_location in ('right', 'left'):
- count = self._nrows
- else:
- count = self._ncols
- for i in range(count):
- self.cbar_axes[i].set_visible(True)
- for j in range(i + 1, self.ngrids):
- self.cbar_axes[j].set_visible(False)
- else:
- for i in range(self.ngrids):
- self.cbar_axes[i].set_visible(False)
- self.cbar_axes[i].set_position([1., 1., 0.001, 0.001],
- which="active")
-
- self._divider.set_horizontal(h)
- self._divider.set_vertical(v)
-
-
-AxesGrid = ImageGrid
-
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_rgb.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_rgb.py
deleted file mode 100644
index e62d4f06154..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_rgb.py
+++ /dev/null
@@ -1,228 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-
-import numpy as np
-from .axes_divider import make_axes_locatable, Size, locatable_axes_factory
-import sys
-from .mpl_axes import Axes
-
-
-def make_rgb_axes(ax, pad=0.01, axes_class=None, add_all=True):
- """
- pad : fraction of the axes height.
- """
-
- divider = make_axes_locatable(ax)
-
- pad_size = Size.Fraction(pad, Size.AxesY(ax))
-
- xsize = Size.Fraction((1.-2.*pad)/3., Size.AxesX(ax))
- ysize = Size.Fraction((1.-2.*pad)/3., Size.AxesY(ax))
-
- divider.set_horizontal([Size.AxesX(ax), pad_size, xsize])
- divider.set_vertical([ysize, pad_size, ysize, pad_size, ysize])
-
- ax.set_axes_locator(divider.new_locator(0, 0, ny1=-1))
-
- ax_rgb = []
- if axes_class is None:
- try:
- axes_class = locatable_axes_factory(ax._axes_class)
- except AttributeError:
- axes_class = locatable_axes_factory(type(ax))
-
- for ny in [4, 2, 0]:
- ax1 = axes_class(ax.get_figure(),
- ax.get_position(original=True),
- sharex=ax, sharey=ax)
- locator = divider.new_locator(nx=2, ny=ny)
- ax1.set_axes_locator(locator)
- for t in ax1.yaxis.get_ticklabels() + ax1.xaxis.get_ticklabels():
- t.set_visible(False)
- try:
- for axis in ax1.axis.values():
- axis.major_ticklabels.set_visible(False)
- except AttributeError:
- pass
-
- ax_rgb.append(ax1)
-
- if add_all:
- fig = ax.get_figure()
- for ax1 in ax_rgb:
- fig.add_axes(ax1)
-
- return ax_rgb
-
-
-def imshow_rgb(ax, r, g, b, **kwargs):
- ny, nx = r.shape
- R = np.zeros([ny, nx, 3], dtype="d")
- R[:,:,0] = r
- G = np.zeros_like(R)
- G[:,:,1] = g
- B = np.zeros_like(R)
- B[:,:,2] = b
-
- RGB = R + G + B
-
- im_rgb = ax.imshow(RGB, **kwargs)
-
- return im_rgb
-
-
-class RGBAxesBase(object):
- """base class for a 4-panel imshow (RGB, R, G, B)
-
- Layout:
- +---------------+-----+
- | | R |
- + +-----+
- | RGB | G |
- + +-----+
- | | B |
- +---------------+-----+
-
- Attributes
- ----------
- _defaultAxesClass : matplotlib.axes.Axes
- defaults to 'Axes' in RGBAxes child class.
- No default in abstract base class
- RGB : _defaultAxesClass
- The axes object for the three-channel imshow
- R : _defaultAxesClass
- The axes object for the red channel imshow
- G : _defaultAxesClass
- The axes object for the green channel imshow
- B : _defaultAxesClass
- The axes object for the blue channel imshow
- """
- def __init__(self, *kl, **kwargs):
- """
- Parameters
- ----------
- pad : float
- fraction of the axes height to put as padding.
- defaults to 0.0
- add_all : bool
- True: Add the {rgb, r, g, b} axes to the figure
- defaults to True.
- axes_class : matplotlib.axes.Axes
-
- kl :
- Unpacked into axes_class() init for RGB
- kwargs :
- Unpacked into axes_class() init for RGB, R, G, B axes
- """
- pad = kwargs.pop("pad", 0.0)
- add_all = kwargs.pop("add_all", True)
- try:
- axes_class = kwargs.pop("axes_class", self._defaultAxesClass)
- except AttributeError:
- new_msg = ("A subclass of RGBAxesBase must have a "
- "_defaultAxesClass attribute. If you are not sure which "
- "axes class to use, consider using "
- "mpl_toolkits.axes_grid1.mpl_axes.Axes.")
- six.reraise(AttributeError, AttributeError(new_msg),
- sys.exc_info()[2])
-
- ax = axes_class(*kl, **kwargs)
-
- divider = make_axes_locatable(ax)
-
- pad_size = Size.Fraction(pad, Size.AxesY(ax))
-
- xsize = Size.Fraction((1.-2.*pad)/3., Size.AxesX(ax))
- ysize = Size.Fraction((1.-2.*pad)/3., Size.AxesY(ax))
-
- divider.set_horizontal([Size.AxesX(ax), pad_size, xsize])
- divider.set_vertical([ysize, pad_size, ysize, pad_size, ysize])
-
- ax.set_axes_locator(divider.new_locator(0, 0, ny1=-1))
-
- ax_rgb = []
- for ny in [4, 2, 0]:
- ax1 = axes_class(ax.get_figure(),
- ax.get_position(original=True),
- sharex=ax, sharey=ax, **kwargs)
- locator = divider.new_locator(nx=2, ny=ny)
- ax1.set_axes_locator(locator)
- ax1.axis[:].toggle(ticklabels=False)
- ax_rgb.append(ax1)
-
- self.RGB = ax
- self.R, self.G, self.B = ax_rgb
-
- if add_all:
- fig = ax.get_figure()
- fig.add_axes(ax)
- self.add_RGB_to_figure()
-
- self._config_axes()
-
- def _config_axes(self, line_color='w', marker_edge_color='w'):
- """Set the line color and ticks for the axes
-
- Parameters
- ----------
- line_color : any matplotlib color
- marker_edge_color : any matplotlib color
- """
- for ax1 in [self.RGB, self.R, self.G, self.B]:
- ax1.axis[:].line.set_color(line_color)
- ax1.axis[:].major_ticks.set_markeredgecolor(marker_edge_color)
-
- def add_RGB_to_figure(self):
- """Add the red, green and blue axes to the RGB composite's axes figure
- """
- self.RGB.get_figure().add_axes(self.R)
- self.RGB.get_figure().add_axes(self.G)
- self.RGB.get_figure().add_axes(self.B)
-
- def imshow_rgb(self, r, g, b, **kwargs):
- """Create the four images {rgb, r, g, b}
-
- Parameters
- ----------
- r : array-like
- The red array
- g : array-like
- The green array
- b : array-like
- The blue array
- kwargs : imshow kwargs
- kwargs get unpacked into the imshow calls for the four images
-
- Returns
- -------
- rgb : matplotlib.image.AxesImage
- r : matplotlib.image.AxesImage
- g : matplotlib.image.AxesImage
- b : matplotlib.image.AxesImage
- """
- if not (r.shape == g.shape == b.shape):
- raise ValueError('Input shapes do not match.'
- '\nr.shape = {}'
- '\ng.shape = {}'
- '\nb.shape = {}'
- .format(r.shape, g.shape, b.shape))
- RGB = np.dstack([r, g, b])
- R = np.zeros_like(RGB)
- R[:,:,0] = r
- G = np.zeros_like(RGB)
- G[:,:,1] = g
- B = np.zeros_like(RGB)
- B[:,:,2] = b
-
- im_rgb = self.RGB.imshow(RGB, **kwargs)
- im_r = self.R.imshow(R, **kwargs)
- im_g = self.G.imshow(G, **kwargs)
- im_b = self.B.imshow(B, **kwargs)
-
- return im_rgb, im_r, im_g, im_b
-
-
-class RGBAxes(RGBAxesBase):
- _defaultAxesClass = Axes
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_size.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_size.py
deleted file mode 100644
index 163a6245fef..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_size.py
+++ /dev/null
@@ -1,323 +0,0 @@
-
-"""
-provides a classes of simple units that will be used with AxesDivider
-class (or others) to determine the size of each axes. The unit
-classes define `get_size` method that returns a tuple of two floats,
-meaning relative and absolute sizes, respectively.
-
-Note that this class is nothing more than a simple tuple of two
-floats. Take a look at the Divider class to see how these two
-values are used.
-
-"""
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-
-import matplotlib.cbook as cbook
-from matplotlib.axes import Axes
-
-class _Base(object):
- "Base class"
-
- def __rmul__(self, other):
- float(other) # just to check if number if given
- return Fraction(other, self)
-
- def __add__(self, other):
- if isinstance(other, _Base):
- return Add(self, other)
- else:
- float(other)
- other = Fixed(other)
- return Add(self, other)
-
-
-class Add(_Base):
- def __init__(self, a, b):
- self._a = a
- self._b = b
-
- def get_size(self, renderer):
- a_rel_size, a_abs_size = self._a.get_size(renderer)
- b_rel_size, b_abs_size = self._b.get_size(renderer)
- return a_rel_size + b_rel_size, a_abs_size + b_abs_size
-
-class AddList(_Base):
- def __init__(self, add_list):
- self._list = add_list
-
- def get_size(self, renderer):
- sum_rel_size = sum([a.get_size(renderer)[0] for a in self._list])
- sum_abs_size = sum([a.get_size(renderer)[1] for a in self._list])
- return sum_rel_size, sum_abs_size
-
-
-class Fixed(_Base):
- "Simple fixed size with absolute part = *fixed_size* and relative part = 0"
- def __init__(self, fixed_size):
- self.fixed_size = fixed_size
-
- def get_size(self, renderer):
- rel_size = 0.
- abs_size = self.fixed_size
- return rel_size, abs_size
-
-
-class Scaled(_Base):
- "Simple scaled(?) size with absolute part = 0 and relative part = *scalable_size*"
- def __init__(self, scalable_size):
- self._scalable_size = scalable_size
-
- def get_size(self, renderer):
- rel_size = self._scalable_size
- abs_size = 0.
- return rel_size, abs_size
-
-Scalable=Scaled
-
-def _get_axes_aspect(ax):
- aspect = ax.get_aspect()
- # when aspec is "auto", consider it as 1.
- if aspect in ('normal', 'auto'):
- aspect = 1.
- elif aspect == "equal":
- aspect = 1
- else:
- aspect = float(aspect)
-
- return aspect
-
-class AxesX(_Base):
- """
- Scaled size whose relative part corresponds to the data width
- of the *axes* multiplied by the *aspect*.
- """
- def __init__(self, axes, aspect=1., ref_ax=None):
- self._axes = axes
- self._aspect = aspect
- if aspect == "axes" and ref_ax is None:
- raise ValueError("ref_ax must be set when aspect='axes'")
- self._ref_ax = ref_ax
-
- def get_size(self, renderer):
- l1, l2 = self._axes.get_xlim()
- if self._aspect == "axes":
- ref_aspect = _get_axes_aspect(self._ref_ax)
- aspect = ref_aspect/_get_axes_aspect(self._axes)
- else:
- aspect = self._aspect
-
- rel_size = abs(l2-l1)*aspect
- abs_size = 0.
- return rel_size, abs_size
-
-class AxesY(_Base):
- """
- Scaled size whose relative part corresponds to the data height
- of the *axes* multiplied by the *aspect*.
- """
- def __init__(self, axes, aspect=1., ref_ax=None):
- self._axes = axes
- self._aspect = aspect
- if aspect == "axes" and ref_ax is None:
- raise ValueError("ref_ax must be set when aspect='axes'")
- self._ref_ax = ref_ax
-
- def get_size(self, renderer):
- l1, l2 = self._axes.get_ylim()
-
- if self._aspect == "axes":
- ref_aspect = _get_axes_aspect(self._ref_ax)
- aspect = _get_axes_aspect(self._axes)
- else:
- aspect = self._aspect
-
- rel_size = abs(l2-l1)*aspect
- abs_size = 0.
- return rel_size, abs_size
-
-
-class MaxExtent(_Base):
- """
- Size whose absolute part is the largest width (or height) of
- the given *artist_list*.
- """
- def __init__(self, artist_list, w_or_h):
- self._artist_list = artist_list
-
- if w_or_h not in ["width", "height"]:
- raise ValueError()
-
- self._w_or_h = w_or_h
-
- def add_artist(self, a):
- self._artist_list.append(a)
-
- def get_size(self, renderer):
- rel_size = 0.
- w_list, h_list = [], []
- for a in self._artist_list:
- bb = a.get_window_extent(renderer)
- w_list.append(bb.width)
- h_list.append(bb.height)
- dpi = a.get_figure().get_dpi()
- if self._w_or_h == "width":
- abs_size = max(w_list)/dpi
- elif self._w_or_h == "height":
- abs_size = max(h_list)/dpi
-
- return rel_size, abs_size
-
-
-class MaxWidth(_Base):
- """
- Size whose absolute part is the largest width of
- the given *artist_list*.
- """
- def __init__(self, artist_list):
- self._artist_list = artist_list
-
- def add_artist(self, a):
- self._artist_list.append(a)
-
- def get_size(self, renderer):
- rel_size = 0.
- w_list = []
- for a in self._artist_list:
- bb = a.get_window_extent(renderer)
- w_list.append(bb.width)
- dpi = a.get_figure().get_dpi()
- abs_size = max(w_list)/dpi
-
- return rel_size, abs_size
-
-
-
-class MaxHeight(_Base):
- """
- Size whose absolute part is the largest height of
- the given *artist_list*.
- """
- def __init__(self, artist_list):
- self._artist_list = artist_list
-
- def add_artist(self, a):
- self._artist_list.append(a)
-
- def get_size(self, renderer):
- rel_size = 0.
- h_list = []
- for a in self._artist_list:
- bb = a.get_window_extent(renderer)
- h_list.append(bb.height)
- dpi = a.get_figure().get_dpi()
- abs_size = max(h_list)/dpi
-
- return rel_size, abs_size
-
-
-class Fraction(_Base):
- """
- An instance whose size is a *fraction* of the *ref_size*.
- ::
-
- >>> s = Fraction(0.3, AxesX(ax))
-
- """
- def __init__(self, fraction, ref_size):
- self._fraction_ref = ref_size
- self._fraction = fraction
-
- def get_size(self, renderer):
- if self._fraction_ref is None:
- return self._fraction, 0.
- else:
- r, a = self._fraction_ref.get_size(renderer)
- rel_size = r*self._fraction
- abs_size = a*self._fraction
- return rel_size, abs_size
-
-class Padded(_Base):
- """
- Return a instance where the absolute part of *size* is
- increase by the amount of *pad*.
- """
- def __init__(self, size, pad):
- self._size = size
- self._pad = pad
-
- def get_size(self, renderer):
- r, a = self._size.get_size(renderer)
- rel_size = r
- abs_size = a + self._pad
- return rel_size, abs_size
-
-def from_any(size, fraction_ref=None):
- """
- Creates Fixed unit when the first argument is a float, or a
- Fraction unit if that is a string that ends with %. The second
- argument is only meaningful when Fraction unit is created.::
-
- >>> a = Size.from_any(1.2) # => Size.Fixed(1.2)
- >>> Size.from_any("50%", a) # => Size.Fraction(0.5, a)
-
- """
- if cbook.is_numlike(size):
- return Fixed(size)
- elif isinstance(size, six.string_types):
- if size[-1] == "%":
- return Fraction(float(size[:-1]) / 100, fraction_ref)
-
- raise ValueError("Unknown format")
-
-
-class SizeFromFunc(_Base):
- def __init__(self, func):
- self._func = func
-
- def get_size(self, renderer):
- rel_size = 0.
-
- bb = self._func(renderer)
- dpi = renderer.points_to_pixels(72.)
- abs_size = bb/dpi
-
- return rel_size, abs_size
-
-class GetExtentHelper(object):
- def _get_left(tight_bbox, axes_bbox):
- return axes_bbox.xmin - tight_bbox.xmin
-
- def _get_right(tight_bbox, axes_bbox):
- return tight_bbox.xmax - axes_bbox.xmax
-
- def _get_bottom(tight_bbox, axes_bbox):
- return axes_bbox.ymin - tight_bbox.ymin
-
- def _get_top(tight_bbox, axes_bbox):
- return tight_bbox.ymax - axes_bbox.ymax
-
- _get_func_map = dict(left=_get_left,
- right=_get_right,
- bottom=_get_bottom,
- top=_get_top)
-
- del _get_left, _get_right, _get_bottom, _get_top
-
- def __init__(self, ax, direction):
- if isinstance(ax, Axes):
- self._ax_list = [ax]
- else:
- self._ax_list = ax
-
- try:
- self._get_func = self._get_func_map[direction]
- except KeyError:
- raise KeyError("direction must be one of left, right, bottom, top")
-
- def __call__(self, renderer):
- vl = [self._get_func(ax.get_tightbbox(renderer, False),
- ax.bbox) for ax in self._ax_list]
- return max(vl)
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/colorbar.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/colorbar.py
deleted file mode 100644
index 34bdf3618a7..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/colorbar.py
+++ /dev/null
@@ -1,836 +0,0 @@
-"""
-Colorbar toolkit with two classes and a function:
-
- :class:`ColorbarBase`
- the base class with full colorbar drawing functionality.
- It can be used as-is to make a colorbar for a given colormap;
- a mappable object (e.g., image) is not needed.
-
- :class:`Colorbar`
- the derived class for use with images or contour plots.
-
- :func:`make_axes`
- a function for resizing an axes and adding a second axes
- suitable for a colorbar
-
-The :meth:`~matplotlib.figure.Figure.colorbar` method uses :func:`make_axes`
-and :class:`Colorbar`; the :func:`~matplotlib.pyplot.colorbar` function
-is a thin wrapper over :meth:`~matplotlib.figure.Figure.colorbar`.
-"""
-
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-from six.moves import xrange, zip
-
-import numpy as np
-import matplotlib as mpl
-import matplotlib.colors as colors
-import matplotlib.cm as cm
-from matplotlib import docstring
-import matplotlib.ticker as ticker
-import matplotlib.cbook as cbook
-import matplotlib.collections as collections
-import matplotlib.contour as contour
-from matplotlib.path import Path
-from matplotlib.patches import PathPatch
-from matplotlib.transforms import Bbox
-
-
-make_axes_kw_doc = '''
-
- ============= ====================================================
- Property Description
- ============= ====================================================
- *orientation* vertical or horizontal
- *fraction* 0.15; fraction of original axes to use for colorbar
- *pad* 0.05 if vertical, 0.15 if horizontal; fraction
- of original axes between colorbar and new image axes
- *shrink* 1.0; fraction by which to shrink the colorbar
- *aspect* 20; ratio of long to short dimensions
- ============= ====================================================
-
-'''
-
-colormap_kw_doc = '''
-
- =========== ====================================================
- Property Description
- =========== ====================================================
- *extend* [ 'neither' | 'both' | 'min' | 'max' ]
- If not 'neither', make pointed end(s) for out-of-
- range values. These are set for a given colormap
- using the colormap set_under and set_over methods.
- *spacing* [ 'uniform' | 'proportional' ]
- Uniform spacing gives each discrete color the same
- space; proportional makes the space proportional to
- the data interval.
- *ticks* [ None | list of ticks | Locator object ]
- If None, ticks are determined automatically from the
- input.
- *format* [ None | format string | Formatter object ]
- If None, the
- :class:`~matplotlib.ticker.ScalarFormatter` is used.
- If a format string is given, e.g., '%.3f', that is
- used. An alternative
- :class:`~matplotlib.ticker.Formatter` object may be
- given instead.
- *drawedges* bool
- Whether to draw lines at color boundaries.
- =========== ====================================================
-
- The following will probably be useful only in the context of
- indexed colors (that is, when the mappable has norm=NoNorm()),
- or other unusual circumstances.
-
- ============ ===================================================
- Property Description
- ============ ===================================================
- *boundaries* None or a sequence
- *values* None or a sequence which must be of length 1 less
- than the sequence of *boundaries*. For each region
- delimited by adjacent entries in *boundaries*, the
- color mapped to the corresponding value in values
- will be used.
- ============ ===================================================
-
-'''
-
-colorbar_doc = '''
-
-Add a colorbar to a plot.
-
-Function signatures for the :mod:`~matplotlib.pyplot` interface; all
-but the first are also method signatures for the
-:meth:`~matplotlib.figure.Figure.colorbar` method::
-
- colorbar(**kwargs)
- colorbar(mappable, **kwargs)
- colorbar(mappable, cax=cax, **kwargs)
- colorbar(mappable, ax=ax, **kwargs)
-
-arguments:
-
- *mappable*
- the :class:`~matplotlib.image.Image`,
- :class:`~matplotlib.contour.ContourSet`, etc. to
- which the colorbar applies; this argument is mandatory for the
- :meth:`~matplotlib.figure.Figure.colorbar` method but optional for the
- :func:`~matplotlib.pyplot.colorbar` function, which sets the
- default to the current image.
-
-keyword arguments:
-
- *cax*
- None | axes object into which the colorbar will be drawn
- *ax*
- None | parent axes object from which space for a new
- colorbar axes will be stolen
-
-
-Additional keyword arguments are of two kinds:
-
- axes properties:
- %s
- colorbar properties:
- %s
-
-If *mappable* is a :class:`~matplotlib.contours.ContourSet`, its *extend*
-kwarg is included automatically.
-
-Note that the *shrink* kwarg provides a simple way to keep a vertical
-colorbar, for example, from being taller than the axes of the mappable
-to which the colorbar is attached; but it is a manual method requiring
-some trial and error. If the colorbar is too tall (or a horizontal
-colorbar is too wide) use a smaller value of *shrink*.
-
-For more precise control, you can manually specify the positions of
-the axes objects in which the mappable and the colorbar are drawn. In
-this case, do not use any of the axes properties kwargs.
-
-It is known that some vector graphics viewer (svg and pdf) renders white gaps
-between segments of the colorbar. This is due to bugs in the viewers not
-matplotlib. As a workaround the colorbar can be rendered with overlapping
-segments::
-
- cbar = colorbar()
- cbar.solids.set_edgecolor("face")
- draw()
-
-However this has negative consequences in other circumstances. Particularly with
-semi transparent images (alpha < 1) and colorbar extensions and is not enabled
-by default see (issue #1188).
-
-returns:
- :class:`~matplotlib.colorbar.Colorbar` instance; see also its base class,
- :class:`~matplotlib.colorbar.ColorbarBase`. Call the
- :meth:`~matplotlib.colorbar.ColorbarBase.set_label` method
- to label the colorbar.
-
-
-The transData of the *cax* is adjusted so that the limits in the
-longest axis actually corresponds to the limits in colorbar range. On
-the other hand, the shortest axis has a data limits of [1,2], whose
-unconventional value is to prevent underflow when log scale is used.
-''' % (make_axes_kw_doc, colormap_kw_doc)
-
-#docstring.interpd.update(colorbar_doc=colorbar_doc)
-
-
-class CbarAxesLocator(object):
- """
- CbarAxesLocator is a axes_locator for colorbar axes. It adjust the
- position of the axes to make a room for extended ends, i.e., the
- extended ends are located outside the axes area.
- """
-
- def __init__(self, locator=None, extend="neither", orientation="vertical"):
- """
- *locator* : the bbox returned from the locator is used as a
- initial axes location. If None, axes.bbox is used.
-
- *extend* : same as in ColorbarBase
- *orientation* : same as in ColorbarBase
-
- """
- self._locator = locator
- self.extesion_fraction = 0.05
- self.extend = extend
- self.orientation = orientation
-
- def get_original_position(self, axes, renderer):
- """
- get the original position of the axes.
- """
- if self._locator is None:
- bbox = axes.get_position(original=True)
- else:
- bbox = self._locator(axes, renderer)
- return bbox
-
- def get_end_vertices(self):
- """
- return a tuple of two vertices for the colorbar extended ends.
- The first vertices is for the minimum end, and the second is for
- the maximum end.
- """
- # Note that concatenating two vertices needs to make a
- # vertices for the frame.
- extesion_fraction = self.extesion_fraction
-
- corx = extesion_fraction*2.
- cory = 1./(1. - corx)
- x1, y1, w, h = 0, 0, 1, 1
- x2, y2 = x1 + w, y1 + h
- dw, dh = w*extesion_fraction, h*extesion_fraction*cory
-
- if self.extend in ["min", "both"]:
- bottom = [(x1, y1),
- (x1+w/2., y1-dh),
- (x2, y1)]
- else:
- bottom = [(x1, y1),
- (x2, y1)]
-
- if self.extend in ["max", "both"]:
- top = [(x2, y2),
- (x1+w/2., y2+dh),
- (x1, y2)]
- else:
- top = [(x2, y2),
- (x1, y2)]
-
- if self.orientation == "horizontal":
- bottom = [(y,x) for (x,y) in bottom]
- top = [(y,x) for (x,y) in top]
-
- return bottom, top
-
-
- def get_path_patch(self):
- """
- get the path for axes patch
- """
- end1, end2 = self.get_end_vertices()
-
- verts = [] + end1 + end2 + end1[:1]
-
- return Path(verts)
-
-
- def get_path_ends(self):
- """
- get the paths for extended ends
- """
-
- end1, end2 = self.get_end_vertices()
-
- return Path(end1), Path(end2)
-
-
- def __call__(self, axes, renderer):
- """
- Return the adjusted position of the axes
- """
- bbox0 = self.get_original_position(axes, renderer)
- bbox = bbox0
-
- x1, y1, w, h = bbox.bounds
- extesion_fraction = self.extesion_fraction
- dw, dh = w*extesion_fraction, h*extesion_fraction
-
- if self.extend in ["min", "both"]:
- if self.orientation == "horizontal":
- x1 = x1 + dw
- else:
- y1 = y1+dh
-
- if self.extend in ["max", "both"]:
- if self.orientation == "horizontal":
- w = w-2*dw
- else:
- h = h-2*dh
-
- return Bbox.from_bounds(x1, y1, w, h)
-
-
-
-class ColorbarBase(cm.ScalarMappable):
- '''
- Draw a colorbar in an existing axes.
-
- This is a base class for the :class:`Colorbar` class, which is the
- basis for the :func:`~matplotlib.pyplot.colorbar` method and pylab
- function.
-
- It is also useful by itself for showing a colormap. If the *cmap*
- kwarg is given but *boundaries* and *values* are left as None,
- then the colormap will be displayed on a 0-1 scale. To show the
- under- and over-value colors, specify the *norm* as::
-
- colors.Normalize(clip=False)
-
- To show the colors versus index instead of on the 0-1 scale,
- use::
-
- norm=colors.NoNorm.
-
- Useful attributes:
-
- :attr:`ax`
- the Axes instance in which the colorbar is drawn
-
- :attr:`lines`
- a LineCollection if lines were drawn, otherwise None
-
- :attr:`dividers`
- a LineCollection if *drawedges* is True, otherwise None
-
- Useful public methods are :meth:`set_label` and :meth:`add_lines`.
-
- '''
-
- def __init__(self, ax, cmap=None,
- norm=None,
- alpha=1.0,
- values=None,
- boundaries=None,
- orientation='vertical',
- extend='neither',
- spacing='uniform', # uniform or proportional
- ticks=None,
- format=None,
- drawedges=False,
- filled=True,
- ):
- self.ax = ax
-
- if cmap is None: cmap = cm.get_cmap()
- if norm is None: norm = colors.Normalize()
- self.alpha = alpha
- cm.ScalarMappable.__init__(self, cmap=cmap, norm=norm)
- self.values = values
- self.boundaries = boundaries
- self.extend = extend
- self.spacing = spacing
- self.orientation = orientation
- self.drawedges = drawedges
- self.filled = filled
-
- # artists
- self.solids = None
- self.lines = None
- self.dividers = None
- self.extension_patch1 = None
- self.extension_patch2 = None
-
- if orientation == "vertical":
- self.cbar_axis = self.ax.yaxis
- else:
- self.cbar_axis = self.ax.xaxis
-
-
- if format is None:
- if isinstance(self.norm, colors.LogNorm):
- # change both axis for proper aspect
- self.ax.set_xscale("log")
- self.ax.set_yscale("log")
- self.cbar_axis.set_minor_locator(ticker.NullLocator())
- formatter = ticker.LogFormatter()
- else:
- formatter = None
- elif isinstance(format, six.string_types):
- formatter = ticker.FormatStrFormatter(format)
- else:
- formatter = format # Assume it is a Formatter
-
- if formatter is None:
- formatter = self.cbar_axis.get_major_formatter()
- else:
- self.cbar_axis.set_major_formatter(formatter)
-
- if cbook.iterable(ticks):
- self.cbar_axis.set_ticks(ticks)
- elif ticks is not None:
- self.cbar_axis.set_major_locator(ticks)
- else:
- self._select_locator(formatter)
-
-
- self._config_axes()
-
- self.update_artists()
-
- self.set_label_text('')
-
-
- def _get_colorbar_limits(self):
- """
- initial limits for colorbar range. The returned min, max values
- will be used to create colorbar solid(?) and etc.
- """
- if self.boundaries is not None:
- C = self.boundaries
- if self.extend in ["min", "both"]:
- C = C[1:]
-
- if self.extend in ["max", "both"]:
- C = C[:-1]
- return min(C), max(C)
- else:
- return self.get_clim()
-
-
- def _config_axes(self):
- '''
- Adjust the properties of the axes to be adequate for colorbar display.
- '''
- ax = self.ax
-
- axes_locator = CbarAxesLocator(ax.get_axes_locator(),
- extend=self.extend,
- orientation=self.orientation)
- ax.set_axes_locator(axes_locator)
-
- # override the get_data_ratio for the aspect works.
- def _f():
- return 1.
- ax.get_data_ratio = _f
- ax.get_data_ratio_log = _f
-
- ax.set_frame_on(True)
- ax.set_navigate(False)
-
- self.ax.set_autoscalex_on(False)
- self.ax.set_autoscaley_on(False)
-
- if self.orientation == 'horizontal':
- ax.xaxis.set_label_position('bottom')
- ax.set_yticks([])
- else:
- ax.set_xticks([])
- ax.yaxis.set_label_position('right')
- ax.yaxis.set_ticks_position('right')
-
-
-
- def update_artists(self):
- """
- Update the colorbar associated artists, *filled* and
- *ends*. Note that *lines* are not updated. This needs to be
- called whenever clim of associated image changes.
- """
- self._process_values()
- self._add_ends()
-
- X, Y = self._mesh()
- if self.filled:
- C = self._values[:,np.newaxis]
- self._add_solids(X, Y, C)
-
- ax = self.ax
- vmin, vmax = self._get_colorbar_limits()
- if self.orientation == 'horizontal':
- ax.set_ylim(1, 2)
- ax.set_xlim(vmin, vmax)
- else:
- ax.set_xlim(1, 2)
- ax.set_ylim(vmin, vmax)
-
-
- def _add_ends(self):
- """
- Create patches from extended ends and add them to the axes.
- """
-
- del self.extension_patch1
- del self.extension_patch2
-
- path1, path2 = self.ax.get_axes_locator().get_path_ends()
- fc=mpl.rcParams['axes.facecolor']
- ec=mpl.rcParams['axes.edgecolor']
- linewidths=0.5*mpl.rcParams['axes.linewidth']
- self.extension_patch1 = PathPatch(path1,
- fc=fc, ec=ec, lw=linewidths,
- zorder=2.,
- transform=self.ax.transAxes,
- clip_on=False)
- self.extension_patch2 = PathPatch(path2,
- fc=fc, ec=ec, lw=linewidths,
- zorder=2.,
- transform=self.ax.transAxes,
- clip_on=False)
- self.ax.add_artist(self.extension_patch1)
- self.ax.add_artist(self.extension_patch2)
-
-
-
- def _set_label_text(self):
- """
- set label.
- """
- self.cbar_axis.set_label_text(self._label, **self._labelkw)
-
- def set_label_text(self, label, **kw):
- '''
- Label the long axis of the colorbar
- '''
- self._label = label
- self._labelkw = kw
- self._set_label_text()
-
-
- def _edges(self, X, Y):
- '''
- Return the separator line segments; helper for _add_solids.
- '''
- N = X.shape[0]
- # Using the non-array form of these line segments is much
- # simpler than making them into arrays.
- if self.orientation == 'vertical':
- return [list(zip(X[i], Y[i])) for i in xrange(1, N-1)]
- else:
- return [list(zip(Y[i], X[i])) for i in xrange(1, N-1)]
-
- def _add_solids(self, X, Y, C):
- '''
- Draw the colors using :meth:`~matplotlib.axes.Axes.pcolormesh`;
- optionally add separators.
- '''
- ## Change to pcolorfast after fixing bugs in some backends...
-
- if self.extend in ["min", "both"]:
- cc = self.to_rgba([C[0][0]])
- self.extension_patch1.set_fc(cc[0])
- X, Y, C = X[1:], Y[1:], C[1:]
-
- if self.extend in ["max", "both"]:
- cc = self.to_rgba([C[-1][0]])
- self.extension_patch2.set_fc(cc[0])
- X, Y, C = X[:-1], Y[:-1], C[:-1]
-
- if self.orientation == 'vertical':
- args = (X, Y, C)
- else:
- args = (np.transpose(Y), np.transpose(X), np.transpose(C))
- kw = {'cmap':self.cmap, 'norm':self.norm,
- 'shading':'flat', 'alpha':self.alpha,
- }
-
- del self.solids
- del self.dividers
-
- col = self.ax.pcolormesh(*args, **kw)
-
- self.solids = col
- if self.drawedges:
- self.dividers = collections.LineCollection(self._edges(X,Y),
- colors=(mpl.rcParams['axes.edgecolor'],),
- linewidths=(0.5*mpl.rcParams['axes.linewidth'],),
- )
- self.ax.add_collection(self.dividers)
- else:
- self.dividers = None
-
- def add_lines(self, levels, colors, linewidths):
- '''
- Draw lines on the colorbar. It deletes preexisting lines.
- '''
- del self.lines
-
- N = len(levels)
- x = np.array([1.0, 2.0])
- X, Y = np.meshgrid(x,levels)
- if self.orientation == 'vertical':
- xy = [list(zip(X[i], Y[i])) for i in xrange(N)]
- else:
- xy = [list(zip(Y[i], X[i])) for i in xrange(N)]
- col = collections.LineCollection(xy, linewidths=linewidths,
- )
- self.lines = col
- col.set_color(colors)
- self.ax.add_collection(col)
-
-
- def _select_locator(self, formatter):
- '''
- select a suitable locator
- '''
- if self.boundaries is None:
- if isinstance(self.norm, colors.NoNorm):
- nv = len(self._values)
- base = 1 + int(nv/10)
- locator = ticker.IndexLocator(base=base, offset=0)
- elif isinstance(self.norm, colors.BoundaryNorm):
- b = self.norm.boundaries
- locator = ticker.FixedLocator(b, nbins=10)
- elif isinstance(self.norm, colors.LogNorm):
- locator = ticker.LogLocator()
- else:
- locator = ticker.MaxNLocator(nbins=5)
- else:
- b = self._boundaries[self._inside]
- locator = ticker.FixedLocator(b) #, nbins=10)
-
- self.cbar_axis.set_major_locator(locator)
-
-
- def _process_values(self, b=None):
- '''
- Set the :attr:`_boundaries` and :attr:`_values` attributes
- based on the input boundaries and values. Input boundaries
- can be *self.boundaries* or the argument *b*.
- '''
- if b is None:
- b = self.boundaries
- if b is not None:
- self._boundaries = np.asarray(b, dtype=float)
- if self.values is None:
- self._values = 0.5*(self._boundaries[:-1]
- + self._boundaries[1:])
- if isinstance(self.norm, colors.NoNorm):
- self._values = (self._values + 0.00001).astype(np.int16)
- return
- self._values = np.array(self.values)
- return
- if self.values is not None:
- self._values = np.array(self.values)
- if self.boundaries is None:
- b = np.zeros(len(self.values)+1, 'd')
- b[1:-1] = 0.5*(self._values[:-1] - self._values[1:])
- b[0] = 2.0*b[1] - b[2]
- b[-1] = 2.0*b[-2] - b[-3]
- self._boundaries = b
- return
- self._boundaries = np.array(self.boundaries)
- return
- # Neither boundaries nor values are specified;
- # make reasonable ones based on cmap and norm.
- if isinstance(self.norm, colors.NoNorm):
- b = self._uniform_y(self.cmap.N+1) * self.cmap.N - 0.5
- v = np.zeros((len(b)-1,), dtype=np.int16)
- v = np.arange(self.cmap.N, dtype=np.int16)
- self._boundaries = b
- self._values = v
- return
- elif isinstance(self.norm, colors.BoundaryNorm):
- b = np.array(self.norm.boundaries)
- v = np.zeros((len(b)-1,), dtype=float)
- bi = self.norm.boundaries
- v = 0.5*(bi[:-1] + bi[1:])
- self._boundaries = b
- self._values = v
- return
- else:
- b = self._uniform_y(self.cmap.N+1)
-
- self._process_values(b)
-
-
- def _uniform_y(self, N):
- '''
- Return colorbar data coordinates for *N* uniformly
- spaced boundaries.
- '''
- vmin, vmax = self._get_colorbar_limits()
- if isinstance(self.norm, colors.LogNorm):
- y = np.logspace(np.log10(vmin), np.log10(vmax), N)
- else:
- y = np.linspace(vmin, vmax, N)
- return y
-
- def _mesh(self):
- '''
- Return X,Y, the coordinate arrays for the colorbar pcolormesh.
- These are suitable for a vertical colorbar; swapping and
- transposition for a horizontal colorbar are done outside
- this function.
- '''
- x = np.array([1.0, 2.0])
- if self.spacing == 'uniform':
- y = self._uniform_y(len(self._boundaries))
- else:
- y = self._boundaries
- self._y = y
-
- X, Y = np.meshgrid(x,y)
- return X, Y
-
-
- def set_alpha(self, alpha):
- """
- set alpha value.
- """
- self.alpha = alpha
-
-
-class Colorbar(ColorbarBase):
- def __init__(self, ax, mappable, **kw):
- mappable.autoscale_None() # Ensure mappable.norm.vmin, vmax
- # are set when colorbar is called,
- # even if mappable.draw has not yet
- # been called. This will not change
- # vmin, vmax if they are already set.
- self.mappable = mappable
- kw['cmap'] = mappable.cmap
- kw['norm'] = mappable.norm
- kw['alpha'] = mappable.get_alpha()
- if isinstance(mappable, contour.ContourSet):
- CS = mappable
- kw['boundaries'] = CS._levels
- kw['values'] = CS.cvalues
- kw['extend'] = CS.extend
- #kw['ticks'] = CS._levels
- kw.setdefault('ticks', ticker.FixedLocator(CS.levels, nbins=10))
- kw['filled'] = CS.filled
- ColorbarBase.__init__(self, ax, **kw)
- if not CS.filled:
- self.add_lines(CS)
- else:
- ColorbarBase.__init__(self, ax, **kw)
-
-
- def add_lines(self, CS):
- '''
- Add the lines from a non-filled
- :class:`~matplotlib.contour.ContourSet` to the colorbar.
- '''
- if not isinstance(CS, contour.ContourSet) or CS.filled:
- raise ValueError('add_lines is only for a ContourSet of lines')
- tcolors = [c[0] for c in CS.tcolors]
- tlinewidths = [t[0] for t in CS.tlinewidths]
- # The following was an attempt to get the colorbar lines
- # to follow subsequent changes in the contour lines,
- # but more work is needed: specifically, a careful
- # look at event sequences, and at how
- # to make one object track another automatically.
- #tcolors = [col.get_colors()[0] for col in CS.collections]
- #tlinewidths = [col.get_linewidth()[0] for lw in CS.collections]
- ColorbarBase.add_lines(self, CS.levels, tcolors, tlinewidths)
-
- def update_bruteforce(self, mappable):
- """
- Update the colorbar artists to reflect the change of the
- associated mappable.
- """
- self.update_artists()
-
- if isinstance(mappable, contour.ContourSet):
- if not mappable.filled:
- self.add_lines(mappable)
-
[email protected](make_axes_kw_doc)
-def make_axes(parent, **kw):
- '''
- Resize and reposition a parent axes, and return a child
- axes suitable for a colorbar
-
- ::
-
- cax, kw = make_axes(parent, **kw)
-
- Keyword arguments may include the following (with defaults):
-
- *orientation*
- 'vertical' or 'horizontal'
-
- %s
-
- All but the first of these are stripped from the input kw set.
-
- Returns (cax, kw), the child axes and the reduced kw dictionary.
- '''
- orientation = kw.setdefault('orientation', 'vertical')
- fraction = kw.pop('fraction', 0.15)
- shrink = kw.pop('shrink', 1.0)
- aspect = kw.pop('aspect', 20)
- #pb = transforms.PBox(parent.get_position())
- pb = parent.get_position(original=True).frozen()
- if orientation == 'vertical':
- pad = kw.pop('pad', 0.05)
- x1 = 1.0-fraction
- pb1, pbx, pbcb = pb.splitx(x1-pad, x1)
- pbcb = pbcb.shrunk(1.0, shrink).anchored('C', pbcb)
- anchor = (0.0, 0.5)
- panchor = (1.0, 0.5)
- else:
- pad = kw.pop('pad', 0.15)
- pbcb, pbx, pb1 = pb.splity(fraction, fraction+pad)
- pbcb = pbcb.shrunk(shrink, 1.0).anchored('C', pbcb)
- aspect = 1.0/aspect
- anchor = (0.5, 1.0)
- panchor = (0.5, 0.0)
- parent.set_position(pb1)
- parent.set_anchor(panchor)
- fig = parent.get_figure()
- cax = fig.add_axes(pbcb)
- cax.set_aspect(aspect, anchor=anchor, adjustable='box')
- return cax, kw
-
[email protected](colorbar_doc)
-def colorbar(mappable, cax=None, ax=None, **kw):
- """
- Create a colorbar for a ScalarMappable instance.
-
- Documentation for the pylab thin wrapper:
-
- %s
- """
- import matplotlib.pyplot as plt
- if ax is None:
- ax = plt.gca()
- if cax is None:
- cax, kw = make_axes(ax, **kw)
- cax._hold = True
- cb = Colorbar(cax, mappable, **kw)
-
- def on_changed(m):
- cb.set_cmap(m.get_cmap())
- cb.set_clim(m.get_clim())
- cb.update_bruteforce(m)
-
- cbid = mappable.callbacksSM.connect('changed', on_changed)
- mappable.colorbar = cb
- ax.figure.sca(ax)
- return cb
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/inset_locator.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/inset_locator.py
deleted file mode 100644
index 9aeedcb0888..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/inset_locator.py
+++ /dev/null
@@ -1,659 +0,0 @@
-"""
-A collection of functions and objects for creating or placing inset axes.
-"""
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import warnings
-from matplotlib import docstring
-import six
-from matplotlib.offsetbox import AnchoredOffsetbox
-from matplotlib.patches import Patch, Rectangle
-from matplotlib.path import Path
-from matplotlib.transforms import Bbox, BboxTransformTo
-from matplotlib.transforms import IdentityTransform, TransformedBbox
-
-from . import axes_size as Size
-from .parasite_axes import HostAxes
-
-
-class InsetPosition(object):
- @docstring.dedent_interpd
- def __init__(self, parent, lbwh):
- """
- An object for positioning an inset axes.
-
- This is created by specifying the normalized coordinates in the axes,
- instead of the figure.
-
- Parameters
- ----------
- parent : `matplotlib.axes.Axes`
- Axes to use for normalizing coordinates.
-
- lbwh : iterable of four floats
- The left edge, bottom edge, width, and height of the inset axes, in
- units of the normalized coordinate of the *parent* axes.
-
- See Also
- --------
- :meth:`matplotlib.axes.Axes.set_axes_locator`
-
- Examples
- --------
- The following bounds the inset axes to a box with 20%% of the parent
- axes's height and 40%% of the width. The size of the axes specified
- ([0, 0, 1, 1]) ensures that the axes completely fills the bounding box:
-
- >>> parent_axes = plt.gca()
- >>> ax_ins = plt.axes([0, 0, 1, 1])
- >>> ip = InsetPosition(ax, [0.5, 0.1, 0.4, 0.2])
- >>> ax_ins.set_axes_locator(ip)
- """
- self.parent = parent
- self.lbwh = lbwh
-
- def __call__(self, ax, renderer):
- bbox_parent = self.parent.get_position(original=False)
- trans = BboxTransformTo(bbox_parent)
- bbox_inset = Bbox.from_bounds(*self.lbwh)
- bb = TransformedBbox(bbox_inset, trans)
- return bb
-
-
-class AnchoredLocatorBase(AnchoredOffsetbox):
- def __init__(self, bbox_to_anchor, offsetbox, loc,
- borderpad=0.5, bbox_transform=None):
- super(AnchoredLocatorBase, self).__init__(
- loc, pad=0., child=None, borderpad=borderpad,
- bbox_to_anchor=bbox_to_anchor, bbox_transform=bbox_transform
- )
-
- def draw(self, renderer):
- raise RuntimeError("No draw method should be called")
-
- def __call__(self, ax, renderer):
- self.axes = ax
-
- fontsize = renderer.points_to_pixels(self.prop.get_size_in_points())
- self._update_offset_func(renderer, fontsize)
-
- width, height, xdescent, ydescent = self.get_extent(renderer)
-
- px, py = self.get_offset(width, height, 0, 0, renderer)
- bbox_canvas = Bbox.from_bounds(px, py, width, height)
- tr = ax.figure.transFigure.inverted()
- bb = TransformedBbox(bbox_canvas, tr)
-
- return bb
-
-
-class AnchoredSizeLocator(AnchoredLocatorBase):
- def __init__(self, bbox_to_anchor, x_size, y_size, loc,
- borderpad=0.5, bbox_transform=None):
-
- super(AnchoredSizeLocator, self).__init__(
- bbox_to_anchor, None, loc,
- borderpad=borderpad, bbox_transform=bbox_transform
- )
-
- self.x_size = Size.from_any(x_size)
- self.y_size = Size.from_any(y_size)
-
- def get_extent(self, renderer):
- x, y, w, h = self.get_bbox_to_anchor().bounds
-
- dpi = renderer.points_to_pixels(72.)
-
- r, a = self.x_size.get_size(renderer)
- width = w * r + a * dpi
-
- r, a = self.y_size.get_size(renderer)
- height = h * r + a * dpi
- xd, yd = 0, 0
-
- fontsize = renderer.points_to_pixels(self.prop.get_size_in_points())
- pad = self.pad * fontsize
-
- return width + 2 * pad, height + 2 * pad, xd + pad, yd + pad
-
-
-class AnchoredZoomLocator(AnchoredLocatorBase):
- def __init__(self, parent_axes, zoom, loc,
- borderpad=0.5,
- bbox_to_anchor=None,
- bbox_transform=None):
- self.parent_axes = parent_axes
- self.zoom = zoom
-
- if bbox_to_anchor is None:
- bbox_to_anchor = parent_axes.bbox
-
- super(AnchoredZoomLocator, self).__init__(
- bbox_to_anchor, None, loc, borderpad=borderpad,
- bbox_transform=bbox_transform)
-
- def get_extent(self, renderer):
- bb = TransformedBbox(self.axes.viewLim,
- self.parent_axes.transData)
-
- x, y, w, h = bb.bounds
- fontsize = renderer.points_to_pixels(self.prop.get_size_in_points())
- pad = self.pad * fontsize
-
- return abs(w * self.zoom) + 2 * pad, abs(h * self.zoom) + 2 * pad, pad, pad
-
-
-class BboxPatch(Patch):
- @docstring.dedent_interpd
- def __init__(self, bbox, **kwargs):
- """
- Patch showing the shape bounded by a Bbox.
-
- Parameters
- ----------
- bbox : `matplotlib.transforms.Bbox`
- Bbox to use for the extents of this patch.
-
- **kwargs
- Patch properties. Valid arguments include:
- %(Patch)s
- """
- if "transform" in kwargs:
- raise ValueError("transform should not be set")
-
- kwargs["transform"] = IdentityTransform()
- Patch.__init__(self, **kwargs)
- self.bbox = bbox
-
- def get_path(self):
- x0, y0, x1, y1 = self.bbox.extents
-
- verts = [(x0, y0),
- (x1, y0),
- (x1, y1),
- (x0, y1),
- (x0, y0),
- (0, 0)]
-
- codes = [Path.MOVETO,
- Path.LINETO,
- Path.LINETO,
- Path.LINETO,
- Path.LINETO,
- Path.CLOSEPOLY]
-
- return Path(verts, codes)
-
- get_path.__doc__ = Patch.get_path.__doc__
-
-
-class BboxConnector(Patch):
- @staticmethod
- def get_bbox_edge_pos(bbox, loc):
- """
- Helper function to obtain the location of a corner of a bbox
-
- Parameters
- ----------
- bbox : `matplotlib.transforms.Bbox`
-
- loc : {1, 2, 3, 4}
- Corner of *bbox*. Valid values are::
-
- 'upper right' : 1,
- 'upper left' : 2,
- 'lower left' : 3,
- 'lower right' : 4
-
- Returns
- -------
- x, y : float
- Coordinates of the corner specified by *loc*.
- """
- x0, y0, x1, y1 = bbox.extents
- if loc == 1:
- return x1, y1
- elif loc == 2:
- return x0, y1
- elif loc == 3:
- return x0, y0
- elif loc == 4:
- return x1, y0
-
- @staticmethod
- def connect_bbox(bbox1, bbox2, loc1, loc2=None):
- """
- Helper function to obtain a Path from one bbox to another.
-
- Parameters
- ----------
- bbox1, bbox2 : `matplotlib.transforms.Bbox`
- Bounding boxes to connect.
-
- loc1 : {1, 2, 3, 4}
- Corner of *bbox1* to use. Valid values are::
-
- 'upper right' : 1,
- 'upper left' : 2,
- 'lower left' : 3,
- 'lower right' : 4
-
- loc2 : {1, 2, 3, 4}, optional
- Corner of *bbox2* to use. If None, defaults to *loc1*.
- Valid values are::
-
- 'upper right' : 1,
- 'upper left' : 2,
- 'lower left' : 3,
- 'lower right' : 4
-
- Returns
- -------
- path : `matplotlib.path.Path`
- A line segment from the *loc1* corner of *bbox1* to the *loc2*
- corner of *bbox2*.
- """
- if isinstance(bbox1, Rectangle):
- transform = bbox1.get_transfrom()
- bbox1 = Bbox.from_bounds(0, 0, 1, 1)
- bbox1 = TransformedBbox(bbox1, transform)
-
- if isinstance(bbox2, Rectangle):
- transform = bbox2.get_transform()
- bbox2 = Bbox.from_bounds(0, 0, 1, 1)
- bbox2 = TransformedBbox(bbox2, transform)
-
- if loc2 is None:
- loc2 = loc1
-
- x1, y1 = BboxConnector.get_bbox_edge_pos(bbox1, loc1)
- x2, y2 = BboxConnector.get_bbox_edge_pos(bbox2, loc2)
-
- verts = [[x1, y1], [x2, y2]]
- codes = [Path.MOVETO, Path.LINETO]
-
- return Path(verts, codes)
-
- @docstring.dedent_interpd
- def __init__(self, bbox1, bbox2, loc1, loc2=None, **kwargs):
- """
- Connect two bboxes with a straight line.
-
- Parameters
- ----------
- bbox1, bbox2 : `matplotlib.transforms.Bbox`
- Bounding boxes to connect.
-
- loc1 : {1, 2, 3, 4}
- Corner of *bbox1* to draw the line. Valid values are::
-
- 'upper right' : 1,
- 'upper left' : 2,
- 'lower left' : 3,
- 'lower right' : 4
-
- loc2 : {1, 2, 3, 4}, optional
- Corner of *bbox2* to draw the line. If None, defaults to *loc1*.
- Valid values are::
-
- 'upper right' : 1,
- 'upper left' : 2,
- 'lower left' : 3,
- 'lower right' : 4
-
- **kwargs
- Patch properties for the line drawn. Valid arguments include:
- %(Patch)s
- """
- if "transform" in kwargs:
- raise ValueError("transform should not be set")
-
- kwargs["transform"] = IdentityTransform()
- Patch.__init__(self, fill=False, **kwargs)
- self.bbox1 = bbox1
- self.bbox2 = bbox2
- self.loc1 = loc1
- self.loc2 = loc2
-
- def get_path(self):
- return self.connect_bbox(self.bbox1, self.bbox2,
- self.loc1, self.loc2)
-
- get_path.__doc__ = Patch.get_path.__doc__
-
-
-class BboxConnectorPatch(BboxConnector):
- @docstring.dedent_interpd
- def __init__(self, bbox1, bbox2, loc1a, loc2a, loc1b, loc2b, **kwargs):
- """
- Connect two bboxes with a quadrilateral.
-
- The quadrilateral is specified by two lines that start and end at corners
- of the bboxes. The four sides of the quadrilateral are defined by the two
- lines given, the line between the two corners specified in *bbox1* and the
- line between the two corners specified in *bbox2*.
-
- Parameters
- ----------
- bbox1, bbox2 : `matplotlib.transforms.Bbox`
- Bounding boxes to connect.
-
- loc1a, loc2a : {1, 2, 3, 4}
- Corners of *bbox1* and *bbox2* to draw the first line.
- Valid values are::
-
- 'upper right' : 1,
- 'upper left' : 2,
- 'lower left' : 3,
- 'lower right' : 4
-
- loc1b, loc2b : {1, 2, 3, 4}
- Corners of *bbox1* and *bbox2* to draw the second line.
- Valid values are::
-
- 'upper right' : 1,
- 'upper left' : 2,
- 'lower left' : 3,
- 'lower right' : 4
-
- **kwargs
- Patch properties for the line drawn:
- %(Patch)s
- """
- if "transform" in kwargs:
- raise ValueError("transform should not be set")
- BboxConnector.__init__(self, bbox1, bbox2, loc1a, loc2a, **kwargs)
- self.loc1b = loc1b
- self.loc2b = loc2b
-
- def get_path(self):
- path1 = self.connect_bbox(self.bbox1, self.bbox2, self.loc1, self.loc2)
- path2 = self.connect_bbox(self.bbox2, self.bbox1,
- self.loc2b, self.loc1b)
- path_merged = (list(path1.vertices) +
- list(path2.vertices) +
- [path1.vertices[0]])
- return Path(path_merged)
-
- get_path.__doc__ = BboxConnector.get_path.__doc__
-
-
-def _add_inset_axes(parent_axes, inset_axes):
- """Helper function to add an inset axes and disable navigation in it"""
- parent_axes.figure.add_axes(inset_axes)
- inset_axes.set_navigate(False)
-
-
-def inset_axes(parent_axes, width, height, loc=1,
- bbox_to_anchor=None, bbox_transform=None,
- axes_class=None,
- axes_kwargs=None,
- borderpad=0.5):
- """
- Create an inset axes with a given width and height.
-
- Both sizes used can be specified either in inches or percentage.
- For example,::
-
- inset_axes(parent_axes, width='40%%', height='30%%', loc=3)
-
- creates in inset axes in the lower left corner of *parent_axes* which spans
- over 30%% in height and 40%% in width of the *parent_axes*. Since the usage
- of `.inset_axes` may become slightly tricky when exceeding such standard
- cases, it is recommended to read
- :ref:`the examples <sphx_glr_gallery_axes_grid1_inset_locator_demo.py>`.
-
- Parameters
- ----------
- parent_axes : `matplotlib.axes.Axes`
- Axes to place the inset axes.
-
- width, height : float or str
- Size of the inset axes to create. If a float is provided, it is
- the size in inches, e.g. *width=1.3*. If a string is provided, it is
- the size in relative units, e.g. *width='40%%'*. By default, i.e. if
- neither *bbox_to_anchor* nor *bbox_transform* are specified, those
- are relative to the parent_axes. Otherwise they are to be understood
- relative to the bounding box provided via *bbox_to_anchor*.
-
- loc : int or string, optional, default to 1
- Location to place the inset axes. The valid locations are::
-
- 'upper right' : 1,
- 'upper left' : 2,
- 'lower left' : 3,
- 'lower right' : 4,
- 'right' : 5,
- 'center left' : 6,
- 'center right' : 7,
- 'lower center' : 8,
- 'upper center' : 9,
- 'center' : 10
-
- bbox_to_anchor : tuple or `matplotlib.transforms.BboxBase`, optional
- Bbox that the inset axes will be anchored to. If None,
- *parent_axes.bbox* is used. If a tuple, can be either
- [left, bottom, width, height], or [left, bottom].
- If the kwargs *width* and/or *height* are specified in relative units,
- the 2-tuple [left, bottom] cannot be used. Note that
- the units of the bounding box are determined through the transform
- in use. When using *bbox_to_anchor* it almost always makes sense to
- also specify a *bbox_transform*. This might often be the axes transform
- *parent_axes.transAxes*.
-
- bbox_transform : `matplotlib.transforms.Transform`, optional
- Transformation for the bbox that contains the inset axes.
- If None, a `.transforms.IdentityTransform` is used (i.e. pixel
- coordinates). This is useful when not providing any argument to
- *bbox_to_anchor*. When using *bbox_to_anchor* it almost always makes
- sense to also specify a *bbox_transform*. This might often be the
- axes transform *parent_axes.transAxes*. Inversely, when specifying
- the axes- or figure-transform here, be aware that not specifying
- *bbox_to_anchor* will use *parent_axes.bbox*, the units of which are
- in display (pixel) coordinates.
-
- axes_class : `matplotlib.axes.Axes` type, optional
- If specified, the inset axes created will be created with this class's
- constructor.
-
- axes_kwargs : dict, optional
- Keyworded arguments to pass to the constructor of the inset axes.
- Valid arguments include:
- %(Axes)s
-
- borderpad : float, optional
- Padding between inset axes and the bbox_to_anchor. Defaults to 0.5.
- The units are axes font size, i.e. for a default font size of 10 points
- *borderpad = 0.5* is equivalent to a padding of 5 points.
-
- Returns
- -------
- inset_axes : `axes_class`
- Inset axes object created.
- """
-
- if axes_class is None:
- axes_class = HostAxes
-
- if axes_kwargs is None:
- inset_axes = axes_class(parent_axes.figure, parent_axes.get_position())
- else:
- inset_axes = axes_class(parent_axes.figure, parent_axes.get_position(),
- **axes_kwargs)
-
- if bbox_transform in [parent_axes.transAxes,
- parent_axes.figure.transFigure]:
- if bbox_to_anchor is None:
- warnings.warn("Using the axes or figure transform requires a "
- "bounding box in the respective coordinates. "
- "Using bbox_to_anchor=(0,0,1,1) now.")
- bbox_to_anchor = (0, 0, 1, 1)
-
- if bbox_to_anchor is None:
- bbox_to_anchor = parent_axes.bbox
-
- if isinstance(bbox_to_anchor, tuple) and \
- (isinstance(width, str) or isinstance(height, str)):
- if len(bbox_to_anchor) != 4:
- raise ValueError("Using relative units for width or height "
- "requires to provide a 4-tuple or a "
- "`BBox` instance to `bbox_to_anchor.")
-
- axes_locator = AnchoredSizeLocator(bbox_to_anchor,
- width, height,
- loc=loc,
- bbox_transform=bbox_transform,
- borderpad=borderpad)
-
- inset_axes.set_axes_locator(axes_locator)
-
- _add_inset_axes(parent_axes, inset_axes)
-
- return inset_axes
-
-
-def zoomed_inset_axes(parent_axes, zoom, loc=1,
- bbox_to_anchor=None, bbox_transform=None,
- axes_class=None,
- axes_kwargs=None,
- borderpad=0.5):
- """
- Create an anchored inset axes by scaling a parent axes. For usage, also see
- :ref:`the examples <sphx_glr_gallery_axes_grid1_inset_locator_demo2.py>`.
-
- Parameters
- ----------
- parent_axes : `matplotlib.axes.Axes`
- Axes to place the inset axes.
-
- zoom : float
- Scaling factor of the data axes. *zoom* > 1 will enlargen the
- coordinates (i.e., "zoomed in"), while *zoom* < 1 will shrink the
- coordinates (i.e., "zoomed out").
-
- loc : int or string, optional, default to 1
- Location to place the inset axes. The valid locations are::
-
- 'upper right' : 1,
- 'upper left' : 2,
- 'lower left' : 3,
- 'lower right' : 4,
- 'right' : 5,
- 'center left' : 6,
- 'center right' : 7,
- 'lower center' : 8,
- 'upper center' : 9,
- 'center' : 10
-
- bbox_to_anchor : tuple or `matplotlib.transforms.BboxBase`, optional
- Bbox that the inset axes will be anchored to. If None,
- *parent_axes.bbox* is used. If a tuple, can be either
- [left, bottom, width, height], or [left, bottom].
- If the kwargs *width* and/or *height* are specified in relative units,
- the 2-tuple [left, bottom] cannot be used. Note that
- the units of the bounding box are determined through the transform
- in use. When using *bbox_to_anchor* it almost always makes sense to
- also specify a *bbox_transform*. This might often be the axes transform
- *parent_axes.transAxes*.
-
- bbox_transform : `matplotlib.transforms.Transform`, optional
- Transformation for the bbox that contains the inset axes.
- If None, a `.transforms.IdentityTransform` is used (i.e. pixel
- coordinates). This is useful when not providing any argument to
- *bbox_to_anchor*. When using *bbox_to_anchor* it almost always makes
- sense to also specify a *bbox_transform*. This might often be the
- axes transform *parent_axes.transAxes*. Inversely, when specifying
- the axes- or figure-transform here, be aware that not specifying
- *bbox_to_anchor* will use *parent_axes.bbox*, the units of which are
- in display (pixel) coordinates.
-
- axes_class : `matplotlib.axes.Axes` type, optional
- If specified, the inset axes created will be created with this class's
- constructor.
-
- axes_kwargs : dict, optional
- Keyworded arguments to pass to the constructor of the inset axes.
- Valid arguments include:
- %(Axes)s
-
- borderpad : float, optional
- Padding between inset axes and the bbox_to_anchor. Defaults to 0.5.
- The units are axes font size, i.e. for a default font size of 10 points
- *borderpad = 0.5* is equivalent to a padding of 5 points.
-
- Returns
- -------
- inset_axes : `axes_class`
- Inset axes object created.
- """
-
- if axes_class is None:
- axes_class = HostAxes
-
- if axes_kwargs is None:
- inset_axes = axes_class(parent_axes.figure, parent_axes.get_position())
- else:
- inset_axes = axes_class(parent_axes.figure, parent_axes.get_position(),
- **axes_kwargs)
-
- axes_locator = AnchoredZoomLocator(parent_axes, zoom=zoom, loc=loc,
- bbox_to_anchor=bbox_to_anchor,
- bbox_transform=bbox_transform,
- borderpad=borderpad)
- inset_axes.set_axes_locator(axes_locator)
-
- _add_inset_axes(parent_axes, inset_axes)
-
- return inset_axes
-
-
-def mark_inset(parent_axes, inset_axes, loc1, loc2, **kwargs):
- """
- Draw a box to mark the location of an area represented by an inset axes.
-
- This function draws a box in *parent_axes* at the bounding box of
- *inset_axes*, and shows a connection with the inset axes by drawing lines
- at the corners, giving a "zoomed in" effect.
-
- Parameters
- ----------
- parent_axes : `matplotlib.axes.Axes`
- Axes which contains the area of the inset axes.
-
- inset_axes : `matplotlib.axes.Axes`
- The inset axes.
-
- loc1, loc2 : {1, 2, 3, 4}
- Corners to use for connecting the inset axes and the area in the
- parent axes.
-
- **kwargs
- Patch properties for the lines and box drawn:
- %(Patch)s
-
- Returns
- -------
- pp : `matplotlib.patches.Patch`
- The patch drawn to represent the area of the inset axes.
-
- p1, p2 : `matplotlib.patches.Patch`
- The patches connecting two corners of the inset axes and its area.
- """
- rect = TransformedBbox(inset_axes.viewLim, parent_axes.transData)
-
- fill = kwargs.pop("fill", False)
- pp = BboxPatch(rect, fill=fill, **kwargs)
- parent_axes.add_patch(pp)
-
- p1 = BboxConnector(inset_axes.bbox, rect, loc1=loc1, **kwargs)
- inset_axes.add_patch(p1)
- p1.set_clip_on(False)
- p2 = BboxConnector(inset_axes.bbox, rect, loc1=loc2, **kwargs)
- inset_axes.add_patch(p2)
- p2.set_clip_on(False)
-
- return pp, p1, p2
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/mpl_axes.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/mpl_axes.py
deleted file mode 100644
index aaff7b7692a..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/mpl_axes.py
+++ /dev/null
@@ -1,154 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-
-import matplotlib.axes as maxes
-from matplotlib.artist import Artist
-from matplotlib.axis import XAxis, YAxis
-
-class SimpleChainedObjects(object):
- def __init__(self, objects):
- self._objects = objects
-
- def __getattr__(self, k):
- _a = SimpleChainedObjects([getattr(a, k) for a in self._objects])
- return _a
-
- def __call__(self, *kl, **kwargs):
- for m in self._objects:
- m(*kl, **kwargs)
-
-
-class Axes(maxes.Axes):
-
- class AxisDict(dict):
- def __init__(self, axes):
- self.axes = axes
- super(Axes.AxisDict, self).__init__()
-
- def __getitem__(self, k):
- if isinstance(k, tuple):
- r = SimpleChainedObjects(
- [super(Axes.AxisDict, self).__getitem__(k1) for k1 in k])
- return r
- elif isinstance(k, slice):
- if k.start is None and k.stop is None and k.step is None:
- r = SimpleChainedObjects(list(six.itervalues(self)))
- return r
- else:
- raise ValueError("Unsupported slice")
- else:
- return dict.__getitem__(self, k)
-
- def __call__(self, *v, **kwargs):
- return maxes.Axes.axis(self.axes, *v, **kwargs)
-
- def __init__(self, *kl, **kw):
- super(Axes, self).__init__(*kl, **kw)
-
- def _init_axis_artists(self, axes=None):
- if axes is None:
- axes = self
-
- self._axislines = self.AxisDict(self)
-
- self._axislines["bottom"] = SimpleAxisArtist(self.xaxis, 1, self.spines["bottom"])
- self._axislines["top"] = SimpleAxisArtist(self.xaxis, 2, self.spines["top"])
- self._axislines["left"] = SimpleAxisArtist(self.yaxis, 1, self.spines["left"])
- self._axislines["right"] = SimpleAxisArtist(self.yaxis, 2, self.spines["right"])
-
-
- def _get_axislines(self):
- return self._axislines
-
- axis = property(_get_axislines)
-
- def cla(self):
-
- super(Axes, self).cla()
- self._init_axis_artists()
-
-
-class SimpleAxisArtist(Artist):
- def __init__(self, axis, axisnum, spine):
- self._axis = axis
- self._axisnum = axisnum
- self.line = spine
-
- if isinstance(axis, XAxis):
- self._axis_direction = ["bottom", "top"][axisnum-1]
- elif isinstance(axis, YAxis):
- self._axis_direction = ["left", "right"][axisnum-1]
- else:
- raise ValueError("axis must be instance of XAxis or YAxis : %s is provided" % (axis,))
- Artist.__init__(self)
-
-
- def _get_major_ticks(self):
- tickline = "tick%dline" % self._axisnum
- return SimpleChainedObjects([getattr(tick, tickline)
- for tick in self._axis.get_major_ticks()])
-
- def _get_major_ticklabels(self):
- label = "label%d" % self._axisnum
- return SimpleChainedObjects([getattr(tick, label)
- for tick in self._axis.get_major_ticks()])
-
- def _get_label(self):
- return self._axis.label
-
- major_ticks = property(_get_major_ticks)
- major_ticklabels = property(_get_major_ticklabels)
- label = property(_get_label)
-
- def set_visible(self, b):
- self.toggle(all=b)
- self.line.set_visible(b)
- self._axis.set_visible(True)
- Artist.set_visible(self, b)
-
- def set_label(self, txt):
- self._axis.set_label_text(txt)
-
- def toggle(self, all=None, ticks=None, ticklabels=None, label=None):
-
- if all:
- _ticks, _ticklabels, _label = True, True, True
- elif all is not None:
- _ticks, _ticklabels, _label = False, False, False
- else:
- _ticks, _ticklabels, _label = None, None, None
-
- if ticks is not None:
- _ticks = ticks
- if ticklabels is not None:
- _ticklabels = ticklabels
- if label is not None:
- _label = label
-
- tickOn = "tick%dOn" % self._axisnum
- labelOn = "label%dOn" % self._axisnum
-
- if _ticks is not None:
- tickparam = {tickOn: _ticks}
- self._axis.set_tick_params(**tickparam)
- if _ticklabels is not None:
- tickparam = {labelOn: _ticklabels}
- self._axis.set_tick_params(**tickparam)
-
- if _label is not None:
- pos = self._axis.get_label_position()
- if (pos == self._axis_direction) and not _label:
- self._axis.label.set_visible(False)
- elif _label:
- self._axis.label.set_visible(True)
- self._axis.set_label_position(self._axis_direction)
-
-
-if __name__ == '__main__':
- import matplotlib.pyplot as plt
- fig = plt.figure()
- ax = Axes(fig, [0.1, 0.1, 0.8, 0.8])
- fig.add_axes(ax)
- ax.cla()
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/parasite_axes.py b/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/parasite_axes.py
deleted file mode 100644
index 16a67b4d1ff..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/parasite_axes.py
+++ /dev/null
@@ -1,486 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-
-from matplotlib import (
- artist as martist, collections as mcoll, transforms as mtransforms,
- rcParams)
-from matplotlib.axes import subplot_class_factory
-from matplotlib.transforms import Bbox
-from .mpl_axes import Axes
-
-import numpy as np
-
-
-class ParasiteAxesBase(object):
-
- def get_images_artists(self):
- artists = {a for a in self.get_children() if a.get_visible()}
- images = {a for a in self.images if a.get_visible()}
-
- return list(images), list(artists - images)
-
- def __init__(self, parent_axes, **kargs):
-
- self._parent_axes = parent_axes
- kargs.update(dict(frameon=False))
- self._get_base_axes_attr("__init__")(self, parent_axes.figure,
- parent_axes._position, **kargs)
-
- def cla(self):
- self._get_base_axes_attr("cla")(self)
-
- martist.setp(self.get_children(), visible=False)
- self._get_lines = self._parent_axes._get_lines
-
- # In mpl's Axes, zorders of x- and y-axis are originally set
- # within Axes.draw().
- if self._axisbelow:
- self.xaxis.set_zorder(0.5)
- self.yaxis.set_zorder(0.5)
- else:
- self.xaxis.set_zorder(2.5)
- self.yaxis.set_zorder(2.5)
-
-
-_parasite_axes_classes = {}
-def parasite_axes_class_factory(axes_class=None):
- if axes_class is None:
- axes_class = Axes
-
- new_class = _parasite_axes_classes.get(axes_class)
- if new_class is None:
- def _get_base_axes_attr(self, attrname):
- return getattr(axes_class, attrname)
-
- new_class = type(str("%sParasite" % (axes_class.__name__)),
- (ParasiteAxesBase, axes_class),
- {'_get_base_axes_attr': _get_base_axes_attr})
- _parasite_axes_classes[axes_class] = new_class
-
- return new_class
-
-ParasiteAxes = parasite_axes_class_factory()
-
-# #class ParasiteAxes(ParasiteAxesBase, Axes):
-
-# @classmethod
-# def _get_base_axes_attr(cls, attrname):
-# return getattr(Axes, attrname)
-
-
-
-class ParasiteAxesAuxTransBase(object):
- def __init__(self, parent_axes, aux_transform, viewlim_mode=None,
- **kwargs):
-
- self.transAux = aux_transform
- self.set_viewlim_mode(viewlim_mode)
-
- self._parasite_axes_class.__init__(self, parent_axes, **kwargs)
-
- def _set_lim_and_transforms(self):
-
- self.transAxes = self._parent_axes.transAxes
-
- self.transData = \
- self.transAux + \
- self._parent_axes.transData
-
- self._xaxis_transform = mtransforms.blended_transform_factory(
- self.transData, self.transAxes)
- self._yaxis_transform = mtransforms.blended_transform_factory(
- self.transAxes, self.transData)
-
- def set_viewlim_mode(self, mode):
- if mode not in [None, "equal", "transform"]:
- raise ValueError("Unknown mode : %s" % (mode,))
- else:
- self._viewlim_mode = mode
-
- def get_viewlim_mode(self):
- return self._viewlim_mode
-
-
- def update_viewlim(self):
- viewlim = self._parent_axes.viewLim.frozen()
- mode = self.get_viewlim_mode()
- if mode is None:
- pass
- elif mode == "equal":
- self.axes.viewLim.set(viewlim)
- elif mode == "transform":
- self.axes.viewLim.set(viewlim.transformed(self.transAux.inverted()))
- else:
- raise ValueError("Unknown mode : %s" % (self._viewlim_mode,))
-
-
- def _pcolor(self, method_name, *XYC, **kwargs):
- if len(XYC) == 1:
- C = XYC[0]
- ny, nx = C.shape
-
- gx = np.arange(-0.5, nx, 1.)
- gy = np.arange(-0.5, ny, 1.)
-
- X, Y = np.meshgrid(gx, gy)
- else:
- X, Y, C = XYC
-
- pcolor_routine = self._get_base_axes_attr(method_name)
-
- if "transform" in kwargs:
- mesh = pcolor_routine(self, X, Y, C, **kwargs)
- else:
- orig_shape = X.shape
- xy = np.vstack([X.flat, Y.flat])
- xyt=xy.transpose()
- wxy = self.transAux.transform(xyt)
- gx, gy = wxy[:,0].reshape(orig_shape), wxy[:,1].reshape(orig_shape)
- mesh = pcolor_routine(self, gx, gy, C, **kwargs)
- mesh.set_transform(self._parent_axes.transData)
-
- return mesh
-
- def pcolormesh(self, *XYC, **kwargs):
- return self._pcolor("pcolormesh", *XYC, **kwargs)
-
- def pcolor(self, *XYC, **kwargs):
- return self._pcolor("pcolor", *XYC, **kwargs)
-
-
- def _contour(self, method_name, *XYCL, **kwargs):
-
- if len(XYCL) <= 2:
- C = XYCL[0]
- ny, nx = C.shape
-
- gx = np.arange(0., nx, 1.)
- gy = np.arange(0., ny, 1.)
-
- X,Y = np.meshgrid(gx, gy)
- CL = XYCL
- else:
- X, Y = XYCL[:2]
- CL = XYCL[2:]
-
- contour_routine = self._get_base_axes_attr(method_name)
-
- if "transform" in kwargs:
- cont = contour_routine(self, X, Y, *CL, **kwargs)
- else:
- orig_shape = X.shape
- xy = np.vstack([X.flat, Y.flat])
- xyt=xy.transpose()
- wxy = self.transAux.transform(xyt)
- gx, gy = wxy[:,0].reshape(orig_shape), wxy[:,1].reshape(orig_shape)
- cont = contour_routine(self, gx, gy, *CL, **kwargs)
- for c in cont.collections:
- c.set_transform(self._parent_axes.transData)
-
- return cont
-
- def contour(self, *XYCL, **kwargs):
- return self._contour("contour", *XYCL, **kwargs)
-
- def contourf(self, *XYCL, **kwargs):
- return self._contour("contourf", *XYCL, **kwargs)
-
- def apply_aspect(self, position=None):
- self.update_viewlim()
- self._get_base_axes_attr("apply_aspect")(self)
- #ParasiteAxes.apply_aspect()
-
-
-
-_parasite_axes_auxtrans_classes = {}
-def parasite_axes_auxtrans_class_factory(axes_class=None):
- if axes_class is None:
- parasite_axes_class = ParasiteAxes
- elif not issubclass(axes_class, ParasiteAxesBase):
- parasite_axes_class = parasite_axes_class_factory(axes_class)
- else:
- parasite_axes_class = axes_class
-
- new_class = _parasite_axes_auxtrans_classes.get(parasite_axes_class)
- if new_class is None:
- new_class = type(str("%sParasiteAuxTrans" % (parasite_axes_class.__name__)),
- (ParasiteAxesAuxTransBase, parasite_axes_class),
- {'_parasite_axes_class': parasite_axes_class,
- 'name': 'parasite_axes'})
- _parasite_axes_auxtrans_classes[parasite_axes_class] = new_class
-
- return new_class
-
-
-ParasiteAxesAuxTrans = parasite_axes_auxtrans_class_factory(axes_class=ParasiteAxes)
-
-
-
-
-def _get_handles(ax):
- handles = ax.lines[:]
- handles.extend(ax.patches)
- handles.extend([c for c in ax.collections
- if isinstance(c, mcoll.LineCollection)])
- handles.extend([c for c in ax.collections
- if isinstance(c, mcoll.RegularPolyCollection)])
- handles.extend([c for c in ax.collections
- if isinstance(c, mcoll.CircleCollection)])
-
- return handles
-
-
-class HostAxesBase(object):
- def __init__(self, *args, **kwargs):
-
- self.parasites = []
- self._get_base_axes_attr("__init__")(self, *args, **kwargs)
-
-
- def get_aux_axes(self, tr, viewlim_mode="equal", axes_class=None):
- parasite_axes_class = parasite_axes_auxtrans_class_factory(axes_class)
- ax2 = parasite_axes_class(self, tr, viewlim_mode)
- # note that ax2.transData == tr + ax1.transData
- # Anthing you draw in ax2 will match the ticks and grids of ax1.
- self.parasites.append(ax2)
- ax2._remove_method = lambda h: self.parasites.remove(h)
- return ax2
-
- def _get_legend_handles(self, legend_handler_map=None):
- # don't use this!
- Axes_get_legend_handles = self._get_base_axes_attr("_get_legend_handles")
- all_handles = list(Axes_get_legend_handles(self, legend_handler_map))
-
- for ax in self.parasites:
- all_handles.extend(ax._get_legend_handles(legend_handler_map))
-
- return all_handles
-
-
- def draw(self, renderer):
-
- orig_artists = list(self.artists)
- orig_images = list(self.images)
-
- if hasattr(self, "get_axes_locator"):
- locator = self.get_axes_locator()
- if locator:
- pos = locator(self, renderer)
- self.set_position(pos, which="active")
- self.apply_aspect(pos)
- else:
- self.apply_aspect()
- else:
- self.apply_aspect()
-
- rect = self.get_position()
-
- for ax in self.parasites:
- ax.apply_aspect(rect)
- images, artists = ax.get_images_artists()
- self.images.extend(images)
- self.artists.extend(artists)
-
- self._get_base_axes_attr("draw")(self, renderer)
- self.artists = orig_artists
- self.images = orig_images
-
-
- def cla(self):
-
- for ax in self.parasites:
- ax.cla()
-
- self._get_base_axes_attr("cla")(self)
- #super(HostAxes, self).cla()
-
-
- def twinx(self, axes_class=None):
- """
- create a twin of Axes for generating a plot with a sharex
- x-axis but independent y axis. The y-axis of self will have
- ticks on left and the returned axes will have ticks on the
- right
- """
-
- if axes_class is None:
- axes_class = self._get_base_axes()
-
- parasite_axes_class = parasite_axes_class_factory(axes_class)
-
- ax2 = parasite_axes_class(self, sharex=self, frameon=False)
- self.parasites.append(ax2)
-
- self.axis["right"].set_visible(False)
-
- ax2.axis["right"].set_visible(True)
- ax2.axis["left", "top", "bottom"].set_visible(False)
-
- def _remove_method(h):
- self.parasites.remove(h)
- self.axis["right"].set_visible(True)
- self.axis["right"].toggle(ticklabels=False, label=False)
- ax2._remove_method = _remove_method
-
- return ax2
-
- def twiny(self, axes_class=None):
- """
- create a twin of Axes for generating a plot with a shared
- y-axis but independent x axis. The x-axis of self will have
- ticks on bottom and the returned axes will have ticks on the
- top
- """
-
- if axes_class is None:
- axes_class = self._get_base_axes()
-
- parasite_axes_class = parasite_axes_class_factory(axes_class)
-
- ax2 = parasite_axes_class(self, sharey=self, frameon=False)
- self.parasites.append(ax2)
-
- self.axis["top"].set_visible(False)
-
- ax2.axis["top"].set_visible(True)
- ax2.axis["left", "right", "bottom"].set_visible(False)
-
- def _remove_method(h):
- self.parasites.remove(h)
- self.axis["top"].set_visible(True)
- self.axis["top"].toggle(ticklabels=False, label=False)
- ax2._remove_method = _remove_method
-
- return ax2
-
-
- def twin(self, aux_trans=None, axes_class=None):
- """
- create a twin of Axes for generating a plot with a sharex
- x-axis but independent y axis. The y-axis of self will have
- ticks on left and the returned axes will have ticks on the
- right
- """
-
- if axes_class is None:
- axes_class = self._get_base_axes()
-
- parasite_axes_auxtrans_class = parasite_axes_auxtrans_class_factory(axes_class)
-
- if aux_trans is None:
- ax2 = parasite_axes_auxtrans_class(self, mtransforms.IdentityTransform(),
- viewlim_mode="equal",
- )
- else:
- ax2 = parasite_axes_auxtrans_class(self, aux_trans,
- viewlim_mode="transform",
- )
- self.parasites.append(ax2)
- ax2._remove_method = lambda h: self.parasites.remove(h)
-
- self.axis["top", "right"].set_visible(False)
-
- ax2.axis["top", "right"].set_visible(True)
- ax2.axis["left", "bottom"].set_visible(False)
-
- def _remove_method(h):
- self.parasites.remove(h)
- self.axis["top", "right"].set_visible(True)
- self.axis["top", "right"].toggle(ticklabels=False, label=False)
- ax2._remove_method = _remove_method
-
- return ax2
-
- def get_tightbbox(self, renderer, call_axes_locator=True):
-
- bbs = [ax.get_tightbbox(renderer, call_axes_locator)
- for ax in self.parasites]
- get_tightbbox = self._get_base_axes_attr("get_tightbbox")
- bbs.append(get_tightbbox(self, renderer, call_axes_locator))
-
- _bbox = Bbox.union([b for b in bbs if b.width!=0 or b.height!=0])
-
- return _bbox
-
-
-
-_host_axes_classes = {}
-def host_axes_class_factory(axes_class=None):
- if axes_class is None:
- axes_class = Axes
-
- new_class = _host_axes_classes.get(axes_class)
- if new_class is None:
- def _get_base_axes(self):
- return axes_class
-
- def _get_base_axes_attr(self, attrname):
- return getattr(axes_class, attrname)
-
- new_class = type(str("%sHostAxes" % (axes_class.__name__)),
- (HostAxesBase, axes_class),
- {'_get_base_axes_attr': _get_base_axes_attr,
- '_get_base_axes': _get_base_axes})
-
- _host_axes_classes[axes_class] = new_class
-
- return new_class
-
-def host_subplot_class_factory(axes_class):
- host_axes_class = host_axes_class_factory(axes_class=axes_class)
- subplot_host_class = subplot_class_factory(host_axes_class)
- return subplot_host_class
-
-HostAxes = host_axes_class_factory(axes_class=Axes)
-SubplotHost = subplot_class_factory(HostAxes)
-
-
-def host_axes(*args, **kwargs):
- """
- Create axes that can act as a hosts to parasitic axes.
-
- Parameters
- ----------
- figure : `matplotlib.figure.Figure`
- Figure to which the axes will be added. Defaults to the current figure
- `pyplot.gcf()`.
-
- *args, **kwargs :
- Will be passed on to the underlying ``Axes`` object creation.
- """
- import matplotlib.pyplot as plt
- axes_class = kwargs.pop("axes_class", None)
- host_axes_class = host_axes_class_factory(axes_class)
- fig = kwargs.get("figure", None)
- if fig is None:
- fig = plt.gcf()
- ax = host_axes_class(fig, *args, **kwargs)
- fig.add_axes(ax)
- plt.draw_if_interactive()
- return ax
-
-def host_subplot(*args, **kwargs):
- """
- Create a subplot that can act as a host to parasitic axes.
-
- Parameters
- ----------
- figure : `matplotlib.figure.Figure`
- Figure to which the subplot will be added. Defaults to the current
- figure `pyplot.gcf()`.
-
- *args, **kwargs :
- Will be passed on to the underlying ``Axes`` object creation.
- """
- import matplotlib.pyplot as plt
- axes_class = kwargs.pop("axes_class", None)
- host_subplot_class = host_subplot_class_factory(axes_class)
- fig = kwargs.get("figure", None)
- if fig is None:
- fig = plt.gcf()
- ax = host_subplot_class(fig, *args, **kwargs)
- fig.add_subplot(ax)
- plt.draw_if_interactive()
- return ax
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/__init__.py b/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/__init__.py
deleted file mode 100644
index 8431c0cd3ee..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-
-from .axislines import (
- Axes, AxesZero, AxisArtistHelper, AxisArtistHelperRectlinear,
- GridHelperBase, GridHelperRectlinear, Subplot, SubplotZero)
-from .axis_artist import AxisArtist, GridlinesCollection
-
-from .grid_helper_curvelinear import GridHelperCurveLinear
-
-from .floating_axes import FloatingAxes, FloatingSubplot
-
-from mpl_toolkits.axes_grid1.parasite_axes import (
- host_axes_class_factory, parasite_axes_class_factory,
- parasite_axes_auxtrans_class_factory, subplot_class_factory)
-
-ParasiteAxes = parasite_axes_class_factory(Axes)
-
-ParasiteAxesAuxTrans = \
- parasite_axes_auxtrans_class_factory(axes_class=ParasiteAxes)
-
-HostAxes = host_axes_class_factory(axes_class=Axes)
-
-SubplotHost = subplot_class_factory(HostAxes)
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/angle_helper.py b/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/angle_helper.py
deleted file mode 100644
index 15732a58ec0..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/angle_helper.py
+++ /dev/null
@@ -1,416 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-
-import numpy as np
-import math
-
-from mpl_toolkits.axisartist.grid_finder import ExtremeFinderSimple
-
-def select_step_degree(dv):
-
- degree_limits_ = [1.5, 3, 7, 13, 20, 40, 70, 120, 270, 520]
- degree_steps_ = [ 1, 2, 5, 10, 15, 30, 45, 90, 180, 360]
- degree_factors = [1.] * len(degree_steps_)
-
- minsec_limits_ = [1.5, 2.5, 3.5, 8, 11, 18, 25, 45]
- minsec_steps_ = [1, 2, 3, 5, 10, 15, 20, 30]
-
- minute_limits_ = np.array(minsec_limits_) / 60
- minute_factors = [60.] * len(minute_limits_)
-
- second_limits_ = np.array(minsec_limits_) / 3600
- second_factors = [3600.] * len(second_limits_)
-
- degree_limits = np.concatenate([second_limits_,
- minute_limits_,
- degree_limits_])
-
- degree_steps = np.concatenate([minsec_steps_,
- minsec_steps_,
- degree_steps_])
-
- degree_factors = np.concatenate([second_factors,
- minute_factors,
- degree_factors])
-
- n = degree_limits.searchsorted(dv)
- step = degree_steps[n]
- factor = degree_factors[n]
-
- return step, factor
-
-
-
-def select_step_hour(dv):
-
- hour_limits_ = [1.5, 2.5, 3.5, 5, 7, 10, 15, 21, 36]
- hour_steps_ = [1, 2 , 3, 4, 6, 8, 12, 18, 24]
- hour_factors = [1.] * len(hour_steps_)
-
- minsec_limits_ = [1.5, 2.5, 3.5, 4.5, 5.5, 8, 11, 14, 18, 25, 45]
- minsec_steps_ = [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30]
-
- minute_limits_ = np.array(minsec_limits_) / 60
- minute_factors = [60.] * len(minute_limits_)
-
- second_limits_ = np.array(minsec_limits_) / 3600
- second_factors = [3600.] * len(second_limits_)
-
- hour_limits = np.concatenate([second_limits_,
- minute_limits_,
- hour_limits_])
-
- hour_steps = np.concatenate([minsec_steps_,
- minsec_steps_,
- hour_steps_])
-
- hour_factors = np.concatenate([second_factors,
- minute_factors,
- hour_factors])
-
- n = hour_limits.searchsorted(dv)
- step = hour_steps[n]
- factor = hour_factors[n]
-
- return step, factor
-
-
-def select_step_sub(dv):
-
- # subarcsec or degree
- tmp = 10.**(int(math.log10(dv))-1.)
-
- factor = 1./tmp
-
- if 1.5*tmp >= dv:
- step = 1
- elif 3.*tmp >= dv:
- step = 2
- elif 7.*tmp >= dv:
- step = 5
- else:
- step = 1
- factor = 0.1*factor
-
- return step, factor
-
-
-def select_step(v1, v2, nv, hour=False, include_last=True,
- threshold_factor=3600.):
-
- if v1 > v2:
- v1, v2 = v2, v1
-
- dv = (v2 - v1) / nv
-
- if hour:
- _select_step = select_step_hour
- cycle = 24.
- else:
- _select_step = select_step_degree
- cycle = 360.
-
- # for degree
- if dv > 1./threshold_factor:
- step, factor = _select_step(dv)
- else:
- step, factor = select_step_sub(dv*threshold_factor)
-
- factor = factor * threshold_factor
-
-
- f1, f2, fstep = v1*factor, v2*factor, step/factor
- levs = np.arange(np.floor(f1/step), np.ceil(f2/step)+0.5, dtype=int) * step
-
- # n : number of valid levels. If there is a cycle, e.g., [0, 90, 180,
- # 270, 360], the grid line needs to be extended from 0 to 360, so
- # we need to return the whole array. However, the last level (360)
- # needs to be ignored often. In this case, so we return n=4.
-
- n = len(levs)
-
-
- # we need to check the range of values
- # for example, -90 to 90, 0 to 360,
-
- if factor == 1. and (levs[-1] >= levs[0]+cycle): # check for cycle
- nv = int(cycle / step)
- if include_last:
- levs = levs[0] + np.arange(0, nv+1, 1) * step
- else:
- levs = levs[0] + np.arange(0, nv, 1) * step
-
- n = len(levs)
-
- return np.array(levs), n, factor
-
-
-def select_step24(v1, v2, nv, include_last=True, threshold_factor=3600):
- v1, v2 = v1/15., v2/15.
- levs, n, factor = select_step(v1, v2, nv, hour=True,
- include_last=include_last,
- threshold_factor=threshold_factor)
- return levs*15., n, factor
-
-def select_step360(v1, v2, nv, include_last=True, threshold_factor=3600):
- return select_step(v1, v2, nv, hour=False,
- include_last=include_last,
- threshold_factor=threshold_factor)
-
-
-class LocatorBase(object):
- def __init__(self, den, include_last=True):
- self.den = den
- self._include_last = include_last
-
- @property
- def nbins(self):
- return self.den
-
- @nbins.setter
- def nbins(self, v):
- self.den = v
-
- def set_params(self, nbins=None):
- if nbins is not None:
- self.den = int(nbins)
-
-
-class LocatorHMS(LocatorBase):
- def __call__(self, v1, v2):
- return select_step24(v1, v2, self.den, self._include_last)
-
-class LocatorHM(LocatorBase):
- def __call__(self, v1, v2):
- return select_step24(v1, v2, self.den, self._include_last,
- threshold_factor=60)
-
-class LocatorH(LocatorBase):
- def __call__(self, v1, v2):
- return select_step24(v1, v2, self.den, self._include_last,
- threshold_factor=1)
-
-
-class LocatorDMS(LocatorBase):
- def __call__(self, v1, v2):
- return select_step360(v1, v2, self.den, self._include_last)
-
-class LocatorDM(LocatorBase):
- def __call__(self, v1, v2):
- return select_step360(v1, v2, self.den, self._include_last,
- threshold_factor=60)
-
-class LocatorD(LocatorBase):
- def __call__(self, v1, v2):
- return select_step360(v1, v2, self.den, self._include_last,
- threshold_factor=1)
-
-
-class FormatterDMS(object):
- deg_mark = r"^{\circ}"
- min_mark = r"^{\prime}"
- sec_mark = r"^{\prime\prime}"
-
- fmt_d = "$%d" + deg_mark + "$"
- fmt_ds = r"$%d.%s" + deg_mark + "$"
-
- # %s for sign
- fmt_d_m = r"$%s%d" + deg_mark + r"\,%02d" + min_mark + "$"
- fmt_d_ms = r"$%s%d" + deg_mark + r"\,%02d.%s" + min_mark + "$"
-
- fmt_d_m_partial = "$%s%d" + deg_mark + r"\,%02d" + min_mark + r"\,"
- fmt_s_partial = "%02d" + sec_mark + "$"
- fmt_ss_partial = "%02d.%s" + sec_mark + "$"
-
- def _get_number_fraction(self, factor):
- ## check for fractional numbers
- number_fraction = None
- # check for 60
-
- for threshold in [1, 60, 3600]:
- if factor <= threshold:
- break
-
- d = factor // threshold
- int_log_d = int(np.floor(np.log10(d)))
- if 10**int_log_d == d and d != 1:
- number_fraction = int_log_d
- factor = factor // 10**int_log_d
- return factor, number_fraction
-
- return factor, number_fraction
-
-
- def __call__(self, direction, factor, values):
- if len(values) == 0:
- return []
- #ss = [[-1, 1][v>0] for v in values] #not py24 compliant
- values = np.asarray(values)
- ss = np.where(values>0, 1, -1)
-
- sign_map = {(-1, True):"-"}
- signs = [sign_map.get((s, v!=0), "") for s, v in zip(ss, values)]
-
- factor, number_fraction = self._get_number_fraction(factor)
-
- values = np.abs(values)
-
- if number_fraction is not None:
- values, frac_part = divmod(values, 10**number_fraction)
- frac_fmt = "%%0%dd" % (number_fraction,)
- frac_str = [frac_fmt % (f1,) for f1 in frac_part]
-
- if factor == 1:
- if number_fraction is None:
- return [self.fmt_d % (s*int(v),) for (s, v) in zip(ss, values)]
- else:
- return [self.fmt_ds % (s*int(v), f1)
- for (s, v, f1) in zip(ss, values, frac_str)]
- elif factor == 60:
- deg_part, min_part = divmod(values, 60)
- if number_fraction is None:
- return [self.fmt_d_m % (s1, d1, m1)
- for s1, d1, m1 in zip(signs, deg_part, min_part)]
- else:
- return [self.fmt_d_ms % (s, d1, m1, f1)
- for s, d1, m1, f1 in zip(signs, deg_part, min_part, frac_str)]
-
- elif factor == 3600:
- if ss[-1] == -1:
- inverse_order = True
- values = values[::-1]
- signs = signs[::-1]
- else:
- inverse_order = False
-
- l_hm_old = ""
- r = []
-
- deg_part, min_part_ = divmod(values, 3600)
- min_part, sec_part = divmod(min_part_, 60)
-
- if number_fraction is None:
- sec_str = [self.fmt_s_partial % (s1,) for s1 in sec_part]
- else:
- sec_str = [self.fmt_ss_partial % (s1, f1) for s1, f1 in zip(sec_part, frac_str)]
-
- for s, d1, m1, s1 in zip(signs, deg_part, min_part, sec_str):
- l_hm = self.fmt_d_m_partial % (s, d1, m1)
- if l_hm != l_hm_old:
- l_hm_old = l_hm
- l = l_hm + s1 #l_s
- else:
- l = "$" + s + s1
- r.append(l)
-
- if inverse_order:
- return r[::-1]
- else:
- return r
-
- else: # factor > 3600.
- return [r"$%s^{\circ}$" % (str(v),) for v in ss*values]
-
-
-class FormatterHMS(FormatterDMS):
- deg_mark = r"^\mathrm{h}"
- min_mark = r"^\mathrm{m}"
- sec_mark = r"^\mathrm{s}"
-
- fmt_d = "$%d" + deg_mark + "$"
- fmt_ds = r"$%d.%s" + deg_mark + "$"
-
- # %s for sign
- fmt_d_m = r"$%s%d" + deg_mark + r"\,%02d" + min_mark+"$"
- fmt_d_ms = r"$%s%d" + deg_mark + r"\,%02d.%s" + min_mark+"$"
-
- fmt_d_m_partial = "$%s%d" + deg_mark + r"\,%02d" + min_mark + r"\,"
- fmt_s_partial = "%02d" + sec_mark + "$"
- fmt_ss_partial = "%02d.%s" + sec_mark + "$"
-
- def __call__(self, direction, factor, values): # hour
- return FormatterDMS.__call__(self, direction, factor, np.asarray(values)/15.)
-
-
-
-
-
-class ExtremeFinderCycle(ExtremeFinderSimple):
- """
- When there is a cycle, e.g., longitude goes from 0-360.
- """
- def __init__(self,
- nx, ny,
- lon_cycle = 360.,
- lat_cycle = None,
- lon_minmax = None,
- lat_minmax = (-90, 90)
- ):
- #self.transfrom_xy = transform_xy
- #self.inv_transfrom_xy = inv_transform_xy
- self.nx, self.ny = nx, ny
- self.lon_cycle, self.lat_cycle = lon_cycle, lat_cycle
- self.lon_minmax = lon_minmax
- self.lat_minmax = lat_minmax
-
-
- def __call__(self, transform_xy, x1, y1, x2, y2):
- """
- get extreme values.
-
- x1, y1, x2, y2 in image coordinates (0-based)
- nx, ny : number of divisions in each axis
- """
- x_, y_ = np.linspace(x1, x2, self.nx), np.linspace(y1, y2, self.ny)
- x, y = np.meshgrid(x_, y_)
- lon, lat = transform_xy(np.ravel(x), np.ravel(y))
-
- # iron out jumps, but algorithm should be improved.
- # This is just naive way of doing and my fail for some cases.
- # Consider replacing this with numpy.unwrap
- # We are ignoring invalid warnings. They are triggered when
- # comparing arrays with NaNs using > We are already handling
- # that correctly using np.nanmin and np.nanmax
- with np.errstate(invalid='ignore'):
- if self.lon_cycle is not None:
- lon0 = np.nanmin(lon)
- lon -= 360. * ((lon - lon0) > 180.)
- if self.lat_cycle is not None:
- lat0 = np.nanmin(lat)
- lat -= 360. * ((lat - lat0) > 180.)
-
- lon_min, lon_max = np.nanmin(lon), np.nanmax(lon)
- lat_min, lat_max = np.nanmin(lat), np.nanmax(lat)
-
- lon_min, lon_max, lat_min, lat_max = \
- self._adjust_extremes(lon_min, lon_max, lat_min, lat_max)
-
- return lon_min, lon_max, lat_min, lat_max
-
-
- def _adjust_extremes(self, lon_min, lon_max, lat_min, lat_max):
-
- lon_min, lon_max, lat_min, lat_max = \
- self._add_pad(lon_min, lon_max, lat_min, lat_max)
-
- # check cycle
- if self.lon_cycle:
- lon_max = min(lon_max, lon_min + self.lon_cycle)
- if self.lat_cycle:
- lat_max = min(lat_max, lat_min + self.lat_cycle)
-
- if self.lon_minmax is not None:
- min0 = self.lon_minmax[0]
- lon_min = max(min0, lon_min)
- max0 = self.lon_minmax[1]
- lon_max = min(max0, lon_max)
-
- if self.lat_minmax is not None:
- min0 = self.lat_minmax[0]
- lat_min = max(min0, lat_min)
- max0 = self.lat_minmax[1]
- lat_max = min(max0, lat_max)
-
- return lon_min, lon_max, lat_min, lat_max
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axes_divider.py b/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axes_divider.py
deleted file mode 100644
index 52949405302..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axes_divider.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from mpl_toolkits.axes_grid1.axes_divider import (
- Divider, AxesLocator, SubplotDivider, AxesDivider, locatable_axes_factory,
- make_axes_locatable)
-
-from mpl_toolkits.axes_grid.axislines import Axes
-LocatableAxes = locatable_axes_factory(Axes)
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axes_grid.py b/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axes_grid.py
deleted file mode 100644
index 58212ac89c4..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axes_grid.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import mpl_toolkits.axes_grid1.axes_grid as axes_grid_orig
-from .axes_divider import LocatableAxes
-
-class CbarAxes(axes_grid_orig.CbarAxesBase, LocatableAxes):
- def __init__(self, *kl, **kwargs):
- orientation=kwargs.pop("orientation", None)
- if orientation is None:
- raise ValueError("orientation must be specified")
- self.orientation = orientation
- self._default_label_on = False
- self.locator = None
-
- super(LocatableAxes, self).__init__(*kl, **kwargs)
-
- def cla(self):
- super(LocatableAxes, self).cla()
- self._config_axes()
-
-
-class Grid(axes_grid_orig.Grid):
- _defaultLocatableAxesClass = LocatableAxes
-
-class ImageGrid(axes_grid_orig.ImageGrid):
- _defaultLocatableAxesClass = LocatableAxes
- _defaultCbarAxesClass = CbarAxes
-
-AxesGrid = ImageGrid
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axes_rgb.py b/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axes_rgb.py
deleted file mode 100644
index 695a362b57d..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axes_rgb.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from mpl_toolkits.axes_grid1.axes_rgb import (
- make_rgb_axes, imshow_rgb, RGBAxesBase)
-
-from .axislines import Axes
-
-
-class RGBAxes(RGBAxesBase):
- _defaultAxesClass = Axes
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axis_artist.py b/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axis_artist.py
deleted file mode 100644
index 620232112cf..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axis_artist.py
+++ /dev/null
@@ -1,1527 +0,0 @@
-"""
-axis_artist.py module provides axis-related artists. They are
-
- * axis line
- * tick lines
- * tick labels
- * axis label
- * grid lines
-
-The main artist class is a AxisArtist and a GridlinesCollection. The
-GridlinesCollection is responsible for drawing grid lines and the
-AxisArtist is responsible for all other artists. The AxisArtist class
-has attributes that are associated with each type of artists.
-
- * line : axis line
- * major_ticks : major tick lines
- * major_ticklabels : major tick labels
- * minor_ticks : minor tick lines
- * minor_ticklabels : minor tick labels
- * label : axis label
-
-Typically, the AxisArtist associated with a axes will be accessed with
-the *axis* dictionary of the axes, i.e., the AxisArtist for the bottom
-axis is
-
- ax.axis["bottom"]
-
-where *ax* is an instance of axes (mpl_toolkits.axislines.Axes). Thus,
-ax.axis["bottom"].line is an artist associated with the axis line, and
-ax.axis["bottom"].major_ticks is an artist associated with the major tick
-lines.
-
-You can change the colors, fonts, line widths, etc. of these artists
-by calling suitable set method. For example, to change the color of the major
-ticks of the bottom axis to red,
-
- ax.axis["bottom"].major_ticks.set_color("r")
-
-However, things like the locations of ticks, and their ticklabels need
-to be changed from the side of the grid_helper.
-
-axis_direction
---------------
-
-AxisArtist, AxisLabel, TickLabels have *axis_direction* attribute,
-which adjusts the location, angle, etc.,. The *axis_direction* must be
-one of [left, right, bottom, top] and they follow the matplotlib
-convention for the rectangle axis.
-
-For example, for the *bottom* axis (the left and right is relative to
-the direction of the increasing coordinate),
-
- * ticklabels and axislabel are on the right
- * ticklabels and axislabel have text angle of 0
- * ticklabels are baseline, center-aligned
- * axislabel is top, center-aligned
-
-
-The text angles are actually relative to (90 + angle of the direction
-to the ticklabel), which gives 0 for bottom axis.
-
- Parameter left bottom right top
- ticklabels location left right right left
- axislabel location left right right left
- ticklabels angle 90 0 -90 180
- axislabel angle 180 0 0 180
- ticklabel va center baseline center baseline
- axislabel va center top center bottom
- ticklabel ha right center right center
- axislabel ha right center right center
-
-
-Ticks are by default direct opposite side of the ticklabels. To make
-ticks to the same side of the ticklabels,
-
- ax.axis["bottom"].major_ticks.set_ticks_out(True)
-
-
-Following attributes can be customized (use set_xxx method)
-
- * Ticks : ticksize, tick_out
- * TickLabels : pad
- * AxisLabel : pad
-
-"""
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-
-# FIXME :
-# angles are given in data coordinate - need to convert it to canvas coordinate
-
-
-import matplotlib.artist as martist
-import matplotlib.text as mtext
-import matplotlib.font_manager as font_manager
-
-from matplotlib.path import Path
-from matplotlib.transforms import (
- Affine2D, Bbox, IdentityTransform, ScaledTranslation, TransformedPath)
-from matplotlib.collections import LineCollection
-
-from matplotlib import rcParams
-
-from matplotlib.artist import allow_rasterization
-
-import warnings
-
-import numpy as np
-
-
-import matplotlib.lines as mlines
-from .axisline_style import AxislineStyle
-
-
-class BezierPath(mlines.Line2D):
-
- def __init__(self, path, *kl, **kw):
- mlines.Line2D.__init__(self, [], [], *kl, **kw)
- self._path = path
- self._invalid = False
-
- def recache(self):
-
- self._transformed_path = TransformedPath(self._path, self.get_transform())
-
- self._invalid = False
-
- def set_path(self, path):
- self._path = path
- self._invalid = True
-
-
- def draw(self, renderer):
- if self._invalid:
- self.recache()
-
- if not self._visible: return
- renderer.open_group('line2d')
-
- gc = renderer.new_gc()
- self._set_gc_clip(gc)
-
- gc.set_foreground(self._color)
- gc.set_antialiased(self._antialiased)
- gc.set_linewidth(self._linewidth)
- gc.set_alpha(self._alpha)
- if self.is_dashed():
- cap = self._dashcapstyle
- join = self._dashjoinstyle
- else:
- cap = self._solidcapstyle
- join = self._solidjoinstyle
- gc.set_joinstyle(join)
- gc.set_capstyle(cap)
- gc.set_dashes(self._dashOffset, self._dashSeq)
-
- if self._lineStyles[self._linestyle] != '_draw_nothing':
- tpath, affine = (
- self._transformed_path.get_transformed_path_and_affine())
- renderer.draw_path(gc, tpath, affine.frozen())
-
- gc.restore()
- renderer.close_group('line2d')
-
-
-
-class UnimplementedException(Exception):
- pass
-
-from matplotlib.artist import Artist
-
-class AttributeCopier(object):
- def __init__(self, ref_artist, klass=Artist):
- self._klass = klass
- self._ref_artist = ref_artist
- super(AttributeCopier, self).__init__()
-
- def set_ref_artist(self, artist):
- self._ref_artist = artist
-
- def get_ref_artist(self):
- raise RuntimeError("get_ref_artist must overridden")
- #return self._ref_artist
-
- def get_attribute_from_ref_artist(self, attr_name, default_value):
- get_attr_method_name = "get_"+attr_name
- c = getattr(self._klass, get_attr_method_name)(self)
- if c == 'auto':
- ref_artist = self.get_ref_artist()
- if ref_artist:
- attr = getattr(ref_artist,
- get_attr_method_name)()
- return attr
- else:
- return default_value
-
- return c
-
-
-from matplotlib.lines import Line2D
-
-class Ticks(Line2D, AttributeCopier):
- """
- Ticks are derived from Line2D, and note that ticks themselves
- are markers. Thus, you should use set_mec, set_mew, etc.
-
- To change the tick size (length), you need to use
- set_ticksize. To change the direction of the ticks (ticks are
- in opposite direction of ticklabels by default), use
- set_tick_out(False).
- """
-
- def __init__(self, ticksize, tick_out=False, **kwargs):
- self._ticksize = ticksize
- self.locs_angles_labels = []
-
- self.set_tick_out(tick_out)
-
- self._axis = kwargs.pop("axis", None)
- if self._axis is not None:
- if "color" not in kwargs:
- kwargs["color"] = "auto"
- if ("mew" not in kwargs) and ("markeredgewidth" not in kwargs):
- kwargs["markeredgewidth"] = "auto"
-
- Line2D.__init__(self, [0.], [0.], **kwargs)
- AttributeCopier.__init__(self, self._axis, klass=Line2D)
- self.set_snap(True)
-
- def get_ref_artist(self):
- #return self._ref_artist.get_ticklines()[0]
- return self._ref_artist.majorTicks[0].tick1line
-
- def get_color(self):
- return self.get_attribute_from_ref_artist("color", "k")
-
- def get_markeredgecolor(self):
- if self._markeredgecolor == 'auto':
- return self.get_color()
- else:
- return self._markeredgecolor
-
- def get_markeredgewidth(self):
- return self.get_attribute_from_ref_artist("markeredgewidth", .5)
-
-
- def set_tick_out(self, b):
- """
- set True if tick need to be rotated by 180 degree.
- """
- self._tick_out = b
-
- def get_tick_out(self):
- """
- Return True if the tick will be rotated by 180 degree.
- """
- return self._tick_out
-
-
- def set_ticksize(self, ticksize):
- """
- set length of the ticks in points.
- """
- self._ticksize = ticksize
-
-
- def get_ticksize(self):
- """
- Return length of the ticks in points.
- """
- return self._ticksize
-
- def set_locs_angles(self, locs_angles):
- self.locs_angles = locs_angles
-
-
- def _update(self, renderer):
- pass
-
- _tickvert_path = Path([[0., 0.], [1., 0.]])
-
- def draw(self, renderer):
- if not self.get_visible():
- return
-
- self._update(renderer) # update the tick
-
- size = self._ticksize
- path_trans = self.get_transform()
-
- # set gc : copied from lines.py
-# gc = renderer.new_gc()
-# self._set_gc_clip(gc)
-
-# gc.set_foreground(self.get_color())
-# gc.set_antialiased(self._antialiased)
-# gc.set_linewidth(self._linewidth)
-# gc.set_alpha(self._alpha)
-# if self.is_dashed():
-# cap = self._dashcapstyle
-# join = self._dashjoinstyle
-# else:
-# cap = self._solidcapstyle
-# join = self._solidjoinstyle
-# gc.set_joinstyle(join)
-# gc.set_capstyle(cap)
-# gc.set_snap(self.get_snap())
-
-
- gc = renderer.new_gc()
- gc.set_foreground(self.get_markeredgecolor())
- gc.set_linewidth(self.get_markeredgewidth())
- gc.set_alpha(self._alpha)
-
- offset = renderer.points_to_pixels(size)
- marker_scale = Affine2D().scale(offset, offset)
-
- if self.get_tick_out():
- add_angle = 180
- else:
- add_angle = 0
-
- marker_rotation = Affine2D()
- marker_transform = marker_scale + marker_rotation
-
- for loc, angle in self.locs_angles:
- marker_rotation.clear().rotate_deg(angle+add_angle)
- locs = path_trans.transform_non_affine(np.array([loc]))
- if self.axes and not self.axes.viewLim.contains(*locs[0]):
- continue
- renderer.draw_markers(gc, self._tickvert_path, marker_transform,
- Path(locs), path_trans.get_affine())
-
- gc.restore()
-
-
-class LabelBase(mtext.Text):
- """
- A base class for AxisLabel and TickLabels. The position and angle
- of the text are calculated by to offset_ref_angle,
- text_ref_angle, and offset_radius attributes.
- """
-
- def __init__(self, *kl, **kwargs):
- self.locs_angles_labels = []
- self._ref_angle = 0
- self._offset_radius = 0.
-
- super(LabelBase, self).__init__(*kl,
- **kwargs)
-
- self.set_rotation_mode("anchor")
- self._text_follow_ref_angle = True
- #self._offset_ref_angle = 0
-
- def _set_ref_angle(self, a):
- self._ref_angle = a
-
- def _get_ref_angle(self):
- return self._ref_angle
-
- def _get_text_ref_angle(self):
- if self._text_follow_ref_angle:
- return self._get_ref_angle()+90
- else:
- return 0 #self.get_ref_angle()
-
- def _get_offset_ref_angle(self):
- return self._get_ref_angle()
-
- def _set_offset_radius(self, offset_radius):
- self._offset_radius = offset_radius
-
- def _get_offset_radius(self):
- return self._offset_radius
-
-
- _get_opposite_direction = {"left":"right",
- "right":"left",
- "top":"bottom",
- "bottom":"top"}.__getitem__
-
-
- def _update(self, renderer):
- pass
-
- def draw(self, renderer):
- if not self.get_visible(): return
-
- self._update(renderer)
-
- # save original and adjust some properties
- tr = self.get_transform()
- angle_orig = self.get_rotation()
-
- offset_tr = Affine2D()
- self.set_transform(tr+offset_tr)
-
- text_ref_angle = self._get_text_ref_angle()
- offset_ref_angle = self._get_offset_ref_angle()
-
- theta = (offset_ref_angle)/180.*np.pi
- dd = self._get_offset_radius()
- dx, dy = dd * np.cos(theta), dd * np.sin(theta)
- offset_tr.translate(dx, dy)
- self.set_rotation(text_ref_angle+angle_orig)
- super(LabelBase, self).draw(renderer)
- offset_tr.clear()
-
-
- # restore original properties
- self.set_transform(tr)
- self.set_rotation(angle_orig)
-
-
- def get_window_extent(self, renderer):
-
- self._update(renderer)
-
- # save original and adjust some properties
- tr = self.get_transform()
- angle_orig = self.get_rotation()
-
- offset_tr = Affine2D()
- self.set_transform(tr+offset_tr)
-
- text_ref_angle = self._get_text_ref_angle()
- offset_ref_angle = self._get_offset_ref_angle()
-
- theta = (offset_ref_angle)/180.*np.pi
- dd = self._get_offset_radius()
- dx, dy = dd * np.cos(theta), dd * np.sin(theta)
- offset_tr.translate(dx, dy)
- self.set_rotation(text_ref_angle+angle_orig)
-
- bbox = super(LabelBase, self).get_window_extent(renderer).frozen()
-
- offset_tr.clear()
-
-
- # restore original properties
- self.set_transform(tr)
- self.set_rotation(angle_orig)
-
- return bbox
-
-
-class AxisLabel(LabelBase, AttributeCopier):
- """
- Axis Label. Derived from Text. The position of the text is updated
- in the fly, so changing text position has no effect. Otherwise, the
- properties can be changed as a normal Text.
-
- To change the pad between ticklabels and axis label, use set_pad.
- """
-
- def __init__(self, *kl, **kwargs):
-
- axis_direction = kwargs.pop("axis_direction", "bottom")
- self._axis = kwargs.pop("axis", None)
- #super(AxisLabel, self).__init__(*kl, **kwargs)
- LabelBase.__init__(self, *kl, **kwargs)
- AttributeCopier.__init__(self, self._axis, klass=LabelBase)
-
- self.set_axis_direction(axis_direction)
- self._pad = 5
- self._extra_pad = 0
-
- def set_pad(self, pad):
- """
- Set the pad in points. Note that the actual pad will be the
- sum of the internal pad and the external pad (that are set
- automatically by the AxisArtist), and it only set the internal
- pad
- """
- self._pad = pad
-
- def get_pad(self):
- """
- return pad in points. See set_pad for more details.
- """
- return self._pad
-
-
- def _set_external_pad(self, p):
- """
- Set external pad IN PIXELS. This is intended to be set by the
- AxisArtist, bot by user..
- """
- self._extra_pad = p
-
- def _get_external_pad(self):
- """
- Get external pad.
- """
- return self._extra_pad
-
-
- def get_ref_artist(self):
- return self._axis.get_label()
-
-
- def get_text(self):
- t = super(AxisLabel, self).get_text()
- if t == "__from_axes__":
- return self._axis.get_label().get_text()
- return self._text
-
- _default_alignments = dict(left=("bottom", "center"),
- right=("top", "center"),
- bottom=("top", "center"),
- top=("bottom", "center"))
-
-
-
- def set_default_alignment(self, d):
- if d not in ["left", "right", "top", "bottom"]:
- raise ValueError('direction must be on of "left", "right", "top", "bottom"')
-
- va, ha = self._default_alignments[d]
- self.set_va(va)
- self.set_ha(ha)
-
-
- _default_angles = dict(left=180,
- right=0,
- bottom=0,
- top=180)
-
-
- def set_default_angle(self, d):
- if d not in ["left", "right", "top", "bottom"]:
- raise ValueError('direction must be on of "left", "right", "top", "bottom"')
-
- self.set_rotation(self._default_angles[d])
-
-
- def set_axis_direction(self, d):
- """
- Adjust the text angle and text alignment of axis label
- according to the matplotlib convention.
-
-
- ===================== ========== ========= ========== ==========
- property left bottom right top
- ===================== ========== ========= ========== ==========
- axislabel angle 180 0 0 180
- axislabel va center top center bottom
- axislabel ha right center right center
- ===================== ========== ========= ========== ==========
-
- Note that the text angles are actually relative to (90 + angle
- of the direction to the ticklabel), which gives 0 for bottom
- axis.
-
- """
- if d not in ["left", "right", "top", "bottom"]:
- raise ValueError('direction must be on of "left", "right", "top", "bottom"')
-
- self.set_default_alignment(d)
- self.set_default_angle(d)
-
- def get_color(self):
- return self.get_attribute_from_ref_artist("color", "k")
-
- def draw(self, renderer):
- if not self.get_visible():
- return
-
- pad = renderer.points_to_pixels(self.get_pad())
- r = self._get_external_pad() + pad
- self._set_offset_radius(r)
-
- super(AxisLabel, self).draw(renderer)
-
-
- def get_window_extent(self, renderer):
-
- if not self.get_visible():
- return
-
- pad = renderer.points_to_pixels(self.get_pad())
- r = self._get_external_pad() + pad
- self._set_offset_radius(r)
-
- bb = super(AxisLabel, self).get_window_extent(renderer)
-
- return bb
-
-
-class TickLabels(AxisLabel, AttributeCopier): # mtext.Text
- """
- Tick Labels. While derived from Text, this single artist draws all
- ticklabels. As in AxisLabel, the position of the text is updated
- in the fly, so changing text position has no effect. Otherwise,
- the properties can be changed as a normal Text. Unlike the
- ticklabels of the mainline matplotlib, properties of single
- ticklabel alone cannot modified.
-
- To change the pad between ticks and ticklabels, use set_pad.
- """
-
- def __init__(self, **kwargs):
-
- axis_direction = kwargs.pop("axis_direction", "bottom")
- AxisLabel.__init__(self, **kwargs)
- self.set_axis_direction(axis_direction)
- #self._axis_direction = axis_direction
- self._axislabel_pad = 0
- #self._extra_pad = 0
-
-
- # attribute copier
- def get_ref_artist(self):
- return self._axis.get_ticklabels()[0]
-
- def set_axis_direction(self, label_direction):
- """
- Adjust the text angle and text alignment of ticklabels
- according to the matplotlib convention.
-
- The *label_direction* must be one of [left, right, bottom,
- top].
-
- ===================== ========== ========= ========== ==========
- property left bottom right top
- ===================== ========== ========= ========== ==========
- ticklabels angle 90 0 -90 180
- ticklabel va center baseline center baseline
- ticklabel ha right center right center
- ===================== ========== ========= ========== ==========
-
-
- Note that the text angles are actually relative to (90 + angle
- of the direction to the ticklabel), which gives 0 for bottom
- axis.
-
- """
-
- if label_direction not in ["left", "right", "top", "bottom"]:
- raise ValueError('direction must be one of "left", "right", "top", "bottom"')
-
- self._axis_direction = label_direction
- self.set_default_alignment(label_direction)
- self.set_default_angle(label_direction)
-
-
- def invert_axis_direction(self):
- label_direction = self._get_opposite_direction(self._axis_direction)
- self.set_axis_direction(label_direction)
-
- def _get_ticklabels_offsets(self, renderer, label_direction):
- """
- Calculates the offsets of the ticklabels from the tick and
- their total heights. The offset only takes account the offset
- due to the vertical alignment of the ticklabels, i.e.,if axis
- direction is bottom and va is ;top', it will return 0. if va
- is 'baseline', it will return (height-descent).
- """
- whd_list = self.get_texts_widths_heights_descents(renderer)
-
- if not whd_list:
- return 0, 0
-
- r = 0
- va, ha = self.get_va(), self.get_ha()
-
- if label_direction == "left":
- pad = max(w for w, h, d in whd_list)
- if ha == "left":
- r = pad
- elif ha == "center":
- r = .5 * pad
- elif label_direction == "right":
- pad = max(w for w, h, d in whd_list)
- if ha == "right":
- r = pad
- elif ha == "center":
- r = .5 * pad
- elif label_direction == "bottom":
- pad = max(h for w, h, d in whd_list)
- if va == "bottom":
- r = pad
- elif va == "center":
- r =.5 * pad
- elif va == "baseline":
- max_ascent = max(h - d for w, h, d in whd_list)
- max_descent = max(d for w, h, d in whd_list)
- r = max_ascent
- pad = max_ascent + max_descent
- elif label_direction == "top":
- pad = max(h for w, h, d in whd_list)
- if va == "top":
- r = pad
- elif va == "center":
- r =.5 * pad
- elif va == "baseline":
- max_ascent = max(h - d for w, h, d in whd_list)
- max_descent = max(d for w, h, d in whd_list)
- r = max_descent
- pad = max_ascent + max_descent
-
- #tick_pad = renderer.points_to_pixels(self.get_pad())
-
- # r : offset
-
- # pad : total height of the ticklabels. This will be used to
- # calculate the pad for the axislabel.
- return r, pad
-
-
-
- _default_alignments = dict(left=("center", "right"),
- right=("center", "left"),
- bottom=("baseline", "center"),
- top=("baseline", "center"))
-
-
-
- # set_default_alignments(self, d)
-
- _default_angles = dict(left=90,
- right=-90,
- bottom=0,
- top=180)
-
-
- def draw(self, renderer):
- if not self.get_visible():
- self._axislabel_pad = self._get_external_pad()
- return
-
- r, total_width = self._get_ticklabels_offsets(renderer,
- self._axis_direction)
-
- #self._set_external_pad(r+self._get_external_pad())
- pad = self._get_external_pad() + \
- renderer.points_to_pixels(self.get_pad())
- self._set_offset_radius(r+pad)
-
- #self._set_offset_radius(r)
-
- for (x, y), a, l in self._locs_angles_labels:
- if not l.strip(): continue
- self._set_ref_angle(a) #+ add_angle
- self.set_x(x)
- self.set_y(y)
- self.set_text(l)
- LabelBase.draw(self, renderer)
-
- self._axislabel_pad = total_width \
- + pad # the value saved will be used to draw axislabel.
-
-
- def set_locs_angles_labels(self, locs_angles_labels):
- self._locs_angles_labels = locs_angles_labels
-
- def get_window_extents(self, renderer):
-
- if not self.get_visible():
- self._axislabel_pad = self._get_external_pad()
- return []
-
- bboxes = []
-
- r, total_width = self._get_ticklabels_offsets(renderer,
- self._axis_direction)
-
- pad = self._get_external_pad() + \
- renderer.points_to_pixels(self.get_pad())
- self._set_offset_radius(r+pad)
-
-
- for (x, y), a, l in self._locs_angles_labels:
- self._set_ref_angle(a) #+ add_angle
- self.set_x(x)
- self.set_y(y)
- self.set_text(l)
- bb = LabelBase.get_window_extent(self, renderer)
- bboxes.append(bb)
-
- self._axislabel_pad = total_width \
- + pad # the value saved will be used to draw axislabel.
-
- return bboxes
-
-
- def get_texts_widths_heights_descents(self, renderer):
- """
- return a list of width, height, descent for ticklabels.
- """
- whd_list = []
- for (x, y), a, l in self._locs_angles_labels:
- if not l.strip(): continue
- clean_line, ismath = self.is_math_text(l)
- whd = renderer.get_text_width_height_descent(
- clean_line, self._fontproperties, ismath=ismath)
- whd_list.append(whd)
-
- return whd_list
-
-
-class GridlinesCollection(LineCollection):
- def __init__(self, *kl, **kwargs):
- """
- *which* : "major" or "minor"
- *axis* : "both", "x" or "y"
- """
- self._which = kwargs.pop("which", "major")
- self._axis = kwargs.pop("axis", "both")
- super(GridlinesCollection, self).__init__(*kl, **kwargs)
- self.set_grid_helper(None)
-
- def set_which(self, which):
- self._which = which
-
- def set_axis(self, axis):
- self._axis = axis
-
- def set_grid_helper(self, grid_helper):
- self._grid_helper = grid_helper
-
- def draw(self, renderer):
- if self._grid_helper is not None:
- self._grid_helper.update_lim(self.axes)
- gl = self._grid_helper.get_gridlines(self._which, self._axis)
- if gl:
- self.set_segments([np.transpose(l) for l in gl])
- else:
- self.set_segments([])
- super(GridlinesCollection, self).draw(renderer)
-
-
-
-
-class AxisArtist(martist.Artist):
- """
- An artist which draws axis (a line along which the n-th axes coord
- is constant) line, ticks, ticklabels, and axis label.
- """
-
- ZORDER=2.5
-
- @property
- def LABELPAD(self):
- return self.label.get_pad()
-
- @LABELPAD.setter
- def LABELPAD(self, v):
- return self.label.set_pad(v)
-
- def __init__(self, axes,
- helper,
- offset=None,
- axis_direction="bottom",
- **kw):
- """
- *axes* : axes
- *helper* : an AxisArtistHelper instance.
- """
- #axes is also used to follow the axis attribute (tick color, etc).
-
- super(AxisArtist, self).__init__(**kw)
-
- self.axes = axes
-
- self._axis_artist_helper = helper
-
- if offset is None:
- offset = (0, 0)
- self.dpi_transform = Affine2D()
- self.offset_transform = ScaledTranslation(offset[0], offset[1],
- self.dpi_transform)
-
- self._label_visible = True
- self._majortick_visible = True
- self._majorticklabel_visible = True
- self._minortick_visible = True
- self._minorticklabel_visible = True
-
-
- #if self._axis_artist_helper._loc in ["left", "right"]:
- if axis_direction in ["left", "right"]:
- axis_name = "ytick"
- self.axis = axes.yaxis
- else:
- axis_name = "xtick"
- self.axis = axes.xaxis
-
-
- self._axisline_style = None
-
-
- self._axis_direction = axis_direction
-
-
- self._init_line()
- self._init_ticks(axis_name, **kw)
- self._init_offsetText(axis_direction)
- self._init_label()
-
- self.set_zorder(self.ZORDER)
-
- self._rotate_label_along_line = False
-
- # axis direction
- self._tick_add_angle = 180.
- self._ticklabel_add_angle = 0.
- self._axislabel_add_angle = 0.
- self.set_axis_direction(axis_direction)
-
-
- # axis direction
-
- def set_axis_direction(self, axis_direction):
- """
- Adjust the direction, text angle, text alignment of
- ticklabels, labels following the matplotlib convention for
- the rectangle axes.
-
- The *axis_direction* must be one of [left, right, bottom,
- top].
-
- ===================== ========== ========= ========== ==========
- property left bottom right top
- ===================== ========== ========= ========== ==========
- ticklabels location "-" "+" "+" "-"
- axislabel location "-" "+" "+" "-"
- ticklabels angle 90 0 -90 180
- ticklabel va center baseline center baseline
- ticklabel ha right center right center
- axislabel angle 180 0 0 180
- axislabel va center top center bottom
- axislabel ha right center right center
- ===================== ========== ========= ========== ==========
-
-
- Note that the direction "+" and "-" are relative to the direction of
- the increasing coordinate. Also, the text angles are actually
- relative to (90 + angle of the direction to the ticklabel),
- which gives 0 for bottom axis.
-
- """
-
- if axis_direction not in ["left", "right", "top", "bottom"]:
- raise ValueError('direction must be on of "left", "right", "top", "bottom"')
- self._axis_direction = axis_direction
- if axis_direction in ["left", "top"]:
- #self._set_tick_direction("+")
- self.set_ticklabel_direction("-")
- self.set_axislabel_direction("-")
- else:
- #self._set_tick_direction("-")
- self.set_ticklabel_direction("+")
- self.set_axislabel_direction("+")
-
- self.major_ticklabels.set_axis_direction(axis_direction)
- self.label.set_axis_direction(axis_direction)
-
- # def _set_tick_direction(self, d):
- # if d not in ["+", "-"]:
- # raise ValueError('direction must be on of "in", "out"')
-
- # if d == "+":
- # self._tick_add_angle = 0 #get_helper()._extremes=0, 10
- # else:
- # self._tick_add_angle = 180 #get_helper()._extremes=0, 10
-
- def set_ticklabel_direction(self, tick_direction):
- """
- Adjust the direction of the ticklabel.
-
- ACCEPTS: [ "+" | "-" ]
-
- Note that the label_direction '+' and '-' are relative to the
- direction of the increasing coordinate.
- """
-
- if tick_direction not in ["+", "-"]:
- raise ValueError('direction must be one of "+", "-"')
-
- if tick_direction == "-":
- self._ticklabel_add_angle = 180
- else:
- self._ticklabel_add_angle = 0
-
- def invert_ticklabel_direction(self):
- self._ticklabel_add_angle = (self._ticklabel_add_angle + 180) % 360
- self.major_ticklabels.invert_axis_direction()
- self.minor_ticklabels.invert_axis_direction()
-
- # def invert_ticks_direction(self):
- # self.major_ticks.set_tick_out(not self.major_ticks.get_tick_out())
- # self.minor_ticks.set_tick_out(not self.minor_ticks.get_tick_out())
-
- def set_axislabel_direction(self, label_direction):
- """
- Adjust the direction of the axislabel.
-
- ACCEPTS: [ "+" | "-" ]
-
- Note that the label_direction '+' and '-' are relative to the
- direction of the increasing coordinate.
- """
- if label_direction not in ["+", "-"]:
- raise ValueError('direction must be one of "+", "-"')
-
- if label_direction == "-":
- self._axislabel_add_angle = 180
- else:
- self._axislabel_add_angle = 0
-
-
-
- def get_transform(self):
- return self.axes.transAxes + self.offset_transform
-
- def get_helper(self):
- """
- Return axis artist helper instance.
- """
- return self._axis_artist_helper
-
-
- def set_axisline_style(self, axisline_style=None, **kw):
- """
- Set the axisline style.
-
- *axisline_style* can be a string with axisline style name with optional
- comma-separated attributes. Alternatively, the attrs can
- be provided as keywords.
-
- set_arrowstyle("->,size=1.5")
- set_arrowstyle("->", size=1.5)
-
- Old attrs simply are forgotten.
-
- Without argument (or with arrowstyle=None), return
- available styles as a list of strings.
- """
-
- if axisline_style==None:
- return AxislineStyle.pprint_styles()
-
- if isinstance(axisline_style, AxislineStyle._Base):
- self._axisline_style = axisline_style
- else:
- self._axisline_style = AxislineStyle(axisline_style, **kw)
-
-
- self._init_line()
-
-
- def get_axisline_style(self):
- """
- return the current axisline style.
- """
- return self._axisline_style
-
- def _init_line(self):
- """
- Initialize the *line* artist that is responsible to draw the axis line.
- """
- tran = self._axis_artist_helper.get_line_transform(self.axes) \
- + self.offset_transform
-
- axisline_style = self.get_axisline_style()
- if axisline_style is None:
- self.line = BezierPath(self._axis_artist_helper.get_line(self.axes),
- color=rcParams['axes.edgecolor'],
- linewidth=rcParams['axes.linewidth'],
- transform=tran)
- else:
- self.line = axisline_style(self, transform=tran)
-
- def _draw_line(self, renderer):
- self.line.set_path(self._axis_artist_helper.get_line(self.axes))
- if self.get_axisline_style() is not None:
- self.line.set_line_mutation_scale(self.major_ticklabels.get_size())
- self.line.draw(renderer)
-
-
- def _init_ticks(self, axis_name, **kw):
-
- trans=self._axis_artist_helper.get_tick_transform(self.axes) \
- + self.offset_transform
-
-
- major_tick_size = kw.get("major_tick_size",
- rcParams['%s.major.size'%axis_name])
- major_tick_pad = kw.get("major_tick_pad",
- rcParams['%s.major.pad'%axis_name])
- minor_tick_size = kw.get("minor_tick_size",
- rcParams['%s.minor.size'%axis_name])
- minor_tick_pad = kw.get("minor_tick_pad",
- rcParams['%s.minor.pad'%axis_name])
-
- self.major_ticks = Ticks(major_tick_size,
- axis=self.axis,
- transform=trans)
- self.minor_ticks = Ticks(minor_tick_size,
- axis=self.axis,
- transform=trans)
-
- if axis_name == "xaxis":
- size = rcParams['xtick.labelsize']
- else:
- size = rcParams['ytick.labelsize']
-
-
- fontprops = font_manager.FontProperties(size=size)
-
- self.major_ticklabels = TickLabels(size=size, axis=self.axis,
- axis_direction=self._axis_direction)
- self.minor_ticklabels = TickLabels(size=size, axis=self.axis,
- axis_direction=self._axis_direction)
-
-
- self.major_ticklabels.set(figure = self.axes.figure,
- transform=trans,
- fontproperties=fontprops)
- self.major_ticklabels.set_pad(major_tick_pad)
-
- self.minor_ticklabels.set(figure = self.axes.figure,
- transform=trans,
- fontproperties=fontprops)
- self.minor_ticklabels.set_pad(minor_tick_pad)
-
-
-
- def _get_tick_info(self, tick_iter):
- """
- return ticks_loc_angle, ticklabels_loc_angle_label
-
- ticks_loc_angle : list of locs and angles for ticks
- ticklabels_loc_angle_label : list of locs, angles and labels for tickslabels
- """
- ticks_loc_angle = []
- ticklabels_loc_angle_label = []
-
- tick_add_angle = self._tick_add_angle
- ticklabel_add_angle = self._ticklabel_add_angle
-
- for loc, angle_normal, angle_tangent, label in tick_iter:
- angle_label = angle_tangent - 90
- angle_label += ticklabel_add_angle
-
- if np.cos((angle_label - angle_normal)/180.*np.pi) < 0.:
- angle_tick = angle_normal
- else:
- angle_tick = angle_normal + 180
-
- ticks_loc_angle.append([loc, angle_tick])
- ticklabels_loc_angle_label.append([loc, angle_label, label])
-
- return ticks_loc_angle, ticklabels_loc_angle_label
-
-
- def _update_ticks(self, renderer):
-
-
- # set extra pad for major and minor ticklabels:
- # use ticksize of majorticks even for minor ticks. not clear what is best.
-
- dpi_cor = renderer.points_to_pixels(1.)
- if self.major_ticks.get_visible() and self.major_ticks.get_tick_out():
- self.major_ticklabels._set_external_pad(self.major_ticks._ticksize*dpi_cor)
- self.minor_ticklabels._set_external_pad(self.major_ticks._ticksize*dpi_cor)
- else:
- self.major_ticklabels._set_external_pad(0)
- self.minor_ticklabels._set_external_pad(0)
-
-
- majortick_iter, minortick_iter = \
- self._axis_artist_helper.get_tick_iterators(self.axes)
-
- tick_loc_angle, ticklabel_loc_angle_label \
- = self._get_tick_info(majortick_iter)
-
- self.major_ticks.set_locs_angles(tick_loc_angle)
- self.major_ticklabels.set_locs_angles_labels(ticklabel_loc_angle_label)
-
- #self.major_ticks.draw(renderer)
- #self.major_ticklabels.draw(renderer)
-
-
- # minor ticks
- tick_loc_angle, ticklabel_loc_angle_label \
- = self._get_tick_info(minortick_iter)
-
- self.minor_ticks.set_locs_angles(tick_loc_angle)
- self.minor_ticklabels.set_locs_angles_labels(ticklabel_loc_angle_label)
-
- #self.minor_ticks.draw(renderer)
- #self.minor_ticklabels.draw(renderer)
-
-
- #if (self.major_ticklabels.get_visible() or self.minor_ticklabels.get_visible()):
- # self._draw_offsetText(renderer)
-
- return self.major_ticklabels.get_window_extents(renderer)
-
-
- def _draw_ticks(self, renderer):
-
- extents = self._update_ticks(renderer)
-
- self.major_ticks.draw(renderer)
- self.major_ticklabels.draw(renderer)
-
- self.minor_ticks.draw(renderer)
- self.minor_ticklabels.draw(renderer)
-
-
- if (self.major_ticklabels.get_visible() or self.minor_ticklabels.get_visible()):
- self._draw_offsetText(renderer)
-
- return extents
-
- def _draw_ticks2(self, renderer):
-
-
- # set extra pad for major and minor ticklabels:
- # use ticksize of majorticks even for minor ticks. not clear what is best.
-
- dpi_cor = renderer.points_to_pixels(1.)
- if self.major_ticks.get_visible() and self.major_ticks.get_tick_out():
- self.major_ticklabels._set_external_pad(self.major_ticks._ticksize*dpi_cor)
- self.minor_ticklabels._set_external_pad(self.major_ticks._ticksize*dpi_cor)
- else:
- self.major_ticklabels._set_external_pad(0)
- self.minor_ticklabels._set_external_pad(0)
-
-
- majortick_iter, minortick_iter = \
- self._axis_artist_helper.get_tick_iterators(self.axes)
-
- tick_loc_angle, ticklabel_loc_angle_label \
- = self._get_tick_info(majortick_iter)
-
- self.major_ticks.set_locs_angles(tick_loc_angle)
- self.major_ticklabels.set_locs_angles_labels(ticklabel_loc_angle_label)
-
- self.major_ticks.draw(renderer)
- self.major_ticklabels.draw(renderer)
-
-
- # minor ticks
- tick_loc_angle, ticklabel_loc_angle_label \
- = self._get_tick_info(minortick_iter)
-
- self.minor_ticks.set_locs_angles(tick_loc_angle)
- self.minor_ticklabels.set_locs_angles_labels(ticklabel_loc_angle_label)
-
- self.minor_ticks.draw(renderer)
- self.minor_ticklabels.draw(renderer)
-
-
- if (self.major_ticklabels.get_visible() or self.minor_ticklabels.get_visible()):
- self._draw_offsetText(renderer)
-
- return self.major_ticklabels.get_window_extents(renderer)
-
-
-
-
- _offsetText_pos = dict(left=(0, 1, "bottom", "right"),
- right=(1, 1, "bottom", "left"),
- bottom=(1, 0, "top", "right"),
- top=(1, 1, "bottom", "right"))
-
- def _init_offsetText(self, direction):
-
- x,y,va,ha = self._offsetText_pos[direction]
-
- self.offsetText = mtext.Annotation("",
- xy=(x,y), xycoords="axes fraction",
- xytext=(0,0), textcoords="offset points",
- #fontproperties = fp,
- color = rcParams['xtick.color'],
- verticalalignment=va,
- horizontalalignment=ha,
- )
- self.offsetText.set_transform(IdentityTransform())
- self.axes._set_artist_props(self.offsetText)
-
-
- def _update_offsetText(self):
- self.offsetText.set_text( self.axis.major.formatter.get_offset() )
- self.offsetText.set_size(self.major_ticklabels.get_size())
- offset = self.major_ticklabels.get_pad() + self.major_ticklabels.get_size() + 2.
- self.offsetText.xyann= (0, offset)
-
-
- def _draw_offsetText(self, renderer):
- self._update_offsetText()
- self.offsetText.draw(renderer)
-
-
-
- def _init_label(self, **kw):
- # x in axes coords, y in display coords (to be updated at draw
- # time by _update_label_positions)
-
- labelsize = kw.get("labelsize",
- rcParams['axes.labelsize'])
- #labelcolor = kw.get("labelcolor",
- # rcParams['axes.labelcolor'])
- fontprops = font_manager.FontProperties(
- size=labelsize,
- weight=rcParams['axes.labelweight'])
- textprops = dict(fontproperties = fontprops)
- #color = labelcolor)
-
- tr = self._axis_artist_helper.get_axislabel_transform(self.axes) \
- + self.offset_transform
-
- self.label = AxisLabel(0, 0, "__from_axes__",
- color = "auto", #rcParams['axes.labelcolor'],
- fontproperties=fontprops,
- axis=self.axis,
- transform=tr,
- axis_direction=self._axis_direction,
- )
-
- self.label.set_figure(self.axes.figure)
-
- labelpad = kw.get("labelpad", 5)
- self.label.set_pad(labelpad)
-
-
- def _update_label(self, renderer):
-
- if not self.label.get_visible():
- return
-
- fontprops = font_manager.FontProperties(
- size=rcParams['axes.labelsize'],
- weight=rcParams['axes.labelweight'])
-
- #pad_points = self.major_tick_pad
-
- #if abs(self._ticklabel_add_angle - self._axislabel_add_angle)%360 > 90:
- if self._ticklabel_add_angle != self._axislabel_add_angle:
- if (self.major_ticks.get_visible() and not self.major_ticks.get_tick_out()) \
- or \
- (self.minor_ticks.get_visible() and not self.major_ticks.get_tick_out()):
- axislabel_pad = self.major_ticks._ticksize
- else:
- axislabel_pad = 0
- else:
- axislabel_pad = max(self.major_ticklabels._axislabel_pad,
- self.minor_ticklabels._axislabel_pad)
-
-
- #label_offset = axislabel_pad + self.LABELPAD
-
- #self.label._set_offset_radius(label_offset)
- self.label._set_external_pad(axislabel_pad)
-
- xy, angle_tangent = self._axis_artist_helper.get_axislabel_pos_angle(self.axes)
- if xy is None: return
-
- angle_label = angle_tangent - 90
-
-
- x, y = xy
- self.label._set_ref_angle(angle_label+self._axislabel_add_angle)
- self.label.set(x=x, y=y)
-
-
- def _draw_label(self, renderer):
- self._update_label(renderer)
- self.label.draw(renderer)
-
- def _draw_label2(self, renderer):
-
- if not self.label.get_visible():
- return
-
- fontprops = font_manager.FontProperties(
- size=rcParams['axes.labelsize'],
- weight=rcParams['axes.labelweight'])
-
- #pad_points = self.major_tick_pad
-
- #if abs(self._ticklabel_add_angle - self._axislabel_add_angle)%360 > 90:
- if self._ticklabel_add_angle != self._axislabel_add_angle:
- if (self.major_ticks.get_visible() and not self.major_ticks.get_tick_out()) \
- or \
- (self.minor_ticks.get_visible() and not self.major_ticks.get_tick_out()):
- axislabel_pad = self.major_ticks._ticksize
- else:
- axislabel_pad = 0
- else:
- axislabel_pad = max(self.major_ticklabels._axislabel_pad,
- self.minor_ticklabels._axislabel_pad)
-
- #label_offset = axislabel_pad + self.LABELPAD
-
- #self.label._set_offset_radius(label_offset)
- self.label._set_external_pad(axislabel_pad)
-
- xy, angle_tangent = self._axis_artist_helper.get_axislabel_pos_angle(self.axes)
- if xy is None: return
-
- angle_label = angle_tangent - 90
-
- x, y = xy
- self.label._set_ref_angle(angle_label+self._axislabel_add_angle)
- self.label.set(x=x, y=y)
- self.label.draw(renderer)
-
-
-
- def set_label(self, s):
- self.label.set_text(s)
-
-
-
- def get_tightbbox(self, renderer):
- if not self.get_visible(): return
-
- self._axis_artist_helper.update_lim(self.axes)
-
- dpi_cor = renderer.points_to_pixels(1.)
- self.dpi_transform.clear().scale(dpi_cor, dpi_cor)
-
-
- bb = []
-
- self._update_ticks(renderer)
-
- #if self.major_ticklabels.get_visible():
- bb.extend(self.major_ticklabels.get_window_extents(renderer))
- #if self.minor_ticklabels.get_visible():
- bb.extend(self.minor_ticklabels.get_window_extents(renderer))
-
-
- self._update_label(renderer)
-
- #if self.label.get_visible():
- bb.append(self.label.get_window_extent(renderer))
- bb.append(self.offsetText.get_window_extent(renderer))
-
- bb = [b for b in bb if b and (b.width!=0 or b.height!=0)]
- if bb:
- _bbox = Bbox.union(bb)
- return _bbox
- else:
- return None
-
- #self._draw_line(renderer)
-
- #self._draw_ticks(renderer)
-
- #self._draw_offsetText(renderer)
- #self._draw_label(renderer)
-
-
-
- @allow_rasterization
- def draw(self, renderer):
- 'Draw the axis lines, tick lines and labels'
-
- if not self.get_visible(): return
-
- renderer.open_group(__name__)
-
- self._axis_artist_helper.update_lim(self.axes)
-
- dpi_cor = renderer.points_to_pixels(1.)
- self.dpi_transform.clear().scale(dpi_cor, dpi_cor)
-
-
- self._draw_ticks(renderer)
-
- self._draw_line(renderer)
-
- #self._draw_offsetText(renderer)
- self._draw_label(renderer)
-
- renderer.close_group(__name__)
-
- #def get_ticklabel_extents(self, renderer):
- # pass
-
- def toggle(self, all=None, ticks=None, ticklabels=None, label=None):
- """
- Toggle visibility of ticks, ticklabels, and (axis) label.
- To turn all off, ::
-
- axis.toggle(all=False)
-
- To turn all off but ticks on ::
-
- axis.toggle(all=False, ticks=True)
-
- To turn all on but (axis) label off ::
-
- axis.toggle(all=True, label=False))
-
- """
- if all:
- _ticks, _ticklabels, _label = True, True, True
- elif all is not None:
- _ticks, _ticklabels, _label = False, False, False
- else:
- _ticks, _ticklabels, _label = None, None, None
-
- if ticks is not None:
- _ticks = ticks
- if ticklabels is not None:
- _ticklabels = ticklabels
- if label is not None:
- _label = label
-
- if _ticks is not None:
- self.major_ticks.set_visible(_ticks)
- self.minor_ticks.set_visible(_ticks)
- if _ticklabels is not None:
- self.major_ticklabels.set_visible(_ticklabels)
- self.minor_ticklabels.set_visible(_ticklabels)
- if _label is not None:
- self.label.set_visible(_label)
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axisline_style.py b/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axisline_style.py
deleted file mode 100644
index 876f5fe1898..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axisline_style.py
+++ /dev/null
@@ -1,168 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-
-from matplotlib.patches import _Style, FancyArrowPatch
-from matplotlib.transforms import IdentityTransform
-from matplotlib.path import Path
-import numpy as np
-
-class _FancyAxislineStyle(object):
- class SimpleArrow(FancyArrowPatch):
- """
- The artist class that will be returned for SimpleArrow style.
- """
- _ARROW_STYLE = "->"
-
- def __init__(self, axis_artist, line_path, transform,
- line_mutation_scale):
- self._axis_artist = axis_artist
- self._line_transform = transform
- self._line_path = line_path
- self._line_mutation_scale = line_mutation_scale
-
- FancyArrowPatch.__init__(self,
- path=self._line_path,
- arrowstyle=self._ARROW_STYLE,
- arrow_transmuter=None,
- patchA=None,
- patchB=None,
- shrinkA=0.,
- shrinkB=0.,
- mutation_scale=line_mutation_scale,
- mutation_aspect=None,
- transform=IdentityTransform(),
- )
-
- def set_line_mutation_scale(self, scale):
- self.set_mutation_scale(scale*self._line_mutation_scale)
-
- def _extend_path(self, path, mutation_size=10):
- """
- Extend the path to make a room for drawing arrow.
- """
- from matplotlib.bezier import get_cos_sin
-
- x0, y0 = path.vertices[-2]
- x1, y1 = path.vertices[-1]
- cost, sint = get_cos_sin(x0, y0, x1, y1)
-
- d = mutation_size * 1.
- x2, y2 = x1 + cost*d, y1+sint*d
-
- if path.codes is None:
- _path = Path(np.concatenate([path.vertices, [[x2, y2]]]))
- else:
- _path = Path(np.concatenate([path.vertices, [[x2, y2]]]),
- np.concatenate([path.codes, [Path.LINETO]]))
-
- return _path
-
- def set_path(self, path):
- self._line_path = path
-
- def draw(self, renderer):
- """
- Draw the axis line.
- 1) transform the path to the display coordinate.
- 2) extend the path to make a room for arrow
- 3) update the path of the FancyArrowPatch.
- 4) draw
- """
- path_in_disp = self._line_transform.transform_path(self._line_path)
- mutation_size = self.get_mutation_scale() #line_mutation_scale()
- extented_path = self._extend_path(path_in_disp,
- mutation_size=mutation_size)
-
- self._path_original = extented_path
- FancyArrowPatch.draw(self, renderer)
-
- class FilledArrow(SimpleArrow):
- """
- The artist class that will be returned for SimpleArrow style.
- """
- _ARROW_STYLE = "-|>"
-
-
-class AxislineStyle(_Style):
- """
- :class:`AxislineStyle` is a container class which defines style classes
- for AxisArtists.
-
- An instance of any axisline style class is an callable object,
- whose call signature is ::
-
- __call__(self, axis_artist, path, transform)
-
- When called, this should return a mpl artist with following
- methods implemented. ::
-
- def set_path(self, path):
- # set the path for axisline.
-
- def set_line_mutation_scale(self, scale):
- # set the scale
-
- def draw(self, renderer):
- # draw
-
-
- """
-
- _style_list = {}
-
-
- class _Base(object):
- # The derived classes are required to be able to be initialized
- # w/o arguments, i.e., all its argument (except self) must have
- # the default values.
-
- def __init__(self):
- """
- initialization.
- """
- super(AxislineStyle._Base, self).__init__()
-
-
-
-
- def __call__(self, axis_artist, transform):
- """
- Given the AxisArtist instance, and transform for the path
- (set_path method), return the mpl artist for drawing the axis line.
- """
-
- return self.new_line(axis_artist, transform)
-
-
- class SimpleArrow(_Base):
- """
- A simple arrow.
- """
-
- ArrowAxisClass = _FancyAxislineStyle.SimpleArrow
-
- def __init__(self, size=1):
- """
- *size*
- size of the arrow as a fraction of the ticklabel size.
- """
-
- self.size = size
- super(AxislineStyle.SimpleArrow, self).__init__()
-
- def new_line(self, axis_artist, transform):
-
- linepath = Path([(0,0), (0, 1)])
- axisline = self.ArrowAxisClass(axis_artist, linepath, transform,
- line_mutation_scale=self.size)
- return axisline
-
-
- _style_list["->"] = SimpleArrow
-
- class FilledArrow(SimpleArrow):
- ArrowAxisClass = _FancyAxislineStyle.FilledArrow
-
- _style_list["-|>"] = FilledArrow
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axislines.py b/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axislines.py
deleted file mode 100644
index 6182608cc5b..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axislines.py
+++ /dev/null
@@ -1,828 +0,0 @@
-"""
-Axislines includes modified implementation of the Axes class. The
-biggest difference is that the artists responsible for drawing the axis spine,
-ticks, ticklabels and axis labels are separated out from mpl's Axis
-class. Originally, this change was motivated to support curvilinear
-grid. Here are a few reasons that I came up with a new axes class:
-
-
- * "top" and "bottom" x-axis (or "left" and "right" y-axis) can have
- different ticks (tick locations and labels). This is not possible
- with the current mpl, although some twin axes trick can help.
-
- * Curvilinear grid.
-
- * angled ticks.
-
-In the new axes class, xaxis and yaxis is set to not visible by
-default, and new set of artist (AxisArtist) are defined to draw axis
-line, ticks, ticklabels and axis label. Axes.axis attribute serves as
-a dictionary of these artists, i.e., ax.axis["left"] is a AxisArtist
-instance responsible to draw left y-axis. The default Axes.axis contains
-"bottom", "left", "top" and "right".
-
-AxisArtist can be considered as a container artist and
-has following children artists which will draw ticks, labels, etc.
-
- * line
- * major_ticks, major_ticklabels
- * minor_ticks, minor_ticklabels
- * offsetText
- * label
-
-Note that these are separate artists from Axis class of the
-original mpl, thus most of tick-related command in the original mpl
-won't work, although some effort has made to work with. For example,
-color and markerwidth of the ax.axis["bottom"].major_ticks will follow
-those of Axes.xaxis unless explicitly specified.
-
-In addition to AxisArtist, the Axes will have *gridlines* attribute,
-which obviously draws grid lines. The gridlines needs to be separated
-from the axis as some gridlines can never pass any axis.
-
-"""
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-
-import warnings
-
-import numpy as np
-
-from matplotlib import rcParams
-import matplotlib.artist as martist
-import matplotlib.axes as maxes
-from matplotlib.path import Path
-from matplotlib.transforms import Bbox
-from .axisline_style import AxislineStyle
-from .axis_artist import AxisArtist, GridlinesCollection
-
-
-class AxisArtistHelper(object):
- """
- AxisArtistHelper should define
- following method with given APIs. Note that the first axes argument
- will be axes attribute of the caller artist.::
-
-
- # LINE (spinal line?)
-
- def get_line(self, axes):
- # path : Path
- return path
-
- def get_line_transform(self, axes):
- # ...
- # trans : transform
- return trans
-
- # LABEL
-
- def get_label_pos(self, axes):
- # x, y : position
- return (x, y), trans
-
-
- def get_label_offset_transform(self, \
- axes,
- pad_points, fontprops, renderer,
- bboxes,
- ):
- # va : vertical alignment
- # ha : horizontal alignment
- # a : angle
- return trans, va, ha, a
-
- # TICK
-
- def get_tick_transform(self, axes):
- return trans
-
- def get_tick_iterators(self, axes):
- # iter : iterable object that yields (c, angle, l) where
- # c, angle, l is position, tick angle, and label
-
- return iter_major, iter_minor
-
-
- """
-
- class _Base(object):
- """
- Base class for axis helper.
- """
- def __init__(self):
- """
- """
- self.delta1, self.delta2 = 0.00001, 0.00001
-
- def update_lim(self, axes):
- pass
-
-
- class Fixed(_Base):
- """
- Helper class for a fixed (in the axes coordinate) axis.
- """
-
- _default_passthru_pt = dict(left=(0, 0),
- right=(1, 0),
- bottom=(0, 0),
- top=(0, 1))
-
- def __init__(self,
- loc, nth_coord=None,
- ):
- """
- nth_coord = along which coordinate value varies
- in 2d, nth_coord = 0 -> x axis, nth_coord = 1 -> y axis
- """
-
- self._loc = loc
-
- if loc not in ["left", "right", "bottom", "top"]:
- raise ValueError("%s" % loc)
-
- if nth_coord is None:
- if loc in ["left", "right"]:
- nth_coord = 1
- elif loc in ["bottom", "top"]:
- nth_coord = 0
-
- self.nth_coord = nth_coord
-
- super(AxisArtistHelper.Fixed, self).__init__()
-
- self.passthru_pt = self._default_passthru_pt[loc]
-
-
-
- _verts = np.array([[0., 0.],
- [1., 1.]])
- fixed_coord = 1-nth_coord
- _verts[:,fixed_coord] = self.passthru_pt[fixed_coord]
-
- # axis line in transAxes
- self._path = Path(_verts)
-
-
- def get_nth_coord(self):
- return self.nth_coord
-
- # LINE
-
- def get_line(self, axes):
- return self._path
-
- def get_line_transform(self, axes):
- return axes.transAxes
-
- # LABEL
-
- def get_axislabel_transform(self, axes):
- return axes.transAxes
-
- def get_axislabel_pos_angle(self, axes):
- """
- label reference position in transAxes.
-
- get_label_transform() returns a transform of (transAxes+offset)
- """
- loc = self._loc
- pos, angle_tangent = dict(left=((0., 0.5), 90),
- right=((1., 0.5), 90),
- bottom=((0.5, 0.), 0),
- top=((0.5, 1.), 0))[loc]
-
- return pos, angle_tangent
-
-
-
- # TICK
-
- def get_tick_transform(self, axes):
- trans_tick = [axes.get_xaxis_transform(),
- axes.get_yaxis_transform()][self.nth_coord]
-
- return trans_tick
-
-
- class Floating(_Base):
- def __init__(self, nth_coord,
- value):
-
- self.nth_coord = nth_coord
-
- self._value = value
-
- super(AxisArtistHelper.Floating,
- self).__init__()
-
-
- def get_nth_coord(self):
- return self.nth_coord
-
- def get_line(self, axes):
- raise RuntimeError("get_line method should be defined by the derived class")
-
-
-
-
-class AxisArtistHelperRectlinear(object):
-
- class Fixed(AxisArtistHelper.Fixed):
-
- def __init__(self, axes, loc, nth_coord=None):
- """
- nth_coord = along which coordinate value varies
- in 2d, nth_coord = 0 -> x axis, nth_coord = 1 -> y axis
- """
- super(AxisArtistHelperRectlinear.Fixed, self).__init__(
- loc, nth_coord)
- self.axis = [axes.xaxis, axes.yaxis][self.nth_coord]
-
- # TICK
-
- def get_tick_iterators(self, axes):
- """tick_loc, tick_angle, tick_label"""
-
- loc = self._loc
-
- if loc in ["bottom", "top"]:
- angle_normal, angle_tangent = 90, 0
- else:
- angle_normal, angle_tangent = 0, 90
-
- major = self.axis.major
- majorLocs = major.locator()
- major.formatter.set_locs(majorLocs)
- majorLabels = [major.formatter(val, i) for i, val in enumerate(majorLocs)]
-
- minor = self.axis.minor
- minorLocs = minor.locator()
- minor.formatter.set_locs(minorLocs)
- minorLabels = [minor.formatter(val, i) for i, val in enumerate(minorLocs)]
-
- trans_tick = self.get_tick_transform(axes)
-
- tr2ax = trans_tick + axes.transAxes.inverted()
-
- def _f(locs, labels):
- for x, l in zip(locs, labels):
-
- c = list(self.passthru_pt) # copy
- c[self.nth_coord] = x
-
- # check if the tick point is inside axes
- c2 = tr2ax.transform_point(c)
- #delta=0.00001
- if 0. -self.delta1<= c2[self.nth_coord] <= 1.+self.delta2:
- yield c, angle_normal, angle_tangent, l
-
- return _f(majorLocs, majorLabels), _f(minorLocs, minorLabels)
-
-
-
- class Floating(AxisArtistHelper.Floating):
- def __init__(self, axes, nth_coord,
- passingthrough_point, axis_direction="bottom"):
- super(AxisArtistHelperRectlinear.Floating, self).__init__(
- nth_coord, passingthrough_point)
- self._axis_direction = axis_direction
- self.axis = [axes.xaxis, axes.yaxis][self.nth_coord]
-
- def get_line(self, axes):
- _verts = np.array([[0., 0.],
- [1., 1.]])
-
- fixed_coord = 1-self.nth_coord
- trans_passingthrough_point = axes.transData + axes.transAxes.inverted()
- p = trans_passingthrough_point.transform_point([self._value,
- self._value])
- _verts[:,fixed_coord] = p[fixed_coord]
-
- return Path(_verts)
-
- def get_line_transform(self, axes):
- return axes.transAxes
-
- def get_axislabel_transform(self, axes):
- return axes.transAxes
-
- def get_axislabel_pos_angle(self, axes):
- """
- label reference position in transAxes.
-
- get_label_transform() returns a transform of (transAxes+offset)
- """
- loc = self._axis_direction
- #angle = dict(left=0,
- # right=0,
- # bottom=.5*np.pi,
- # top=.5*np.pi)[loc]
-
- if self.nth_coord == 0:
- angle = 0
- else:
- angle = 90
-
- _verts = [0.5, 0.5]
-
- fixed_coord = 1-self.nth_coord
- trans_passingthrough_point = axes.transData + axes.transAxes.inverted()
- p = trans_passingthrough_point.transform_point([self._value,
- self._value])
- _verts[fixed_coord] = p[fixed_coord]
- if not (0. <= _verts[fixed_coord] <= 1.):
- return None, None
- else:
- return _verts, angle
-
-
-
- def get_tick_transform(self, axes):
- return axes.transData
-
-
- def get_tick_iterators(self, axes):
- """tick_loc, tick_angle, tick_label"""
-
- loc = self._axis_direction
-
- if loc in ["bottom", "top"]:
- angle_normal, angle_tangent = 90, 0
- else:
- angle_normal, angle_tangent = 0, 90
-
- if self.nth_coord == 0:
- angle_normal, angle_tangent = 90, 0
- else:
- angle_normal, angle_tangent = 0, 90
-
- #angle = 90 - 90 * self.nth_coord
-
- major = self.axis.major
- majorLocs = major.locator()
- major.formatter.set_locs(majorLocs)
- majorLabels = [major.formatter(val, i) for i, val in enumerate(majorLocs)]
-
- minor = self.axis.minor
- minorLocs = minor.locator()
- minor.formatter.set_locs(minorLocs)
- minorLabels = [minor.formatter(val, i) for i, val in enumerate(minorLocs)]
-
- tr2ax = axes.transData + axes.transAxes.inverted()
-
- def _f(locs, labels):
- for x, l in zip(locs, labels):
-
- c = [self._value, self._value]
- c[self.nth_coord] = x
- c1, c2 = tr2ax.transform_point(c)
- if 0. <= c1 <= 1. and 0. <= c2 <= 1.:
- if 0. - self.delta1 <= [c1, c2][self.nth_coord] <= 1. + self.delta2:
- yield c, angle_normal, angle_tangent, l
-
- return _f(majorLocs, majorLabels), _f(minorLocs, minorLabels)
-
-
-
-
-
-class GridHelperBase(object):
-
- def __init__(self):
- self._force_update = True
- self._old_limits = None
- super(GridHelperBase, self).__init__()
-
-
- def update_lim(self, axes):
- x1, x2 = axes.get_xlim()
- y1, y2 = axes.get_ylim()
-
- if self._force_update or self._old_limits != (x1, x2, y1, y2):
- self._update(x1, x2, y1, y2)
- self._force_update = False
- self._old_limits = (x1, x2, y1, y2)
-
-
- def _update(self, x1, x2, y1, y2):
- pass
-
-
- def invalidate(self):
- self._force_update = True
-
- def valid(self):
- return not self._force_update
-
-
- def get_gridlines(self, which, axis):
- """
- Return list of grid lines as a list of paths (list of points).
-
- *which* : "major" or "minor"
- *axis* : "both", "x" or "y"
- """
- return []
-
- def new_gridlines(self, ax):
- """
- Create and return a new GridlineCollection instance.
-
- *which* : "major" or "minor"
- *axis* : "both", "x" or "y"
-
- """
- gridlines = GridlinesCollection(None, transform=ax.transData,
- colors=rcParams['grid.color'],
- linestyles=rcParams['grid.linestyle'],
- linewidths=rcParams['grid.linewidth'])
- ax._set_artist_props(gridlines)
- gridlines.set_grid_helper(self)
-
- ax.axes._set_artist_props(gridlines)
- # gridlines.set_clip_path(self.axes.patch)
- # set_clip_path need to be deferred after Axes.cla is completed.
- # It is done inside the cla.
-
- return gridlines
-
-
-class GridHelperRectlinear(GridHelperBase):
-
-
- def __init__(self, axes):
-
- super(GridHelperRectlinear, self).__init__()
- self.axes = axes
-
-
-
- def new_fixed_axis(self, loc,
- nth_coord=None,
- axis_direction=None,
- offset=None,
- axes=None,
- ):
-
- if axes is None:
- warnings.warn("'new_fixed_axis' explicitly requires the axes keyword.")
- axes = self.axes
-
- _helper = AxisArtistHelperRectlinear.Fixed(axes, loc, nth_coord)
-
- if axis_direction is None:
- axis_direction = loc
- axisline = AxisArtist(axes, _helper, offset=offset,
- axis_direction=axis_direction,
- )
-
- return axisline
-
-
- def new_floating_axis(self, nth_coord, value,
- axis_direction="bottom",
- axes=None,
- ):
-
- if axes is None:
- warnings.warn(
- "'new_floating_axis' explicitly requires the axes keyword.")
- axes = self.axes
-
- passthrough_point = (value, value)
- transform = axes.transData
-
- _helper = AxisArtistHelperRectlinear.Floating(
- axes, nth_coord, value, axis_direction)
-
- axisline = AxisArtist(axes, _helper)
-
- axisline.line.set_clip_on(True)
- axisline.line.set_clip_box(axisline.axes.bbox)
- return axisline
-
-
- def get_gridlines(self, which="major", axis="both"):
- """
- return list of gridline coordinates in data coordinates.
-
- *which* : "major" or "minor"
- *axis* : "both", "x" or "y"
- """
-
- gridlines = []
-
-
- if axis in ["both", "x"]:
- locs = []
- y1, y2 = self.axes.get_ylim()
- #if self.axes.xaxis._gridOnMajor:
- if which in ["both", "major"]:
- locs.extend(self.axes.xaxis.major.locator())
- #if self.axes.xaxis._gridOnMinor:
- if which in ["both", "minor"]:
- locs.extend(self.axes.xaxis.minor.locator())
-
- for x in locs:
- gridlines.append([[x, x], [y1, y2]])
-
-
- if axis in ["both", "y"]:
- x1, x2 = self.axes.get_xlim()
- locs = []
- if self.axes.yaxis._gridOnMajor:
- #if which in ["both", "major"]:
- locs.extend(self.axes.yaxis.major.locator())
- if self.axes.yaxis._gridOnMinor:
- #if which in ["both", "minor"]:
- locs.extend(self.axes.yaxis.minor.locator())
-
- for y in locs:
- gridlines.append([[x1, x2], [y, y]])
-
- return gridlines
-
-
-
-
-
-
-class SimpleChainedObjects(object):
- def __init__(self, objects):
- self._objects = objects
-
- def __getattr__(self, k):
- _a = SimpleChainedObjects([getattr(a, k) for a in self._objects])
- return _a
-
- def __call__(self, *kl, **kwargs):
- for m in self._objects:
- m(*kl, **kwargs)
-
-
-class Axes(maxes.Axes):
-
- class AxisDict(dict):
- def __init__(self, axes):
- self.axes = axes
- super(Axes.AxisDict, self).__init__()
-
- def __getitem__(self, k):
- if isinstance(k, tuple):
- r = SimpleChainedObjects([dict.__getitem__(self, k1) for k1 in k])
- return r
- elif isinstance(k, slice):
- if k.start == None and k.stop == None and k.step == None:
- r = SimpleChainedObjects(list(six.itervalues(self)))
- return r
- else:
- raise ValueError("Unsupported slice")
- else:
- return dict.__getitem__(self, k)
-
- def __call__(self, *v, **kwargs):
- return maxes.Axes.axis(self.axes, *v, **kwargs)
-
-
- def __init__(self, *kl, **kw):
-
-
- helper = kw.pop("grid_helper", None)
-
- self._axisline_on = True
-
- if helper:
- self._grid_helper = helper
- else:
- self._grid_helper = GridHelperRectlinear(self)
-
- super(Axes, self).__init__(*kl, **kw)
-
- self.toggle_axisline(True)
-
-
- def toggle_axisline(self, b=None):
- if b is None:
- b = not self._axisline_on
- if b:
- self._axisline_on = True
- for s in self.spines.values():
- s.set_visible(False)
- self.xaxis.set_visible(False)
- self.yaxis.set_visible(False)
- else:
- self._axisline_on = False
- for s in self.spines.values():
- s.set_visible(True)
- self.xaxis.set_visible(True)
- self.yaxis.set_visible(True)
-
-
- def _init_axis(self):
- super(Axes, self)._init_axis()
-
-
- def _init_axis_artists(self, axes=None):
- if axes is None:
- axes = self
-
- self._axislines = self.AxisDict(self)
- new_fixed_axis = self.get_grid_helper().new_fixed_axis
- for loc in ["bottom", "top", "left", "right"]:
- self._axislines[loc] = new_fixed_axis(loc=loc, axes=axes,
- axis_direction=loc)
-
- for axisline in [self._axislines["top"], self._axislines["right"]]:
- axisline.label.set_visible(False)
- axisline.major_ticklabels.set_visible(False)
- axisline.minor_ticklabels.set_visible(False)
-
- @property
- def axis(self):
- return self._axislines
-
- def new_gridlines(self, grid_helper=None):
- """
- Create and return a new GridlineCollection instance.
-
- *which* : "major" or "minor"
- *axis* : "both", "x" or "y"
-
- """
- if grid_helper is None:
- grid_helper = self.get_grid_helper()
-
- gridlines = grid_helper.new_gridlines(self)
-
- return gridlines
-
-
- def _init_gridlines(self, grid_helper=None):
- # It is done inside the cla.
- gridlines = self.new_gridlines(grid_helper)
-
- self.gridlines = gridlines
-
- def cla(self):
- # gridlines need to b created before cla() since cla calls grid()
-
- self._init_gridlines()
- super(Axes, self).cla()
-
- # the clip_path should be set after Axes.cla() since that's
- # when a patch is created.
- self.gridlines.set_clip_path(self.axes.patch)
-
- self._init_axis_artists()
-
- def get_grid_helper(self):
- return self._grid_helper
-
-
- def grid(self, b=None, which='major', axis="both", **kwargs):
- """
- Toggle the gridlines, and optionally set the properties of the lines.
- """
- # their are some discrepancy between the behavior of grid in
- # axes_grid and the original mpl's grid, because axes_grid
- # explicitly set the visibility of the gridlines.
-
- super(Axes, self).grid(b, which=which, axis=axis, **kwargs)
- if not self._axisline_on:
- return
-
- if b is None:
-
- if self.axes.xaxis._gridOnMinor or self.axes.xaxis._gridOnMajor or \
- self.axes.yaxis._gridOnMinor or self.axes.yaxis._gridOnMajor:
- b=True
- else:
- b=False
-
- self.gridlines.set_which(which)
- self.gridlines.set_axis(axis)
- self.gridlines.set_visible(b)
-
- if len(kwargs):
- martist.setp(self.gridlines, **kwargs)
-
- def get_children(self):
- if self._axisline_on:
- children = list(six.itervalues(self._axislines)) + [self.gridlines]
- else:
- children = []
- children.extend(super(Axes, self).get_children())
- return children
-
- def invalidate_grid_helper(self):
- self._grid_helper.invalidate()
-
-
- def new_fixed_axis(self, loc, offset=None):
- gh = self.get_grid_helper()
- axis = gh.new_fixed_axis(loc,
- nth_coord=None,
- axis_direction=None,
- offset=offset,
- axes=self,
- )
- return axis
-
-
- def new_floating_axis(self, nth_coord, value,
- axis_direction="bottom",
- ):
- gh = self.get_grid_helper()
- axis = gh.new_floating_axis(nth_coord, value,
- axis_direction=axis_direction,
- axes=self)
- return axis
-
-
-
- def draw(self, renderer, inframe=False):
-
- if not self._axisline_on:
- super(Axes, self).draw(renderer, inframe)
- return
-
- orig_artists = self.artists
- self.artists = self.artists + list(self._axislines.values()) + [self.gridlines]
-
- super(Axes, self).draw(renderer, inframe)
-
- self.artists = orig_artists
-
-
- def get_tightbbox(self, renderer, call_axes_locator=True):
-
- bb0 = super(Axes, self).get_tightbbox(renderer, call_axes_locator)
-
- if not self._axisline_on:
- return bb0
-
- bb = [bb0]
-
- for axisline in list(six.itervalues(self._axislines)):
- if not axisline.get_visible():
- continue
-
- bb.append(axisline.get_tightbbox(renderer))
- # if axisline.label.get_visible():
- # bb.append(axisline.label.get_window_extent(renderer))
-
-
- # if axisline.major_ticklabels.get_visible():
- # bb.extend(axisline.major_ticklabels.get_window_extents(renderer))
- # if axisline.minor_ticklabels.get_visible():
- # bb.extend(axisline.minor_ticklabels.get_window_extents(renderer))
- # if axisline.major_ticklabels.get_visible() or \
- # axisline.minor_ticklabels.get_visible():
- # bb.append(axisline.offsetText.get_window_extent(renderer))
-
- #bb.extend([c.get_window_extent(renderer) for c in artists \
- # if c.get_visible()])
-
- _bbox = Bbox.union([b for b in bb if b and (b.width!=0 or b.height!=0)])
-
- return _bbox
-
-
-
-
-Subplot = maxes.subplot_class_factory(Axes)
-
-class AxesZero(Axes):
- def __init__(self, *kl, **kw):
-
- super(AxesZero, self).__init__(*kl, **kw)
-
-
- def _init_axis_artists(self):
- super(AxesZero, self)._init_axis_artists()
-
- new_floating_axis = self._grid_helper.new_floating_axis
- xaxis_zero = new_floating_axis(nth_coord=0,
- value=0.,
- axis_direction="bottom",
- axes=self)
-
- xaxis_zero.line.set_clip_path(self.patch)
- xaxis_zero.set_visible(False)
- self._axislines["xzero"] = xaxis_zero
-
- yaxis_zero = new_floating_axis(nth_coord=1,
- value=0.,
- axis_direction="left",
- axes=self)
-
-
- yaxis_zero.line.set_clip_path(self.patch)
- yaxis_zero.set_visible(False)
- self._axislines["yzero"] = yaxis_zero
-
-SubplotZero = maxes.subplot_class_factory(AxesZero)
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/clip_path.py b/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/clip_path.py
deleted file mode 100644
index 8507b09b075..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/clip_path.py
+++ /dev/null
@@ -1,135 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-from six.moves import zip
-
-import numpy as np
-from math import degrees
-import math
-import warnings
-
-def atan2(dy, dx):
- if dx == 0 and dy == 0:
- warnings.warn("dx and dy is 0")
- return 0
- else:
- return math.atan2(dy, dx)
-
-# FIXME : The current algorithm seems to return incorrect angle when the line
-# ends at the boundary.
-
-def clip(xlines, ylines, x0, clip="right", xdir=True, ydir=True):
-
- clipped_xlines = []
- clipped_ylines = []
-
- _pos_angles = []
-
- if xdir:
- xsign = 1
- else:
- xsign = -1
-
- if ydir:
- ysign = 1
- else:
- ysign = -1
-
-
- for x, y in zip(xlines, ylines):
-
- if clip in ["up", "right"]:
- b = (x < x0).astype("i")
- db = b[1:] - b[:-1]
- else:
- b = (x > x0).astype("i")
- db = b[1:] - b[:-1]
-
-
- if b[0]:
- ns = 0
- else:
- ns = -1
- segx, segy = [], []
- for (i,) in np.argwhere(db!=0):
- c = db[i]
- if c == -1:
- dx = (x0 - x[i])
- dy = (y[i+1] - y[i]) * (dx/ (x[i+1] - x[i]))
- y0 = y[i] + dy
- clipped_xlines.append(np.concatenate([segx, x[ns:i+1], [x0]]))
- clipped_ylines.append(np.concatenate([segy, y[ns:i+1], [y0]]))
- ns = -1
- segx, segy = [], []
-
- if dx == 0. and dy == 0:
- dx = x[i+1] - x[i]
- dy = y[i+1] - y[i]
-
- a = degrees(atan2(ysign*dy, xsign*dx))
- _pos_angles.append((x0, y0, a))
-
- elif c == 1:
- dx = (x0 - x[i])
- dy = (y[i+1] - y[i]) * (dx / (x[i+1] - x[i]))
- y0 = y[i] + dy
- segx, segy = [x0], [y0]
- ns = i+1
-
- if dx == 0. and dy == 0:
- dx = x[i+1] - x[i]
- dy = y[i+1] - y[i]
-
- a = degrees(atan2(ysign*dy, xsign*dx))
- _pos_angles.append((x0, y0, a))
-
- if ns != -1:
- clipped_xlines.append(np.concatenate([segx, x[ns:]]))
- clipped_ylines.append(np.concatenate([segy, y[ns:]]))
-
- #clipped_pos_angles.append(_pos_angles)
-
-
- return clipped_xlines, clipped_ylines, _pos_angles
-
-
-def clip_line_to_rect(xline, yline, bbox):
-
- x0, y0, x1, y1 = bbox.extents
-
- xdir = x1 > x0
- ydir = y1 > y0
-
- if x1 > x0:
- lx1, ly1, c_right_ = clip([xline], [yline], x1, clip="right", xdir=xdir, ydir=ydir)
- lx2, ly2, c_left_ = clip(lx1, ly1, x0, clip="left", xdir=xdir, ydir=ydir)
- else:
- lx1, ly1, c_right_ = clip([xline], [yline], x0, clip="right", xdir=xdir, ydir=ydir)
- lx2, ly2, c_left_ = clip(lx1, ly1, x1, clip="left", xdir=xdir, ydir=ydir)
-
- if y1 > y0:
- ly3, lx3, c_top_ = clip(ly2, lx2, y1, clip="right", xdir=ydir, ydir=xdir)
- ly4, lx4, c_bottom_ = clip(ly3, lx3, y0, clip="left", xdir=ydir, ydir=xdir)
- else:
- ly3, lx3, c_top_ = clip(ly2, lx2, y0, clip="right", xdir=ydir, ydir=xdir)
- ly4, lx4, c_bottom_ = clip(ly3, lx3, y1, clip="left", xdir=ydir, ydir=xdir)
-
-
- # lx1, ly1, c_right_ = clip([xline], [yline], x1, clip="right")
- # lx2, ly2, c_left_ = clip(lx1, ly1, x0, clip="left")
- # ly3, lx3, c_top_ = clip(ly2, lx2, y1, clip="right")
- # ly4, lx4, c_bottom_ = clip(ly3, lx3, y0, clip="left")
-
- #c_left = [((x, y), (a+90)%180-180) for (x, y, a) in c_left_ \
- # if bbox.containsy(y)]
- c_left = [((x, y), (a+90)%180-90) for (x, y, a) in c_left_
- if bbox.containsy(y)]
- c_bottom = [((x, y), (90 - a)%180) for (y, x, a) in c_bottom_
- if bbox.containsx(x)]
- c_right = [((x, y), (a+90)%180+90) for (x, y, a) in c_right_
- if bbox.containsy(y)]
- c_top = [((x, y), (90 - a)%180+180) for (y, x, a) in c_top_
- if bbox.containsx(x)]
-
- return list(zip(lx4, ly4)), [c_left, c_bottom, c_right, c_top]
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/floating_axes.py b/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/floating_axes.py
deleted file mode 100644
index 468413dbac4..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/floating_axes.py
+++ /dev/null
@@ -1,544 +0,0 @@
-"""
-An experimental support for curvilinear grid.
-"""
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-from six.moves import zip
-
-# TODO :
-# see if tick_iterator method can be simplified by reusing the parent method.
-
-import numpy as np
-
-from matplotlib.transforms import Affine2D, IdentityTransform
-from . import grid_helper_curvelinear
-from .axislines import AxisArtistHelper, GridHelperBase
-from .axis_artist import AxisArtist
-from .grid_finder import GridFinder
-
-
-class FloatingAxisArtistHelper(grid_helper_curvelinear.FloatingAxisArtistHelper):
- pass
-
-
-class FixedAxisArtistHelper(grid_helper_curvelinear.FloatingAxisArtistHelper):
-
- def __init__(self, grid_helper, side, nth_coord_ticks=None):
- """
- nth_coord = along which coordinate value varies.
- nth_coord = 0 -> x axis, nth_coord = 1 -> y axis
- """
-
- value, nth_coord = grid_helper.get_data_boundary(side) # return v= 0 , nth=1, extremes of the other coordinate.
- super(FixedAxisArtistHelper, self).__init__(grid_helper,
- nth_coord,
- value,
- axis_direction=side,
- )
- #self.grid_helper = grid_helper
- if nth_coord_ticks is None:
- nth_coord_ticks = nth_coord
- self.nth_coord_ticks = nth_coord_ticks
-
- self.value = value
- self.grid_helper = grid_helper
- self._side = side
-
-
- def update_lim(self, axes):
- self.grid_helper.update_lim(axes)
-
- self.grid_info = self.grid_helper.grid_info
-
-
-
- def get_axislabel_pos_angle(self, axes):
-
- extremes = self.grid_info["extremes"]
-
- if self.nth_coord == 0:
- xx0 = self.value
- yy0 = (extremes[2]+extremes[3])/2.
- dxx, dyy = 0., abs(extremes[2]-extremes[3])/1000.
- elif self.nth_coord == 1:
- xx0 = (extremes[0]+extremes[1])/2.
- yy0 = self.value
- dxx, dyy = abs(extremes[0]-extremes[1])/1000., 0.
-
- grid_finder = self.grid_helper.grid_finder
- xx1, yy1 = grid_finder.transform_xy([xx0], [yy0])
-
- trans_passingthrough_point = axes.transData + axes.transAxes.inverted()
- p = trans_passingthrough_point.transform_point([xx1[0], yy1[0]])
-
-
- if (0. <= p[0] <= 1.) and (0. <= p[1] <= 1.):
- xx1c, yy1c = axes.transData.transform_point([xx1[0], yy1[0]])
- xx2, yy2 = grid_finder.transform_xy([xx0+dxx], [yy0+dyy])
- xx2c, yy2c = axes.transData.transform_point([xx2[0], yy2[0]])
-
- return (xx1c, yy1c), np.arctan2(yy2c-yy1c, xx2c-xx1c)/np.pi*180.
- else:
- return None, None
-
-
-
- def get_tick_transform(self, axes):
- return IdentityTransform() #axes.transData
-
- def get_tick_iterators(self, axes):
- """tick_loc, tick_angle, tick_label, (optionally) tick_label"""
-
-
- grid_finder = self.grid_helper.grid_finder
-
- lat_levs, lat_n, lat_factor = self.grid_info["lat_info"]
- lon_levs, lon_n, lon_factor = self.grid_info["lon_info"]
-
- lon_levs, lat_levs = np.asarray(lon_levs), np.asarray(lat_levs)
- if lat_factor is not None:
- yy0 = lat_levs / lat_factor
- dy = 0.001 / lat_factor
- else:
- yy0 = lat_levs
- dy = 0.001
-
- if lon_factor is not None:
- xx0 = lon_levs / lon_factor
- dx = 0.001 / lon_factor
- else:
- xx0 = lon_levs
- dx = 0.001
-
- _extremes = self.grid_helper._extremes
- xmin, xmax = sorted(_extremes[:2])
- ymin, ymax = sorted(_extremes[2:])
- if self.nth_coord == 0:
- mask = (ymin <= yy0) & (yy0 <= ymax)
- yy0 = yy0[mask]
- elif self.nth_coord == 1:
- mask = (xmin <= xx0) & (xx0 <= xmax)
- xx0 = xx0[mask]
-
- def transform_xy(x, y):
- x1, y1 = grid_finder.transform_xy(x, y)
- x2y2 = axes.transData.transform(np.array([x1, y1]).transpose())
- x2, y2 = x2y2.transpose()
- return x2, y2
-
- # find angles
- if self.nth_coord == 0:
- xx0 = np.empty_like(yy0)
- xx0.fill(self.value)
-
- #yy0_ = yy0.copy()
-
- xx1, yy1 = transform_xy(xx0, yy0)
-
- xx00 = xx0.astype(float, copy=True)
- xx00[xx0+dx>xmax] -= dx
- xx1a, yy1a = transform_xy(xx00, yy0)
- xx1b, yy1b = transform_xy(xx00+dx, yy0)
-
- yy00 = yy0.astype(float, copy=True)
- yy00[yy0+dy>ymax] -= dy
- xx2a, yy2a = transform_xy(xx0, yy00)
- xx2b, yy2b = transform_xy(xx0, yy00+dy)
-
- labels = self.grid_info["lat_labels"]
- labels = [l for l, m in zip(labels, mask) if m]
-
- elif self.nth_coord == 1:
- yy0 = np.empty_like(xx0)
- yy0.fill(self.value)
-
- #xx0_ = xx0.copy()
- xx1, yy1 = transform_xy(xx0, yy0)
-
-
- yy00 = yy0.astype(float, copy=True)
- yy00[yy0+dy>ymax] -= dy
- xx1a, yy1a = transform_xy(xx0, yy00)
- xx1b, yy1b = transform_xy(xx0, yy00+dy)
-
- xx00 = xx0.astype(float, copy=True)
- xx00[xx0+dx>xmax] -= dx
- xx2a, yy2a = transform_xy(xx00, yy0)
- xx2b, yy2b = transform_xy(xx00+dx, yy0)
-
- labels = self.grid_info["lon_labels"]
- labels = [l for l, m in zip(labels, mask) if m]
-
-
- def f1():
- dd = np.arctan2(yy1b-yy1a, xx1b-xx1a) # angle normal
- dd2 = np.arctan2(yy2b-yy2a, xx2b-xx2a) # angle tangent
- mm = ((yy1b-yy1a)==0.) & ((xx1b-xx1a)==0.) # mask where dd1 is not defined
- dd[mm] = dd2[mm] + np.pi / 2
-
- #dd += np.pi
- #dd = np.arctan2(xx2-xx1, angle_tangent-yy1)
- trans_tick = self.get_tick_transform(axes)
- tr2ax = trans_tick + axes.transAxes.inverted()
- for x, y, d, d2, lab in zip(xx1, yy1, dd, dd2, labels):
- c2 = tr2ax.transform_point((x, y))
- delta=0.00001
- if (0. -delta<= c2[0] <= 1.+delta) and \
- (0. -delta<= c2[1] <= 1.+delta):
- d1 = d/3.14159*180.
- d2 = d2/3.14159*180.
- #_mod = (d2-d1+180)%360
- #if _mod < 180:
- # d1 += 180
- ##_div, _mod = divmod(d2-d1, 360)
- yield [x, y], d1, d2, lab
- #, d2/3.14159*180.+da)
-
- return f1(), iter([])
-
- def get_line_transform(self, axes):
- return axes.transData
-
- def get_line(self, axes):
-
- self.update_lim(axes)
- from matplotlib.path import Path
- k, v = dict(left=("lon_lines0", 0),
- right=("lon_lines0", 1),
- bottom=("lat_lines0", 0),
- top=("lat_lines0", 1))[self._side]
-
- xx, yy = self.grid_info[k][v]
- return Path(np.column_stack([xx, yy]))
-
-
-
-from .grid_finder import ExtremeFinderSimple
-
-class ExtremeFinderFixed(ExtremeFinderSimple):
- def __init__(self, extremes):
- self._extremes = extremes
-
- def __call__(self, transform_xy, x1, y1, x2, y2):
- """
- get extreme values.
-
- x1, y1, x2, y2 in image coordinates (0-based)
- nx, ny : number of division in each axis
- """
- #lon_min, lon_max, lat_min, lat_max = self._extremes
- return self._extremes
-
-
-
-class GridHelperCurveLinear(grid_helper_curvelinear.GridHelperCurveLinear):
-
- def __init__(self, aux_trans, extremes,
- grid_locator1=None,
- grid_locator2=None,
- tick_formatter1=None,
- tick_formatter2=None):
- """
- aux_trans : a transform from the source (curved) coordinate to
- target (rectilinear) coordinate. An instance of MPL's Transform
- (inverse transform should be defined) or a tuple of two callable
- objects which defines the transform and its inverse. The callables
- need take two arguments of array of source coordinates and
- should return two target coordinates:
- e.g., *x2, y2 = trans(x1, y1)*
- """
-
- self._old_values = None
-
- self._extremes = extremes
- extreme_finder = ExtremeFinderFixed(extremes)
-
- super(GridHelperCurveLinear, self).__init__(aux_trans,
- extreme_finder,
- grid_locator1=grid_locator1,
- grid_locator2=grid_locator2,
- tick_formatter1=tick_formatter1,
- tick_formatter2=tick_formatter2)
-
-
- # def update_grid_finder(self, aux_trans=None, **kw):
-
- # if aux_trans is not None:
- # self.grid_finder.update_transform(aux_trans)
-
- # self.grid_finder.update(**kw)
- # self.invalidate()
-
-
- # def _update(self, x1, x2, y1, y2):
- # "bbox in 0-based image coordinates"
- # # update wcsgrid
-
- # if self.valid() and self._old_values == (x1, x2, y1, y2):
- # return
-
- # self._update_grid(x1, y1, x2, y2)
-
- # self._old_values = (x1, x2, y1, y2)
-
- # self._force_update = False
-
-
- def get_data_boundary(self, side):
- """
- return v= 0 , nth=1
- """
- lon1, lon2, lat1, lat2 = self._extremes
- return dict(left=(lon1, 0),
- right=(lon2, 0),
- bottom=(lat1, 1),
- top=(lat2, 1))[side]
-
-
- def new_fixed_axis(self, loc,
- nth_coord=None,
- axis_direction=None,
- offset=None,
- axes=None):
-
- if axes is None:
- axes = self.axes
-
- if axis_direction is None:
- axis_direction = loc
-
- _helper = FixedAxisArtistHelper(self, loc,
- nth_coord_ticks=nth_coord)
-
-
- axisline = AxisArtist(axes, _helper, axis_direction=axis_direction)
- axisline.line.set_clip_on(True)
- axisline.line.set_clip_box(axisline.axes.bbox)
-
-
- return axisline
-
-
- # new_floating_axis will inherit the grid_helper's extremes.
-
- # def new_floating_axis(self, nth_coord,
- # value,
- # axes=None,
- # axis_direction="bottom"
- # ):
-
- # axis = super(GridHelperCurveLinear,
- # self).new_floating_axis(nth_coord,
- # value, axes=axes,
- # axis_direction=axis_direction)
-
- # # set extreme values of the axis helper
- # if nth_coord == 1:
- # axis.get_helper().set_extremes(*self._extremes[:2])
- # elif nth_coord == 0:
- # axis.get_helper().set_extremes(*self._extremes[2:])
-
- # return axis
-
-
- def _update_grid(self, x1, y1, x2, y2):
-
- #self.grid_info = self.grid_finder.get_grid_info(x1, y1, x2, y2)
-
- if self.grid_info is None:
- self.grid_info = dict()
-
- grid_info = self.grid_info
-
- grid_finder = self.grid_finder
- extremes = grid_finder.extreme_finder(grid_finder.inv_transform_xy,
- x1, y1, x2, y2)
-
- lon_min, lon_max = sorted(extremes[:2])
- lat_min, lat_max = sorted(extremes[2:])
- lon_levs, lon_n, lon_factor = \
- grid_finder.grid_locator1(lon_min, lon_max)
- lat_levs, lat_n, lat_factor = \
- grid_finder.grid_locator2(lat_min, lat_max)
- grid_info["extremes"] = lon_min, lon_max, lat_min, lat_max #extremes
-
- grid_info["lon_info"] = lon_levs, lon_n, lon_factor
- grid_info["lat_info"] = lat_levs, lat_n, lat_factor
-
- grid_info["lon_labels"] = grid_finder.tick_formatter1("bottom",
- lon_factor,
- lon_levs)
-
- grid_info["lat_labels"] = grid_finder.tick_formatter2("bottom",
- lat_factor,
- lat_levs)
-
- if lon_factor is None:
- lon_values = np.asarray(lon_levs[:lon_n])
- else:
- lon_values = np.asarray(lon_levs[:lon_n]/lon_factor)
- if lat_factor is None:
- lat_values = np.asarray(lat_levs[:lat_n])
- else:
- lat_values = np.asarray(lat_levs[:lat_n]/lat_factor)
-
- lon_values0 = lon_values[(lon_min<lon_values) & (lon_values<lon_max)]
- lat_values0 = lat_values[(lat_min<lat_values) & (lat_values<lat_max)]
- lon_lines, lat_lines = grid_finder._get_raw_grid_lines(lon_values0,
- lat_values0,
- lon_min, lon_max,
- lat_min, lat_max)
-
-
- grid_info["lon_lines"] = lon_lines
- grid_info["lat_lines"] = lat_lines
-
-
- lon_lines, lat_lines = grid_finder._get_raw_grid_lines(extremes[:2],
- extremes[2:],
- *extremes)
- #lon_min, lon_max,
- # lat_min, lat_max)
-
-
- grid_info["lon_lines0"] = lon_lines
- grid_info["lat_lines0"] = lat_lines
-
-
-
- def get_gridlines(self, which="major", axis="both"):
- grid_lines = []
- if axis in ["both", "x"]:
- for gl in self.grid_info["lon_lines"]:
- grid_lines.extend([gl])
- if axis in ["both", "y"]:
- for gl in self.grid_info["lat_lines"]:
- grid_lines.extend([gl])
-
- return grid_lines
-
-
- def get_boundary(self):
- """
- return Nx2 array of x,y coordinate of the boundary
- """
- x0, x1, y0, y1 = self._extremes
- tr = self._aux_trans
- xx = np.linspace(x0, x1, 100)
- yy0, yy1 = np.empty_like(xx), np.empty_like(xx)
- yy0.fill(y0)
- yy1.fill(y1)
-
- yy = np.linspace(y0, y1, 100)
- xx0, xx1 = np.empty_like(yy), np.empty_like(yy)
- xx0.fill(x0)
- xx1.fill(x1)
-
- xxx = np.concatenate([xx[:-1], xx1[:-1], xx[-1:0:-1], xx0])
- yyy = np.concatenate([yy0[:-1], yy[:-1], yy1[:-1], yy[::-1]])
- t = tr.transform(np.array([xxx, yyy]).transpose())
-
- return t
-
-
-
-
-
-
-
-
-
-
-
-
-class FloatingAxesBase(object):
-
-
- def __init__(self, *kl, **kwargs):
- grid_helper = kwargs.get("grid_helper", None)
- if grid_helper is None:
- raise ValueError("FloatingAxes requires grid_helper argument")
- if not hasattr(grid_helper, "get_boundary"):
- raise ValueError("grid_helper must implement get_boundary method")
-
- self._axes_class_floating.__init__(self, *kl, **kwargs)
-
- self.set_aspect(1.)
- self.adjust_axes_lim()
-
-
- def _gen_axes_patch(self):
- """
- Returns the patch used to draw the background of the axes. It
- is also used as the clipping path for any data elements on the
- axes.
-
- In the standard axes, this is a rectangle, but in other
- projections it may not be.
-
- .. note::
- Intended to be overridden by new projection types.
- """
- import matplotlib.patches as mpatches
- grid_helper = self.get_grid_helper()
- t = grid_helper.get_boundary()
- return mpatches.Polygon(t)
-
- def cla(self):
- self._axes_class_floating.cla(self)
- #HostAxes.cla(self)
- self.patch.set_transform(self.transData)
-
-
- patch = self._axes_class_floating._gen_axes_patch(self)
- patch.set_figure(self.figure)
- patch.set_visible(False)
- patch.set_transform(self.transAxes)
-
- self.patch.set_clip_path(patch)
- self.gridlines.set_clip_path(patch)
-
- self._original_patch = patch
-
-
- def adjust_axes_lim(self):
-
- #t = self.get_boundary()
- grid_helper = self.get_grid_helper()
- t = grid_helper.get_boundary()
- x, y = t[:,0], t[:,1]
-
- xmin, xmax = min(x), max(x)
- ymin, ymax = min(y), max(y)
-
- dx = (xmax-xmin)/100.
- dy = (ymax-ymin)/100.
-
- self.set_xlim(xmin-dx, xmax+dx)
- self.set_ylim(ymin-dy, ymax+dy)
-
-
-
-_floatingaxes_classes = {}
-
-def floatingaxes_class_factory(axes_class):
-
- new_class = _floatingaxes_classes.get(axes_class)
- if new_class is None:
- new_class = type(str("Floating %s" % (axes_class.__name__)),
- (FloatingAxesBase, axes_class),
- {'_axes_class_floating': axes_class})
- _floatingaxes_classes[axes_class] = new_class
-
- return new_class
-
-from .axislines import Axes
-from mpl_toolkits.axes_grid1.parasite_axes import host_axes_class_factory
-
-FloatingAxes = floatingaxes_class_factory(host_axes_class_factory(Axes))
-
-
-import matplotlib.axes as maxes
-FloatingSubplot = maxes.subplot_class_factory(FloatingAxes)
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/grid_finder.py b/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/grid_finder.py
deleted file mode 100644
index 62a94b14783..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/grid_finder.py
+++ /dev/null
@@ -1,340 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-
-import numpy as np
-from matplotlib.transforms import Bbox
-from . import clip_path
-clip_line_to_rect = clip_path.clip_line_to_rect
-
-import matplotlib.ticker as mticker
-from matplotlib.transforms import Transform
-
-# extremes finder
-
-class ExtremeFinderSimple(object):
- def __init__(self, nx, ny):
- self.nx, self.ny = nx, ny
-
- def __call__(self, transform_xy, x1, y1, x2, y2):
- """
- get extreme values.
-
- x1, y1, x2, y2 in image coordinates (0-based)
- nx, ny : number of division in each axis
- """
- x_, y_ = np.linspace(x1, x2, self.nx), np.linspace(y1, y2, self.ny)
- x, y = np.meshgrid(x_, y_)
- lon, lat = transform_xy(np.ravel(x), np.ravel(y))
-
- lon_min, lon_max = lon.min(), lon.max()
- lat_min, lat_max = lat.min(), lat.max()
-
- return self._add_pad(lon_min, lon_max, lat_min, lat_max)
-
- def _add_pad(self, lon_min, lon_max, lat_min, lat_max):
- """ a small amount of padding is added because the current
- clipping algorithms seems to fail when the gridline ends at
- the bbox boundary.
- """
- dlon = (lon_max - lon_min) / self.nx
- dlat = (lat_max - lat_min) / self.ny
-
- lon_min, lon_max = lon_min - dlon, lon_max + dlon
- lat_min, lat_max = lat_min - dlat, lat_max + dlat
-
- return lon_min, lon_max, lat_min, lat_max
-
-
-
-class GridFinderBase(object):
- def __init__(self,
- extreme_finder,
- grid_locator1,
- grid_locator2,
- tick_formatter1=None,
- tick_formatter2=None):
- """
- the transData of the axes to the world coordinate.
- locator1, locator2 : grid locator for 1st and 2nd axis.
-
- Derived must define "transform_xy, inv_transform_xy"
- (may use update_transform)
- """
- super(GridFinderBase, self).__init__()
-
- self.extreme_finder = extreme_finder
- self.grid_locator1 = grid_locator1
- self.grid_locator2 = grid_locator2
- self.tick_formatter1 = tick_formatter1
- self.tick_formatter2 = tick_formatter2
-
- def get_grid_info(self,
- x1, y1, x2, y2):
- """
- lon_values, lat_values : list of grid values. if integer is given,
- rough number of grids in each direction.
- """
-
- extremes = self.extreme_finder(self.inv_transform_xy, x1, y1, x2, y2)
-
- # min & max rage of lat (or lon) for each grid line will be drawn.
- # i.e., gridline of lon=0 will be drawn from lat_min to lat_max.
-
- lon_min, lon_max, lat_min, lat_max = extremes
- lon_levs, lon_n, lon_factor = \
- self.grid_locator1(lon_min, lon_max)
- lat_levs, lat_n, lat_factor = \
- self.grid_locator2(lat_min, lat_max)
-
- if lon_factor is None:
- lon_values = np.asarray(lon_levs[:lon_n])
- else:
- lon_values = np.asarray(lon_levs[:lon_n]/lon_factor)
- if lat_factor is None:
- lat_values = np.asarray(lat_levs[:lat_n])
- else:
- lat_values = np.asarray(lat_levs[:lat_n]/lat_factor)
-
-
- lon_lines, lat_lines = self._get_raw_grid_lines(lon_values,
- lat_values,
- lon_min, lon_max,
- lat_min, lat_max)
-
- ddx = (x2-x1)*1.e-10
- ddy = (y2-y1)*1.e-10
- bb = Bbox.from_extents(x1-ddx, y1-ddy, x2+ddx, y2+ddy)
-
- grid_info = {}
- grid_info["extremes"] = extremes
- grid_info["lon_lines"] = lon_lines
- grid_info["lat_lines"] = lat_lines
-
- grid_info["lon"] = self._clip_grid_lines_and_find_ticks(lon_lines,
- lon_values,
- lon_levs,
- bb)
-
- grid_info["lat"] = self._clip_grid_lines_and_find_ticks(lat_lines,
- lat_values,
- lat_levs,
- bb)
-
- tck_labels = grid_info["lon"]["tick_labels"] = dict()
- for direction in ["left", "bottom", "right", "top"]:
- levs = grid_info["lon"]["tick_levels"][direction]
- tck_labels[direction] = self.tick_formatter1(direction,
- lon_factor, levs)
-
- tck_labels = grid_info["lat"]["tick_labels"] = dict()
- for direction in ["left", "bottom", "right", "top"]:
- levs = grid_info["lat"]["tick_levels"][direction]
- tck_labels[direction] = self.tick_formatter2(direction,
- lat_factor, levs)
-
- return grid_info
-
-
- def _get_raw_grid_lines(self,
- lon_values, lat_values,
- lon_min, lon_max, lat_min, lat_max):
-
- lons_i = np.linspace(lon_min, lon_max, 100) # for interpolation
- lats_i = np.linspace(lat_min, lat_max, 100)
-
- lon_lines = [self.transform_xy(np.zeros_like(lats_i) + lon, lats_i)
- for lon in lon_values]
- lat_lines = [self.transform_xy(lons_i, np.zeros_like(lons_i) + lat)
- for lat in lat_values]
-
- return lon_lines, lat_lines
-
-
- def _clip_grid_lines_and_find_ticks(self, lines, values, levs, bb):
- gi = dict()
- gi["values"] = []
- gi["levels"] = []
- gi["tick_levels"] = dict(left=[], bottom=[], right=[], top=[])
- gi["tick_locs"] = dict(left=[], bottom=[], right=[], top=[])
- gi["lines"] = []
-
- tck_levels = gi["tick_levels"]
- tck_locs = gi["tick_locs"]
- for (lx, ly), v, lev in zip(lines, values, levs):
- xy, tcks = clip_line_to_rect(lx, ly, bb)
- if not xy:
- continue
- gi["levels"].append(v)
- gi["lines"].append(xy)
-
- for tck, direction in zip(tcks,
- ["left", "bottom", "right", "top"]):
- for t in tck:
- tck_levels[direction].append(lev)
- tck_locs[direction].append(t)
-
- return gi
-
-
- def update_transform(self, aux_trans):
- if isinstance(aux_trans, Transform):
- def transform_xy(x, y):
- x, y = np.asarray(x), np.asarray(y)
- ll1 = np.concatenate((x[:,np.newaxis], y[:,np.newaxis]), 1)
- ll2 = aux_trans.transform(ll1)
- lon, lat = ll2[:,0], ll2[:,1]
- return lon, lat
-
- def inv_transform_xy(x, y):
- x, y = np.asarray(x), np.asarray(y)
- ll1 = np.concatenate((x[:,np.newaxis], y[:,np.newaxis]), 1)
- ll2 = aux_trans.inverted().transform(ll1)
- lon, lat = ll2[:,0], ll2[:,1]
- return lon, lat
-
- else:
- transform_xy, inv_transform_xy = aux_trans
-
- self.transform_xy = transform_xy
- self.inv_transform_xy = inv_transform_xy
-
-
- def update(self, **kw):
- for k in kw:
- if k in ["extreme_finder",
- "grid_locator1",
- "grid_locator2",
- "tick_formatter1",
- "tick_formatter2"]:
- setattr(self, k, kw[k])
- else:
- raise ValueError("unknown update property '%s'" % k)
-
-
-class GridFinder(GridFinderBase):
-
- def __init__(self,
- transform,
- extreme_finder=None,
- grid_locator1=None,
- grid_locator2=None,
- tick_formatter1=None,
- tick_formatter2=None):
- """
- transform : transform from the image coordinate (which will be
- the transData of the axes to the world coordinate.
-
- or transform = (transform_xy, inv_transform_xy)
-
- locator1, locator2 : grid locator for 1st and 2nd axis.
- """
- if extreme_finder is None:
- extreme_finder = ExtremeFinderSimple(20, 20)
- if grid_locator1 is None:
- grid_locator1 = MaxNLocator()
- if grid_locator2 is None:
- grid_locator2 = MaxNLocator()
- if tick_formatter1 is None:
- tick_formatter1 = FormatterPrettyPrint()
- if tick_formatter2 is None:
- tick_formatter2 = FormatterPrettyPrint()
- super(GridFinder, self).__init__(
- extreme_finder,
- grid_locator1,
- grid_locator2,
- tick_formatter1,
- tick_formatter2)
- self.update_transform(transform)
-
-
-class MaxNLocator(mticker.MaxNLocator):
- def __init__(self, nbins=10, steps=None,
- trim=True,
- integer=False,
- symmetric=False,
- prune=None):
- # trim argument has no effect. It has been left for API compatibility
- mticker.MaxNLocator.__init__(self, nbins, steps=steps,
- integer=integer,
- symmetric=symmetric, prune=prune)
- self.create_dummy_axis()
- self._factor = None
-
- def __call__(self, v1, v2):
- if self._factor is not None:
- self.set_bounds(v1*self._factor, v2*self._factor)
- locs = mticker.MaxNLocator.__call__(self)
- return np.array(locs), len(locs), self._factor
- else:
- self.set_bounds(v1, v2)
- locs = mticker.MaxNLocator.__call__(self)
- return np.array(locs), len(locs), None
-
- def set_factor(self, f):
- self._factor = f
-
-
-class FixedLocator(object):
- def __init__(self, locs):
- self._locs = locs
- self._factor = None
-
-
- def __call__(self, v1, v2):
- if self._factor is None:
- v1, v2 = sorted([v1, v2])
- else:
- v1, v2 = sorted([v1*self._factor, v2*self._factor])
- locs = np.array([l for l in self._locs if ((v1 <= l) and (l <= v2))])
- return locs, len(locs), self._factor
-
- def set_factor(self, f):
- self._factor = f
-
-
-
-# Tick Formatter
-
-class FormatterPrettyPrint(object):
- def __init__(self, useMathText=True):
- self._fmt = mticker.ScalarFormatter(
- useMathText=useMathText, useOffset=False)
- self._fmt.create_dummy_axis()
- self._ignore_factor = True
-
- def __call__(self, direction, factor, values):
- if not self._ignore_factor:
- if factor is None:
- factor = 1.
- values = [v/factor for v in values]
- #values = [v for v in values]
- self._fmt.set_locs(values)
- return [self._fmt(v) for v in values]
-
-
-class DictFormatter(object):
- def __init__(self, format_dict, formatter=None):
- """
- format_dict : dictionary for format strings to be used.
- formatter : fall-back formatter
- """
- super(DictFormatter, self).__init__()
- self._format_dict = format_dict
- self._fallback_formatter = formatter
-
- def __call__(self, direction, factor, values):
- """
- factor is ignored if value is found in the dictionary
- """
-
- if self._fallback_formatter:
- fallback_strings = self._fallback_formatter(
- direction, factor, values)
- else:
- fallback_strings = [""]*len(values)
-
- r = [self._format_dict.get(k, v) for k, v in zip(values,
- fallback_strings)]
- return r
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/grid_helper_curvelinear.py b/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/grid_helper_curvelinear.py
deleted file mode 100644
index 578645148ee..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/grid_helper_curvelinear.py
+++ /dev/null
@@ -1,475 +0,0 @@
-"""
-An experimental support for curvilinear grid.
-"""
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-from six.moves import zip
-
-from itertools import chain
-from .grid_finder import GridFinder
-
-from .axislines import AxisArtistHelper, GridHelperBase
-from .axis_artist import AxisArtist
-from matplotlib.transforms import Affine2D, IdentityTransform
-import numpy as np
-
-from matplotlib.path import Path
-
-class FixedAxisArtistHelper(AxisArtistHelper.Fixed):
- """
- Helper class for a fixed axis.
- """
-
- def __init__(self, grid_helper, side, nth_coord_ticks=None):
- """
- nth_coord = along which coordinate value varies.
- nth_coord = 0 -> x axis, nth_coord = 1 -> y axis
- """
-
- super(FixedAxisArtistHelper, self).__init__(loc=side)
-
- self.grid_helper = grid_helper
- if nth_coord_ticks is None:
- nth_coord_ticks = self.nth_coord
- self.nth_coord_ticks = nth_coord_ticks
-
- self.side = side
- self._limits_inverted = False
-
- def update_lim(self, axes):
- self.grid_helper.update_lim(axes)
-
- if self.nth_coord == 0:
- xy1, xy2 = axes.get_ylim()
- else:
- xy1, xy2 = axes.get_xlim()
-
- if xy1 > xy2:
- self._limits_inverted = True
- else:
- self._limits_inverted = False
-
-
- def change_tick_coord(self, coord_number=None):
- if coord_number is None:
- self.nth_coord_ticks = 1 - self.nth_coord_ticks
- elif coord_number in [0, 1]:
- self.nth_coord_ticks = coord_number
- else:
- raise Exception("wrong coord number")
-
-
- def get_tick_transform(self, axes):
- return axes.transData
-
- def get_tick_iterators(self, axes):
- """tick_loc, tick_angle, tick_label"""
-
- g = self.grid_helper
-
- if self._limits_inverted:
- side = {"left":"right","right":"left",
- "top":"bottom", "bottom":"top"}[self.side]
- else:
- side = self.side
-
- ti1 = g.get_tick_iterator(self.nth_coord_ticks, side)
- ti2 = g.get_tick_iterator(1-self.nth_coord_ticks, side, minor=True)
-
- #ti2 = g.get_tick_iterator(1-self.nth_coord_ticks, self.side, minor=True)
-
- return chain(ti1, ti2), iter([])
-
-
-
-class FloatingAxisArtistHelper(AxisArtistHelper.Floating):
-
- def __init__(self, grid_helper, nth_coord, value, axis_direction=None):
- """
- nth_coord = along which coordinate value varies.
- nth_coord = 0 -> x axis, nth_coord = 1 -> y axis
- """
-
- super(FloatingAxisArtistHelper, self).__init__(nth_coord,
- value,
- )
- self.value = value
- self.grid_helper = grid_helper
- self._extremes = None, None
-
- self._get_line_path = None # a method that returns a Path.
- self._line_num_points = 100 # number of points to create a line
-
- def set_extremes(self, e1, e2):
- self._extremes = e1, e2
-
- def update_lim(self, axes):
- self.grid_helper.update_lim(axes)
-
- x1, x2 = axes.get_xlim()
- y1, y2 = axes.get_ylim()
- grid_finder = self.grid_helper.grid_finder
- extremes = grid_finder.extreme_finder(grid_finder.inv_transform_xy,
- x1, y1, x2, y2)
-
- extremes = list(extremes)
- e1, e2 = self._extremes # ranges of other coordinates
- if self.nth_coord == 0:
- if e1 is not None:
- extremes[2] = max(e1, extremes[2])
- if e2 is not None:
- extremes[3] = min(e2, extremes[3])
- elif self.nth_coord == 1:
- if e1 is not None:
- extremes[0] = max(e1, extremes[0])
- if e2 is not None:
- extremes[1] = min(e2, extremes[1])
-
- grid_info = dict()
- lon_min, lon_max, lat_min, lat_max = extremes
- lon_levs, lon_n, lon_factor = \
- grid_finder.grid_locator1(lon_min, lon_max)
- lat_levs, lat_n, lat_factor = \
- grid_finder.grid_locator2(lat_min, lat_max)
- grid_info["extremes"] = extremes
-
- grid_info["lon_info"] = lon_levs, lon_n, lon_factor
- grid_info["lat_info"] = lat_levs, lat_n, lat_factor
-
- grid_info["lon_labels"] = grid_finder.tick_formatter1("bottom",
- lon_factor,
- lon_levs)
-
- grid_info["lat_labels"] = grid_finder.tick_formatter2("bottom",
- lat_factor,
- lat_levs)
-
- grid_finder = self.grid_helper.grid_finder
-
- #e1, e2 = self._extremes # ranges of other coordinates
- if self.nth_coord == 0:
- xx0 = np.linspace(self.value, self.value, self._line_num_points)
- yy0 = np.linspace(extremes[2], extremes[3], self._line_num_points)
- xx, yy = grid_finder.transform_xy(xx0, yy0)
- elif self.nth_coord == 1:
- xx0 = np.linspace(extremes[0], extremes[1], self._line_num_points)
- yy0 = np.linspace(self.value, self.value, self._line_num_points)
- xx, yy = grid_finder.transform_xy(xx0, yy0)
-
- grid_info["line_xy"] = xx, yy
- self.grid_info = grid_info
-
- def get_axislabel_transform(self, axes):
- return Affine2D() #axes.transData
-
- def get_axislabel_pos_angle(self, axes):
-
- extremes = self.grid_info["extremes"]
-
- if self.nth_coord == 0:
- xx0 = self.value
- yy0 = (extremes[2]+extremes[3])/2.
- dxx, dyy = 0., abs(extremes[2]-extremes[3])/1000.
- elif self.nth_coord == 1:
- xx0 = (extremes[0]+extremes[1])/2.
- yy0 = self.value
- dxx, dyy = abs(extremes[0]-extremes[1])/1000., 0.
-
- grid_finder = self.grid_helper.grid_finder
- xx1, yy1 = grid_finder.transform_xy([xx0], [yy0])
-
- trans_passingthrough_point = axes.transData + axes.transAxes.inverted()
- p = trans_passingthrough_point.transform_point([xx1[0], yy1[0]])
-
-
- if (0. <= p[0] <= 1.) and (0. <= p[1] <= 1.):
- xx1c, yy1c = axes.transData.transform_point([xx1[0], yy1[0]])
- xx2, yy2 = grid_finder.transform_xy([xx0+dxx], [yy0+dyy])
- xx2c, yy2c = axes.transData.transform_point([xx2[0], yy2[0]])
-
- return (xx1c, yy1c), np.arctan2(yy2c-yy1c, xx2c-xx1c)/np.pi*180.
- else:
- return None, None
-
-
-
-
- def get_tick_transform(self, axes):
- return IdentityTransform() #axes.transData
-
- def get_tick_iterators(self, axes):
- """tick_loc, tick_angle, tick_label, (optionally) tick_label"""
-
- grid_finder = self.grid_helper.grid_finder
-
- lat_levs, lat_n, lat_factor = self.grid_info["lat_info"]
- lat_levs = np.asarray(lat_levs)
- if lat_factor is not None:
- yy0 = lat_levs / lat_factor
- dy = 0.01 / lat_factor
- else:
- yy0 = lat_levs
- dy = 0.01
-
- lon_levs, lon_n, lon_factor = self.grid_info["lon_info"]
- lon_levs = np.asarray(lon_levs)
- if lon_factor is not None:
- xx0 = lon_levs / lon_factor
- dx = 0.01 / lon_factor
- else:
- xx0 = lon_levs
- dx = 0.01
-
- if None in self._extremes:
- e0, e1 = self._extremes
- else:
- e0, e1 = sorted(self._extremes)
- if e0 is None:
- e0 = -np.inf
- if e1 is None:
- e1 = np.inf
-
- if self.nth_coord == 0:
- mask = (e0 <= yy0) & (yy0 <= e1)
- #xx0, yy0 = xx0[mask], yy0[mask]
- yy0 = yy0[mask]
- elif self.nth_coord == 1:
- mask = (e0 <= xx0) & (xx0 <= e1)
- #xx0, yy0 = xx0[mask], yy0[mask]
- xx0 = xx0[mask]
-
- def transform_xy(x, y):
- x1, y1 = grid_finder.transform_xy(x, y)
- x2y2 = axes.transData.transform(np.array([x1, y1]).transpose())
- x2, y2 = x2y2.transpose()
- return x2, y2
-
- # find angles
- if self.nth_coord == 0:
- xx0 = np.empty_like(yy0)
- xx0.fill(self.value)
-
- xx1, yy1 = transform_xy(xx0, yy0)
-
- xx00 = xx0.copy()
- xx00[xx0+dx>e1] -= dx
- xx1a, yy1a = transform_xy(xx00, yy0)
- xx1b, yy1b = transform_xy(xx00+dx, yy0)
-
- xx2a, yy2a = transform_xy(xx0, yy0)
- xx2b, yy2b = transform_xy(xx0, yy0+dy)
-
- labels = self.grid_info["lat_labels"]
- labels = [l for l, m in zip(labels, mask) if m]
-
- elif self.nth_coord == 1:
- yy0 = np.empty_like(xx0)
- yy0.fill(self.value)
-
- xx1, yy1 = transform_xy(xx0, yy0)
-
- xx1a, yy1a = transform_xy(xx0, yy0)
- xx1b, yy1b = transform_xy(xx0, yy0+dy)
-
- xx00 = xx0.copy()
- xx00[xx0+dx>e1] -= dx
- xx2a, yy2a = transform_xy(xx00, yy0)
- xx2b, yy2b = transform_xy(xx00+dx, yy0)
-
- labels = self.grid_info["lon_labels"]
- labels = [l for l, m in zip(labels, mask) if m]
-
-
- def f1():
- dd = np.arctan2(yy1b-yy1a, xx1b-xx1a) # angle normal
- dd2 = np.arctan2(yy2b-yy2a, xx2b-xx2a) # angle tangent
- mm = ((yy1b-yy1a)==0.) & ((xx1b-xx1a)==0.) # mask where dd1 is not defined
- dd[mm] = dd2[mm] + np.pi / 2
- #dd = np.arctan2(yy2-yy1, xx2-xx1) # angle normal
- #dd2 = np.arctan2(yy3-yy1, xx3-xx1) # angle tangent
- #mm = ((yy2-yy1)==0.) & ((xx2-xx1)==0.) # mask where dd1 is not defined
- #dd[mm] = dd2[mm] + np.pi / 2
-
- #dd += np.pi
-
- #dd = np.arctan2(xx2-xx1, angle_tangent-yy1)
- trans_tick = self.get_tick_transform(axes)
- tr2ax = trans_tick + axes.transAxes.inverted()
- for x, y, d, d2, lab in zip(xx1, yy1, dd, dd2, labels):
- c2 = tr2ax.transform_point((x, y))
- delta=0.00001
- if (0. -delta<= c2[0] <= 1.+delta) and \
- (0. -delta<= c2[1] <= 1.+delta):
- d1 = d/3.14159*180.
- d2 = d2/3.14159*180.
- yield [x, y], d1, d2, lab
-
- return f1(), iter([])
-
- def get_line_transform(self, axes):
- return axes.transData
-
- def get_line(self, axes):
- self.update_lim(axes)
- x, y = self.grid_info["line_xy"]
-
- if self._get_line_path is None:
- return Path(np.column_stack([x, y]))
- else:
- return self._get_line_path(axes, x, y)
-
-
-
-
-class GridHelperCurveLinear(GridHelperBase):
-
- def __init__(self, aux_trans,
- extreme_finder=None,
- grid_locator1=None,
- grid_locator2=None,
- tick_formatter1=None,
- tick_formatter2=None):
- """
- aux_trans : a transform from the source (curved) coordinate to
- target (rectilinear) coordinate. An instance of MPL's Transform
- (inverse transform should be defined) or a tuple of two callable
- objects which defines the transform and its inverse. The callables
- need take two arguments of array of source coordinates and
- should return two target coordinates.
-
- e.g., ``x2, y2 = trans(x1, y1)``
- """
- super(GridHelperCurveLinear, self).__init__()
-
- self.grid_info = None
- self._old_values = None
- #self._grid_params = dict()
- self._aux_trans = aux_trans
-
- self.grid_finder = GridFinder(aux_trans,
- extreme_finder,
- grid_locator1,
- grid_locator2,
- tick_formatter1,
- tick_formatter2)
-
-
- def update_grid_finder(self, aux_trans=None, **kw):
-
- if aux_trans is not None:
- self.grid_finder.update_transform(aux_trans)
-
- self.grid_finder.update(**kw)
- self.invalidate()
-
-
- def _update(self, x1, x2, y1, y2):
- "bbox in 0-based image coordinates"
- # update wcsgrid
-
- if self.valid() and self._old_values == (x1, x2, y1, y2):
- return
-
- self._update_grid(x1, y1, x2, y2)
-
- self._old_values = (x1, x2, y1, y2)
-
- self._force_update = False
-
-
- def new_fixed_axis(self, loc,
- nth_coord=None,
- axis_direction=None,
- offset=None,
- axes=None):
-
-
- if axes is None:
- axes = self.axes
-
- if axis_direction is None:
- axis_direction = loc
- _helper = FixedAxisArtistHelper(self, loc,
- #nth_coord,
- nth_coord_ticks=nth_coord,
- )
-
- axisline = AxisArtist(axes, _helper, axis_direction=axis_direction)
-
- return axisline
-
-
- def new_floating_axis(self, nth_coord,
- value,
- axes=None,
- axis_direction="bottom"
- ):
-
- if axes is None:
- axes = self.axes
-
- _helper = FloatingAxisArtistHelper(
- self, nth_coord, value, axis_direction)
-
- axisline = AxisArtist(axes, _helper)
-
- #_helper = FloatingAxisArtistHelper(self, nth_coord,
- # value,
- # label_direction=label_direction,
- # )
-
- #axisline = AxisArtistFloating(axes, _helper,
- # axis_direction=axis_direction)
- axisline.line.set_clip_on(True)
- axisline.line.set_clip_box(axisline.axes.bbox)
- #axisline.major_ticklabels.set_visible(True)
- #axisline.minor_ticklabels.set_visible(False)
-
- #axisline.major_ticklabels.set_rotate_along_line(True)
- #axisline.set_rotate_label_along_line(True)
-
- return axisline
-
-
- def _update_grid(self, x1, y1, x2, y2):
-
- self.grid_info = self.grid_finder.get_grid_info(x1, y1, x2, y2)
-
-
- def get_gridlines(self, which="major", axis="both"):
- grid_lines = []
-
- if axis in ["both", "x"]:
- for gl in self.grid_info["lon"]["lines"]:
- grid_lines.extend(gl)
- if axis in ["both", "y"]:
- for gl in self.grid_info["lat"]["lines"]:
- grid_lines.extend(gl)
-
- return grid_lines
-
-
- def get_tick_iterator(self, nth_coord, axis_side, minor=False):
-
- #axisnr = dict(left=0, bottom=1, right=2, top=3)[axis_side]
- angle_tangent = dict(left=90, right=90, bottom=0, top=0)[axis_side]
- #angle = [0, 90, 180, 270][axisnr]
- lon_or_lat = ["lon", "lat"][nth_coord]
- if not minor: # major ticks
- def f():
- for (xy, a), l in zip(self.grid_info[lon_or_lat]["tick_locs"][axis_side],
- self.grid_info[lon_or_lat]["tick_labels"][axis_side]):
- angle_normal = a
- yield xy, angle_normal, angle_tangent, l
- else:
- def f():
- for (xy, a), l in zip(self.grid_info[lon_or_lat]["tick_locs"][axis_side],
- self.grid_info[lon_or_lat]["tick_labels"][axis_side]):
- angle_normal = a
- yield xy, angle_normal, angle_tangent, ""
- #for xy, a, l in self.grid_info[lon_or_lat]["ticks"][axis_side]:
- # yield xy, a, ""
-
- return f()
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/parasite_axes.py b/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/parasite_axes.py
deleted file mode 100644
index cad56e43a22..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/axisartist/parasite_axes.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-from mpl_toolkits.axes_grid1.parasite_axes import (
- host_axes_class_factory, parasite_axes_class_factory,
- parasite_axes_auxtrans_class_factory, subplot_class_factory)
-
-from .axislines import Axes
-
-
-ParasiteAxes = parasite_axes_class_factory(Axes)
-
-ParasiteAxesAuxTrans = \
- parasite_axes_auxtrans_class_factory(axes_class=ParasiteAxes)
-
-HostAxes = host_axes_class_factory(axes_class=Axes)
-
-SubplotHost = subplot_class_factory(HostAxes)
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/__init__.py b/contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/__init__.py
deleted file mode 100644
index cd9c2139d27..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-
-from .axes3d import Axes3D
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/art3d.py b/contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/art3d.py
deleted file mode 100644
index ef55dd693e1..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/art3d.py
+++ /dev/null
@@ -1,774 +0,0 @@
-# art3d.py, original mplot3d version by John Porter
-# Parts rewritten by Reinier Heeres <[email protected]>
-# Minor additions by Ben Axelrod <[email protected]>
-
-'''
-Module containing 3D artist code and functions to convert 2D
-artists into 3D versions which can be added to an Axes3D.
-'''
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-from six.moves import zip
-
-import math
-
-import numpy as np
-
-from matplotlib import (
- artist, cbook, colors as mcolors, lines, text as mtext, path as mpath)
-from matplotlib.cbook import _backports
-from matplotlib.collections import (
- Collection, LineCollection, PolyCollection, PatchCollection,
- PathCollection)
-from matplotlib.colors import Normalize
-from matplotlib.patches import Patch
-from . import proj3d
-
-
-def norm_angle(a):
- """Return angle between -180 and +180"""
- a = (a + 360) % 360
- if a > 180:
- a = a - 360
- return a
-
-
-def norm_text_angle(a):
- """Return angle between -90 and +90"""
- a = (a + 180) % 180
- if a > 90:
- a = a - 180
- return a
-
-
-def get_dir_vector(zdir):
- if zdir == 'x':
- return np.array((1, 0, 0))
- elif zdir == 'y':
- return np.array((0, 1, 0))
- elif zdir == 'z':
- return np.array((0, 0, 1))
- elif zdir is None:
- return np.array((0, 0, 0))
- elif cbook.iterable(zdir) and len(zdir) == 3:
- return zdir
- else:
- raise ValueError("'x', 'y', 'z', None or vector of length 3 expected")
-
-
-class Text3D(mtext.Text):
- '''
- Text object with 3D position and (in the future) direction.
- '''
-
- def __init__(self, x=0, y=0, z=0, text='', zdir='z', **kwargs):
- '''
- *x*, *y*, *z* Position of text
- *text* Text string to display
- *zdir* Direction of text
-
- Keyword arguments are passed onto :func:`~matplotlib.text.Text`.
- '''
- mtext.Text.__init__(self, x, y, text, **kwargs)
- self.set_3d_properties(z, zdir)
-
- def set_3d_properties(self, z=0, zdir='z'):
- x, y = self.get_position()
- self._position3d = np.array((x, y, z))
- self._dir_vec = get_dir_vector(zdir)
- self.stale = True
-
- def draw(self, renderer):
- proj = proj3d.proj_trans_points(
- [self._position3d, self._position3d + self._dir_vec], renderer.M)
- dx = proj[0][1] - proj[0][0]
- dy = proj[1][1] - proj[1][0]
- if dx==0. and dy==0.:
- # atan2 raises ValueError: math domain error on 0,0
- angle = 0.
- else:
- angle = math.degrees(math.atan2(dy, dx))
- self.set_position((proj[0][0], proj[1][0]))
- self.set_rotation(norm_text_angle(angle))
- mtext.Text.draw(self, renderer)
- self.stale = False
-
-
-def text_2d_to_3d(obj, z=0, zdir='z'):
- """Convert a Text to a Text3D object."""
- obj.__class__ = Text3D
- obj.set_3d_properties(z, zdir)
-
-
-class Line3D(lines.Line2D):
- '''
- 3D line object.
- '''
-
- def __init__(self, xs, ys, zs, *args, **kwargs):
- '''
- Keyword arguments are passed onto :func:`~matplotlib.lines.Line2D`.
- '''
- lines.Line2D.__init__(self, [], [], *args, **kwargs)
- self._verts3d = xs, ys, zs
-
- def set_3d_properties(self, zs=0, zdir='z'):
- xs = self.get_xdata()
- ys = self.get_ydata()
-
- try:
- # If *zs* is a list or array, then this will fail and
- # just proceed to juggle_axes().
- zs = float(zs)
- zs = [zs for x in xs]
- except TypeError:
- pass
- self._verts3d = juggle_axes(xs, ys, zs, zdir)
- self.stale = True
-
- def draw(self, renderer):
- xs3d, ys3d, zs3d = self._verts3d
- xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
- self.set_data(xs, ys)
- lines.Line2D.draw(self, renderer)
- self.stale = False
-
-
-def line_2d_to_3d(line, zs=0, zdir='z'):
- '''
- Convert a 2D line to 3D.
- '''
- line.__class__ = Line3D
- line.set_3d_properties(zs, zdir)
-
-
-def path_to_3d_segment(path, zs=0, zdir='z'):
- '''Convert a path to a 3D segment.'''
-
- zs = _backports.broadcast_to(zs, len(path))
- pathsegs = path.iter_segments(simplify=False, curves=False)
- seg = [(x, y, z) for (((x, y), code), z) in zip(pathsegs, zs)]
- seg3d = [juggle_axes(x, y, z, zdir) for (x, y, z) in seg]
- return seg3d
-
-
-def paths_to_3d_segments(paths, zs=0, zdir='z'):
- '''
- Convert paths from a collection object to 3D segments.
- '''
-
- zs = _backports.broadcast_to(zs, len(paths))
- segs = [path_to_3d_segment(path, pathz, zdir)
- for path, pathz in zip(paths, zs)]
- return segs
-
-
-def path_to_3d_segment_with_codes(path, zs=0, zdir='z'):
- '''Convert a path to a 3D segment with path codes.'''
-
- zs = _backports.broadcast_to(zs, len(path))
- seg = []
- codes = []
- pathsegs = path.iter_segments(simplify=False, curves=False)
- for (((x, y), code), z) in zip(pathsegs, zs):
- seg.append((x, y, z))
- codes.append(code)
- seg3d = [juggle_axes(x, y, z, zdir) for (x, y, z) in seg]
- return seg3d, codes
-
-
-def paths_to_3d_segments_with_codes(paths, zs=0, zdir='z'):
- '''
- Convert paths from a collection object to 3D segments with path codes.
- '''
-
- zs = _backports.broadcast_to(zs, len(paths))
- segments = []
- codes_list = []
- for path, pathz in zip(paths, zs):
- segs, codes = path_to_3d_segment_with_codes(path, pathz, zdir)
- segments.append(segs)
- codes_list.append(codes)
- return segments, codes_list
-
-
-class Line3DCollection(LineCollection):
- '''
- A collection of 3D lines.
- '''
-
- def __init__(self, segments, *args, **kwargs):
- '''
- Keyword arguments are passed onto :func:`~matplotlib.collections.LineCollection`.
- '''
- LineCollection.__init__(self, segments, *args, **kwargs)
-
- def set_sort_zpos(self, val):
- '''Set the position to use for z-sorting.'''
- self._sort_zpos = val
- self.stale = True
-
- def set_segments(self, segments):
- '''
- Set 3D segments
- '''
- self._segments3d = np.asanyarray(segments)
- LineCollection.set_segments(self, [])
-
- def do_3d_projection(self, renderer):
- '''
- Project the points according to renderer matrix.
- '''
- xyslist = [
- proj3d.proj_trans_points(points, renderer.M) for points in
- self._segments3d]
- segments_2d = [np.column_stack([xs, ys]) for xs, ys, zs in xyslist]
- LineCollection.set_segments(self, segments_2d)
-
- # FIXME
- minz = 1e9
- for xs, ys, zs in xyslist:
- minz = min(minz, min(zs))
- return minz
-
- def draw(self, renderer, project=False):
- if project:
- self.do_3d_projection(renderer)
- LineCollection.draw(self, renderer)
-
-
-def line_collection_2d_to_3d(col, zs=0, zdir='z'):
- """Convert a LineCollection to a Line3DCollection object."""
- segments3d = paths_to_3d_segments(col.get_paths(), zs, zdir)
- col.__class__ = Line3DCollection
- col.set_segments(segments3d)
-
-
-class Patch3D(Patch):
- '''
- 3D patch object.
- '''
-
- def __init__(self, *args, **kwargs):
- zs = kwargs.pop('zs', [])
- zdir = kwargs.pop('zdir', 'z')
- Patch.__init__(self, *args, **kwargs)
- self.set_3d_properties(zs, zdir)
-
- def set_3d_properties(self, verts, zs=0, zdir='z'):
- zs = _backports.broadcast_to(zs, len(verts))
- self._segment3d = [juggle_axes(x, y, z, zdir)
- for ((x, y), z) in zip(verts, zs)]
- self._facecolor3d = Patch.get_facecolor(self)
-
- def get_path(self):
- return self._path2d
-
- def get_facecolor(self):
- return self._facecolor2d
-
- def do_3d_projection(self, renderer):
- s = self._segment3d
- xs, ys, zs = zip(*s)
- vxs, vys, vzs, vis = proj3d.proj_transform_clip(xs, ys, zs, renderer.M)
- self._path2d = mpath.Path(np.column_stack([vxs, vys]))
- # FIXME: coloring
- self._facecolor2d = self._facecolor3d
- return min(vzs)
-
- def draw(self, renderer):
- Patch.draw(self, renderer)
-
-
-class PathPatch3D(Patch3D):
- '''
- 3D PathPatch object.
- '''
-
- def __init__(self, path, **kwargs):
- zs = kwargs.pop('zs', [])
- zdir = kwargs.pop('zdir', 'z')
- Patch.__init__(self, **kwargs)
- self.set_3d_properties(path, zs, zdir)
-
- def set_3d_properties(self, path, zs=0, zdir='z'):
- Patch3D.set_3d_properties(self, path.vertices, zs=zs, zdir=zdir)
- self._code3d = path.codes
-
- def do_3d_projection(self, renderer):
- s = self._segment3d
- xs, ys, zs = zip(*s)
- vxs, vys, vzs, vis = proj3d.proj_transform_clip(xs, ys, zs, renderer.M)
- self._path2d = mpath.Path(np.column_stack([vxs, vys]), self._code3d)
- # FIXME: coloring
- self._facecolor2d = self._facecolor3d
- return min(vzs)
-
-
-def get_patch_verts(patch):
- """Return a list of vertices for the path of a patch."""
- trans = patch.get_patch_transform()
- path = patch.get_path()
- polygons = path.to_polygons(trans)
- if len(polygons):
- return polygons[0]
- else:
- return []
-
-
-def patch_2d_to_3d(patch, z=0, zdir='z'):
- """Convert a Patch to a Patch3D object."""
- verts = get_patch_verts(patch)
- patch.__class__ = Patch3D
- patch.set_3d_properties(verts, z, zdir)
-
-
-def pathpatch_2d_to_3d(pathpatch, z=0, zdir='z'):
- """Convert a PathPatch to a PathPatch3D object."""
- path = pathpatch.get_path()
- trans = pathpatch.get_patch_transform()
-
- mpath = trans.transform_path(path)
- pathpatch.__class__ = PathPatch3D
- pathpatch.set_3d_properties(mpath, z, zdir)
-
-
-class Patch3DCollection(PatchCollection):
- '''
- A collection of 3D patches.
- '''
-
- def __init__(self, *args, **kwargs):
- """
- Create a collection of flat 3D patches with its normal vector
- pointed in *zdir* direction, and located at *zs* on the *zdir*
- axis. 'zs' can be a scalar or an array-like of the same length as
- the number of patches in the collection.
-
- Constructor arguments are the same as for
- :class:`~matplotlib.collections.PatchCollection`. In addition,
- keywords *zs=0* and *zdir='z'* are available.
-
- Also, the keyword argument "depthshade" is available to
- indicate whether or not to shade the patches in order to
- give the appearance of depth (default is *True*).
- This is typically desired in scatter plots.
- """
- zs = kwargs.pop('zs', 0)
- zdir = kwargs.pop('zdir', 'z')
- self._depthshade = kwargs.pop('depthshade', True)
- PatchCollection.__init__(self, *args, **kwargs)
- self.set_3d_properties(zs, zdir)
-
- def set_sort_zpos(self, val):
- '''Set the position to use for z-sorting.'''
- self._sort_zpos = val
- self.stale = True
-
- def set_3d_properties(self, zs, zdir):
- # Force the collection to initialize the face and edgecolors
- # just in case it is a scalarmappable with a colormap.
- self.update_scalarmappable()
- offsets = self.get_offsets()
- if len(offsets) > 0:
- xs, ys = zip(*offsets)
- else:
- xs = []
- ys = []
- self._offsets3d = juggle_axes(xs, ys, np.atleast_1d(zs), zdir)
- self._facecolor3d = self.get_facecolor()
- self._edgecolor3d = self.get_edgecolor()
- self.stale = True
-
- def do_3d_projection(self, renderer):
- xs, ys, zs = self._offsets3d
- vxs, vys, vzs, vis = proj3d.proj_transform_clip(xs, ys, zs, renderer.M)
-
- fcs = (zalpha(self._facecolor3d, vzs) if self._depthshade else
- self._facecolor3d)
- fcs = mcolors.to_rgba_array(fcs, self._alpha)
- self.set_facecolors(fcs)
-
- ecs = (zalpha(self._edgecolor3d, vzs) if self._depthshade else
- self._edgecolor3d)
- ecs = mcolors.to_rgba_array(ecs, self._alpha)
- self.set_edgecolors(ecs)
- PatchCollection.set_offsets(self, np.column_stack([vxs, vys]))
-
- if vzs.size > 0:
- return min(vzs)
- else:
- return np.nan
-
-
-class Path3DCollection(PathCollection):
- '''
- A collection of 3D paths.
- '''
-
- def __init__(self, *args, **kwargs):
- """
- Create a collection of flat 3D paths with its normal vector
- pointed in *zdir* direction, and located at *zs* on the *zdir*
- axis. 'zs' can be a scalar or an array-like of the same length as
- the number of paths in the collection.
-
- Constructor arguments are the same as for
- :class:`~matplotlib.collections.PathCollection`. In addition,
- keywords *zs=0* and *zdir='z'* are available.
-
- Also, the keyword argument "depthshade" is available to
- indicate whether or not to shade the patches in order to
- give the appearance of depth (default is *True*).
- This is typically desired in scatter plots.
- """
- zs = kwargs.pop('zs', 0)
- zdir = kwargs.pop('zdir', 'z')
- self._depthshade = kwargs.pop('depthshade', True)
- PathCollection.__init__(self, *args, **kwargs)
- self.set_3d_properties(zs, zdir)
-
- def set_sort_zpos(self, val):
- '''Set the position to use for z-sorting.'''
- self._sort_zpos = val
- self.stale = True
-
- def set_3d_properties(self, zs, zdir):
- # Force the collection to initialize the face and edgecolors
- # just in case it is a scalarmappable with a colormap.
- self.update_scalarmappable()
- offsets = self.get_offsets()
- if len(offsets) > 0:
- xs, ys = zip(*offsets)
- else:
- xs = []
- ys = []
- self._offsets3d = juggle_axes(xs, ys, np.atleast_1d(zs), zdir)
- self._facecolor3d = self.get_facecolor()
- self._edgecolor3d = self.get_edgecolor()
- self.stale = True
-
- def do_3d_projection(self, renderer):
- xs, ys, zs = self._offsets3d
- vxs, vys, vzs, vis = proj3d.proj_transform_clip(xs, ys, zs, renderer.M)
-
- fcs = (zalpha(self._facecolor3d, vzs) if self._depthshade else
- self._facecolor3d)
- fcs = mcolors.to_rgba_array(fcs, self._alpha)
- self.set_facecolors(fcs)
-
- ecs = (zalpha(self._edgecolor3d, vzs) if self._depthshade else
- self._edgecolor3d)
- ecs = mcolors.to_rgba_array(ecs, self._alpha)
- self.set_edgecolors(ecs)
- PathCollection.set_offsets(self, np.column_stack([vxs, vys]))
-
- if vzs.size > 0 :
- return min(vzs)
- else :
- return np.nan
-
-
-def patch_collection_2d_to_3d(col, zs=0, zdir='z', depthshade=True):
- """
- Convert a :class:`~matplotlib.collections.PatchCollection` into a
- :class:`Patch3DCollection` object
- (or a :class:`~matplotlib.collections.PathCollection` into a
- :class:`Path3DCollection` object).
-
- Keywords:
-
- *za* The location or locations to place the patches in the
- collection along the *zdir* axis. Defaults to 0.
-
- *zdir* The axis in which to place the patches. Default is "z".
-
- *depthshade* Whether to shade the patches to give a sense of depth.
- Defaults to *True*.
-
- """
- if isinstance(col, PathCollection):
- col.__class__ = Path3DCollection
- elif isinstance(col, PatchCollection):
- col.__class__ = Patch3DCollection
- col._depthshade = depthshade
- col.set_3d_properties(zs, zdir)
-
-
-class Poly3DCollection(PolyCollection):
- '''
- A collection of 3D polygons.
- '''
-
- def __init__(self, verts, *args, **kwargs):
- '''
- Create a Poly3DCollection.
-
- *verts* should contain 3D coordinates.
-
- Keyword arguments:
- zsort, see set_zsort for options.
-
- Note that this class does a bit of magic with the _facecolors
- and _edgecolors properties.
- '''
- zsort = kwargs.pop('zsort', True)
- PolyCollection.__init__(self, verts, *args, **kwargs)
- self.set_zsort(zsort)
- self._codes3d = None
-
- _zsort_functions = {
- 'average': np.average,
- 'min': np.min,
- 'max': np.max,
- }
-
- def set_zsort(self, zsort):
- '''
- Set z-sorting behaviour:
- boolean: if True use default 'average'
- string: 'average', 'min' or 'max'
- '''
-
- if zsort is True:
- zsort = 'average'
-
- if zsort is not False:
- if zsort in self._zsort_functions:
- zsortfunc = self._zsort_functions[zsort]
- else:
- return False
- else:
- zsortfunc = None
-
- self._zsort = zsort
- self._sort_zpos = None
- self._zsortfunc = zsortfunc
- self.stale = True
-
- def get_vector(self, segments3d):
- """Optimize points for projection"""
- si = 0
- ei = 0
- segis = []
- points = []
- for p in segments3d:
- points.extend(p)
- ei = si + len(p)
- segis.append((si, ei))
- si = ei
-
- if len(segments3d):
- xs, ys, zs = zip(*points)
- else :
- # We need this so that we can skip the bad unpacking from zip()
- xs, ys, zs = [], [], []
-
- ones = np.ones(len(xs))
- self._vec = np.array([xs, ys, zs, ones])
- self._segis = segis
-
- def set_verts(self, verts, closed=True):
- '''Set 3D vertices.'''
- self.get_vector(verts)
- # 2D verts will be updated at draw time
- PolyCollection.set_verts(self, [], False)
- self._closed = closed
-
- def set_verts_and_codes(self, verts, codes):
- '''Sets 3D vertices with path codes'''
- # set vertices with closed=False to prevent PolyCollection from
- # setting path codes
- self.set_verts(verts, closed=False)
- # and set our own codes instead.
- self._codes3d = codes
-
- def set_3d_properties(self):
- # Force the collection to initialize the face and edgecolors
- # just in case it is a scalarmappable with a colormap.
- self.update_scalarmappable()
- self._sort_zpos = None
- self.set_zsort(True)
- self._facecolors3d = PolyCollection.get_facecolors(self)
- self._edgecolors3d = PolyCollection.get_edgecolors(self)
- self._alpha3d = PolyCollection.get_alpha(self)
- self.stale = True
-
- def set_sort_zpos(self,val):
- '''Set the position to use for z-sorting.'''
- self._sort_zpos = val
- self.stale = True
-
- def do_3d_projection(self, renderer):
- '''
- Perform the 3D projection for this object.
- '''
- # FIXME: This may no longer be needed?
- if self._A is not None:
- self.update_scalarmappable()
- self._facecolors3d = self._facecolors
-
- txs, tys, tzs = proj3d.proj_transform_vec(self._vec, renderer.M)
- xyzlist = [(txs[si:ei], tys[si:ei], tzs[si:ei])
- for si, ei in self._segis]
-
- # This extra fuss is to re-order face / edge colors
- cface = self._facecolors3d
- cedge = self._edgecolors3d
- if len(cface) != len(xyzlist):
- cface = cface.repeat(len(xyzlist), axis=0)
- if len(cedge) != len(xyzlist):
- if len(cedge) == 0:
- cedge = cface
- else:
- cedge = cedge.repeat(len(xyzlist), axis=0)
-
- # if required sort by depth (furthest drawn first)
- if self._zsort:
- z_segments_2d = sorted(
- ((self._zsortfunc(zs), np.column_stack([xs, ys]), fc, ec, idx)
- for idx, ((xs, ys, zs), fc, ec)
- in enumerate(zip(xyzlist, cface, cedge))),
- key=lambda x: x[0], reverse=True)
- else:
- raise ValueError("whoops")
-
- segments_2d = [s for z, s, fc, ec, idx in z_segments_2d]
- if self._codes3d is not None:
- codes = [self._codes3d[idx] for z, s, fc, ec, idx in z_segments_2d]
- PolyCollection.set_verts_and_codes(self, segments_2d, codes)
- else:
- PolyCollection.set_verts(self, segments_2d, self._closed)
-
- self._facecolors2d = [fc for z, s, fc, ec, idx in z_segments_2d]
- if len(self._edgecolors3d) == len(cface):
- self._edgecolors2d = [ec for z, s, fc, ec, idx in z_segments_2d]
- else:
- self._edgecolors2d = self._edgecolors3d
-
- # Return zorder value
- if self._sort_zpos is not None:
- zvec = np.array([[0], [0], [self._sort_zpos], [1]])
- ztrans = proj3d.proj_transform_vec(zvec, renderer.M)
- return ztrans[2][0]
- elif tzs.size > 0 :
- # FIXME: Some results still don't look quite right.
- # In particular, examine contourf3d_demo2.py
- # with az = -54 and elev = -45.
- return np.min(tzs)
- else :
- return np.nan
-
- def set_facecolor(self, colors):
- PolyCollection.set_facecolor(self, colors)
- self._facecolors3d = PolyCollection.get_facecolor(self)
- set_facecolors = set_facecolor
-
- def set_edgecolor(self, colors):
- PolyCollection.set_edgecolor(self, colors)
- self._edgecolors3d = PolyCollection.get_edgecolor(self)
- set_edgecolors = set_edgecolor
-
- def set_alpha(self, alpha):
- """
- Set the alpha tranparencies of the collection. *alpha* must be
- a float or *None*.
-
- ACCEPTS: float or None
- """
- if alpha is not None:
- try:
- float(alpha)
- except TypeError:
- raise TypeError('alpha must be a float or None')
- artist.Artist.set_alpha(self, alpha)
- try:
- self._facecolors = mcolors.to_rgba_array(
- self._facecolors3d, self._alpha)
- except (AttributeError, TypeError, IndexError):
- pass
- try:
- self._edgecolors = mcolors.to_rgba_array(
- self._edgecolors3d, self._alpha)
- except (AttributeError, TypeError, IndexError):
- pass
- self.stale = True
-
- def get_facecolors(self):
- return self._facecolors2d
- get_facecolor = get_facecolors
-
- def get_edgecolors(self):
- return self._edgecolors2d
- get_edgecolor = get_edgecolors
-
- def draw(self, renderer):
- return Collection.draw(self, renderer)
-
-
-def poly_collection_2d_to_3d(col, zs=0, zdir='z'):
- """Convert a PolyCollection to a Poly3DCollection object."""
- segments_3d, codes = paths_to_3d_segments_with_codes(col.get_paths(),
- zs, zdir)
- col.__class__ = Poly3DCollection
- col.set_verts_and_codes(segments_3d, codes)
- col.set_3d_properties()
-
-
-def juggle_axes(xs, ys, zs, zdir):
- """
- Reorder coordinates so that 2D xs, ys can be plotted in the plane
- orthogonal to zdir. zdir is normally x, y or z. However, if zdir
- starts with a '-' it is interpreted as a compensation for rotate_axes.
- """
- if zdir == 'x':
- return zs, xs, ys
- elif zdir == 'y':
- return xs, zs, ys
- elif zdir[0] == '-':
- return rotate_axes(xs, ys, zs, zdir)
- else:
- return xs, ys, zs
-
-
-def rotate_axes(xs, ys, zs, zdir):
- """
- Reorder coordinates so that the axes are rotated with zdir along
- the original z axis. Prepending the axis with a '-' does the
- inverse transform, so zdir can be x, -x, y, -y, z or -z
- """
- if zdir == 'x':
- return ys, zs, xs
- elif zdir == '-x':
- return zs, xs, ys
-
- elif zdir == 'y':
- return zs, xs, ys
- elif zdir == '-y':
- return ys, zs, xs
-
- else:
- return xs, ys, zs
-
-
-def get_colors(c, num):
- """Stretch the color argument to provide the required number num"""
- return _backports.broadcast_to(
- mcolors.to_rgba_array(c) if len(c) else [0, 0, 0, 0],
- (num, 4))
-
-
-def zalpha(colors, zs):
- """Modify the alphas of the color list according to depth"""
- # FIXME: This only works well if the points for *zs* are well-spaced
- # in all three dimensions. Otherwise, at certain orientations,
- # the min and max zs are very close together.
- # Should really normalize against the viewing depth.
- colors = get_colors(colors, len(zs))
- if len(zs):
- norm = Normalize(min(zs), max(zs))
- sats = 1 - norm(zs) * 0.7
- colors = [(c[0], c[1], c[2], c[3] * s) for c, s in zip(colors, sats)]
- return colors
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/axes3d.py b/contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/axes3d.py
deleted file mode 100644
index b99a090c62c..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/axes3d.py
+++ /dev/null
@@ -1,2958 +0,0 @@
-"""
-axes3d.py, original mplot3d version by John Porter
-Created: 23 Sep 2005
-
-Parts fixed by Reinier Heeres <[email protected]>
-Minor additions by Ben Axelrod <[email protected]>
-Significant updates and revisions by Ben Root <[email protected]>
-
-Module containing Axes3D, an object which can plot 3D objects on a
-2D matplotlib figure.
-"""
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-from six.moves import map, xrange, zip, reduce
-
-import math
-import warnings
-from collections import defaultdict
-
-import numpy as np
-
-import matplotlib.axes as maxes
-import matplotlib.cbook as cbook
-import matplotlib.collections as mcoll
-import matplotlib.colors as mcolors
-import matplotlib.docstring as docstring
-import matplotlib.scale as mscale
-import matplotlib.transforms as mtransforms
-from matplotlib.axes import Axes, rcParams
-from matplotlib.cbook import _backports
-from matplotlib.colors import Normalize, LightSource
-from matplotlib.transforms import Bbox
-from matplotlib.tri.triangulation import Triangulation
-
-from . import art3d
-from . import proj3d
-from . import axis3d
-
-
-def unit_bbox():
- box = Bbox(np.array([[0, 0], [1, 1]]))
- return box
-
-
-class Axes3D(Axes):
- """
- 3D axes object.
- """
- name = '3d'
- _shared_z_axes = cbook.Grouper()
-
- def __init__(self, fig, rect=None, *args, **kwargs):
- '''
- Build an :class:`Axes3D` instance in
- :class:`~matplotlib.figure.Figure` *fig* with
- *rect=[left, bottom, width, height]* in
- :class:`~matplotlib.figure.Figure` coordinates
-
- Optional keyword arguments:
-
- ================ =========================================
- Keyword Description
- ================ =========================================
- *azim* Azimuthal viewing angle (default -60)
- *elev* Elevation viewing angle (default 30)
- *zscale* [%(scale)s]
- *sharez* Other axes to share z-limits with
- *proj_type* 'persp' or 'ortho' (default 'persp')
- ================ =========================================
-
- .. versionadded :: 1.2.1
- *sharez*
-
- ''' % {'scale': ' | '.join([repr(x) for x in mscale.get_scale_names()])}
-
- if rect is None:
- rect = [0.0, 0.0, 1.0, 1.0]
- self._cids = []
-
- self.initial_azim = kwargs.pop('azim', -60)
- self.initial_elev = kwargs.pop('elev', 30)
- zscale = kwargs.pop('zscale', None)
- sharez = kwargs.pop('sharez', None)
- self.set_proj_type(kwargs.pop('proj_type', 'persp'))
-
- self.xy_viewLim = unit_bbox()
- self.zz_viewLim = unit_bbox()
- self.xy_dataLim = unit_bbox()
- self.zz_dataLim = unit_bbox()
- # inihibit autoscale_view until the axes are defined
- # they can't be defined until Axes.__init__ has been called
- self.view_init(self.initial_elev, self.initial_azim)
- self._ready = 0
-
- self._sharez = sharez
- if sharez is not None:
- self._shared_z_axes.join(self, sharez)
- self._adjustable = 'datalim'
-
- super(Axes3D, self).__init__(fig, rect,
- frameon=True,
- *args, **kwargs)
- # Disable drawing of axes by base class
- super(Axes3D, self).set_axis_off()
- # Enable drawing of axes by Axes3D class
- self.set_axis_on()
- self.M = None
-
- # func used to format z -- fall back on major formatters
- self.fmt_zdata = None
-
- if zscale is not None:
- self.set_zscale(zscale)
-
- if self.zaxis is not None:
- self._zcid = self.zaxis.callbacks.connect(
- 'units finalize', lambda: self._on_units_changed(scalez=True))
- else:
- self._zcid = None
-
- self._ready = 1
- self.mouse_init()
- self.set_top_view()
-
- self.patch.set_linewidth(0)
- # Calculate the pseudo-data width and height
- pseudo_bbox = self.transLimits.inverted().transform([(0, 0), (1, 1)])
- self._pseudo_w, self._pseudo_h = pseudo_bbox[1] - pseudo_bbox[0]
-
- self.figure.add_axes(self)
-
- def set_axis_off(self):
- self._axis3don = False
- self.stale = True
-
- def set_axis_on(self):
- self._axis3don = True
- self.stale = True
-
- def have_units(self):
- """
- Return *True* if units are set on the *x*, *y*, or *z* axes
-
- """
- return (self.xaxis.have_units() or self.yaxis.have_units() or
- self.zaxis.have_units())
-
- def convert_zunits(self, z):
- """
- For artists in an axes, if the zaxis has units support,
- convert *z* using zaxis unit type
-
- .. versionadded :: 1.2.1
-
- """
- return self.zaxis.convert_units(z)
-
- def _process_unit_info(self, xdata=None, ydata=None, zdata=None,
- kwargs=None):
- """
- Look for unit *kwargs* and update the axis instances as necessary
-
- """
- super(Axes3D, self)._process_unit_info(xdata=xdata, ydata=ydata,
- kwargs=kwargs)
-
- if self.xaxis is None or self.yaxis is None or self.zaxis is None:
- return
-
- if zdata is not None:
- # we only need to update if there is nothing set yet.
- if not self.zaxis.have_units():
- self.zaxis.update_units(xdata)
-
- # process kwargs 2nd since these will override default units
- if kwargs is not None:
- zunits = kwargs.pop('zunits', self.zaxis.units)
- if zunits != self.zaxis.units:
- self.zaxis.set_units(zunits)
- # If the units being set imply a different converter,
- # we need to update.
- if zdata is not None:
- self.zaxis.update_units(zdata)
-
- def set_top_view(self):
- # this happens to be the right view for the viewing coordinates
- # moved up and to the left slightly to fit labels and axes
- xdwl = (0.95/self.dist)
- xdw = (0.9/self.dist)
- ydwl = (0.95/self.dist)
- ydw = (0.9/self.dist)
-
- # This is purposely using the 2D Axes's set_xlim and set_ylim,
- # because we are trying to place our viewing pane.
- super(Axes3D, self).set_xlim(-xdwl, xdw, auto=None)
- super(Axes3D, self).set_ylim(-ydwl, ydw, auto=None)
-
- def _init_axis(self):
- '''Init 3D axes; overrides creation of regular X/Y axes'''
- self.w_xaxis = axis3d.XAxis('x', self.xy_viewLim.intervalx,
- self.xy_dataLim.intervalx, self)
- self.xaxis = self.w_xaxis
- self.w_yaxis = axis3d.YAxis('y', self.xy_viewLim.intervaly,
- self.xy_dataLim.intervaly, self)
- self.yaxis = self.w_yaxis
- self.w_zaxis = axis3d.ZAxis('z', self.zz_viewLim.intervalx,
- self.zz_dataLim.intervalx, self)
- self.zaxis = self.w_zaxis
-
- for ax in self.xaxis, self.yaxis, self.zaxis:
- ax.init3d()
-
- def get_children(self):
- return [self.zaxis, ] + super(Axes3D, self).get_children()
-
- def _get_axis_list(self):
- return super(Axes3D, self)._get_axis_list() + (self.zaxis, )
-
- def unit_cube(self, vals=None):
- minx, maxx, miny, maxy, minz, maxz = vals or self.get_w_lims()
- xs, ys, zs = ([minx, maxx, maxx, minx, minx, maxx, maxx, minx],
- [miny, miny, maxy, maxy, miny, miny, maxy, maxy],
- [minz, minz, minz, minz, maxz, maxz, maxz, maxz])
- return list(zip(xs, ys, zs))
-
- def tunit_cube(self, vals=None, M=None):
- if M is None:
- M = self.M
- xyzs = self.unit_cube(vals)
- tcube = proj3d.proj_points(xyzs, M)
- return tcube
-
- def tunit_edges(self, vals=None, M=None):
- tc = self.tunit_cube(vals, M)
- edges = [(tc[0], tc[1]),
- (tc[1], tc[2]),
- (tc[2], tc[3]),
- (tc[3], tc[0]),
-
- (tc[0], tc[4]),
- (tc[1], tc[5]),
- (tc[2], tc[6]),
- (tc[3], tc[7]),
-
- (tc[4], tc[5]),
- (tc[5], tc[6]),
- (tc[6], tc[7]),
- (tc[7], tc[4])]
- return edges
-
- def draw(self, renderer):
- # draw the background patch
- self.patch.draw(renderer)
- self._frameon = False
-
- # first, set the aspect
- # this is duplicated from `axes._base._AxesBase.draw`
- # but must be called before any of the artist are drawn as
- # it adjusts the view limits and the size of the bounding box
- # of the axes
- locator = self.get_axes_locator()
- if locator:
- pos = locator(self, renderer)
- self.apply_aspect(pos)
- else:
- self.apply_aspect()
-
- # add the projection matrix to the renderer
- self.M = self.get_proj()
- renderer.M = self.M
- renderer.vvec = self.vvec
- renderer.eye = self.eye
- renderer.get_axis_position = self.get_axis_position
-
- # Calculate projection of collections and zorder them
- for i, col in enumerate(
- sorted(self.collections,
- key=lambda col: col.do_3d_projection(renderer),
- reverse=True)):
- col.zorder = i
-
- # Calculate projection of patches and zorder them
- for i, patch in enumerate(
- sorted(self.patches,
- key=lambda patch: patch.do_3d_projection(renderer),
- reverse=True)):
- patch.zorder = i
-
- if self._axis3don:
- axes = (self.xaxis, self.yaxis, self.zaxis)
- # Draw panes first
- for ax in axes:
- ax.draw_pane(renderer)
- # Then axes
- for ax in axes:
- ax.draw(renderer)
-
- # Then rest
- super(Axes3D, self).draw(renderer)
-
- def get_axis_position(self):
- vals = self.get_w_lims()
- tc = self.tunit_cube(vals, self.M)
- xhigh = tc[1][2] > tc[2][2]
- yhigh = tc[3][2] > tc[2][2]
- zhigh = tc[0][2] > tc[2][2]
- return xhigh, yhigh, zhigh
-
- def _on_units_changed(self, scalex=False, scaley=False, scalez=False):
- """
- Callback for processing changes to axis units.
-
- Currently forces updates of data limits and view limits.
- """
- self.relim()
- self.autoscale_view(scalex=scalex, scaley=scaley, scalez=scalez)
-
- def update_datalim(self, xys, **kwargs):
- pass
-
- def get_autoscale_on(self):
- """
- Get whether autoscaling is applied for all axes on plot commands
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
- return super(Axes3D, self).get_autoscale_on() and self.get_autoscalez_on()
-
- def get_autoscalez_on(self):
- """
- Get whether autoscaling for the z-axis is applied on plot commands
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
- return self._autoscaleZon
-
- def set_autoscale_on(self, b):
- """
- Set whether autoscaling is applied on plot commands
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
-
- Parameters
- ----------
- b : bool
- .. ACCEPTS: bool
- """
- super(Axes3D, self).set_autoscale_on(b)
- self.set_autoscalez_on(b)
-
- def set_autoscalez_on(self, b):
- """
- Set whether autoscaling for the z-axis is applied on plot commands
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
-
- Parameters
- ----------
- b : bool
- .. ACCEPTS: bool
- """
- self._autoscaleZon = b
-
- def set_zmargin(self, m):
- """
- Set padding of Z data limits prior to autoscaling.
-
- *m* times the data interval will be added to each
- end of that interval before it is used in autoscaling.
-
- accepts: float in range 0 to 1
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
- if m < 0 or m > 1 :
- raise ValueError("margin must be in range 0 to 1")
- self._zmargin = m
- self.stale = True
-
- def margins(self, *args, **kw):
- """
- Convenience method to set or retrieve autoscaling margins.
-
- signatures::
- margins()
-
- returns xmargin, ymargin, zmargin
-
- ::
-
- margins(margin)
-
- margins(xmargin, ymargin, zmargin)
-
- margins(x=xmargin, y=ymargin, z=zmargin)
-
- margins(..., tight=False)
-
- All forms above set the xmargin, ymargin and zmargin
- parameters. All keyword parameters are optional. A single argument
- specifies xmargin, ymargin and zmargin. The *tight* parameter
- is passed to :meth:`autoscale_view`, which is executed after
- a margin is changed; the default here is *True*, on the
- assumption that when margins are specified, no additional
- padding to match tick marks is usually desired. Setting
- *tight* to *None* will preserve the previous setting.
-
- Specifying any margin changes only the autoscaling; for example,
- if *xmargin* is not None, then *xmargin* times the X data
- interval will be added to each end of that interval before
- it is used in autoscaling.
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
- if not args and not kw:
- return self._xmargin, self._ymargin, self._zmargin
-
- tight = kw.pop('tight', True)
- mx = kw.pop('x', None)
- my = kw.pop('y', None)
- mz = kw.pop('z', None)
- if not args:
- pass
- elif len(args) == 1:
- mx = my = mz = args[0]
- elif len(args) == 2:
- warnings.warn(
- "Passing exactly two positional arguments to Axes3D.margins "
- "is deprecated. If needed, pass them as keyword arguments "
- "instead", cbook.mplDeprecation)
- mx, my = args
- elif len(args) == 3:
- mx, my, mz = args
- else:
- raise ValueError(
- "Axes3D.margins takes at most three positional arguments")
- if mx is not None:
- self.set_xmargin(mx)
- if my is not None:
- self.set_ymargin(my)
- if mz is not None:
- self.set_zmargin(mz)
-
- scalex = mx is not None
- scaley = my is not None
- scalez = mz is not None
-
- self.autoscale_view(tight=tight, scalex=scalex, scaley=scaley,
- scalez=scalez)
-
- def autoscale(self, enable=True, axis='both', tight=None):
- """
- Convenience method for simple axis view autoscaling.
- See :meth:`matplotlib.axes.Axes.autoscale` for full explanation.
- Note that this function behaves the same, but for all
- three axes. Therefore, 'z' can be passed for *axis*,
- and 'both' applies to all three axes.
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
- if enable is None:
- scalex = True
- scaley = True
- scalez = True
- else:
- if axis in ['x', 'both']:
- self._autoscaleXon = scalex = bool(enable)
- else:
- scalex = False
- if axis in ['y', 'both']:
- self._autoscaleYon = scaley = bool(enable)
- else:
- scaley = False
- if axis in ['z', 'both']:
- self._autoscaleZon = scalez = bool(enable)
- else:
- scalez = False
- self.autoscale_view(tight=tight, scalex=scalex, scaley=scaley,
- scalez=scalez)
-
- def auto_scale_xyz(self, X, Y, Z=None, had_data=None):
- x, y, z = map(np.asarray, (X, Y, Z))
- try:
- x, y = x.flatten(), y.flatten()
- if Z is not None:
- z = z.flatten()
- except AttributeError:
- raise
-
- # This updates the bounding boxes as to keep a record as
- # to what the minimum sized rectangular volume holds the
- # data.
- self.xy_dataLim.update_from_data_xy(np.array([x, y]).T, not had_data)
- if z is not None:
- self.zz_dataLim.update_from_data_xy(np.array([z, z]).T, not had_data)
-
- # Let autoscale_view figure out how to use this data.
- self.autoscale_view()
-
- def autoscale_view(self, tight=None, scalex=True, scaley=True,
- scalez=True):
- """
- Autoscale the view limits using the data limits.
- See :meth:`matplotlib.axes.Axes.autoscale_view` for documentation.
- Note that this function applies to the 3D axes, and as such
- adds the *scalez* to the function arguments.
-
- .. versionchanged :: 1.1.0
- Function signature was changed to better match the 2D version.
- *tight* is now explicitly a kwarg and placed first.
-
- .. versionchanged :: 1.2.1
- This is now fully functional.
-
- """
- if not self._ready:
- return
-
- # This method looks at the rectangular volume (see above)
- # of data and decides how to scale the view portal to fit it.
- if tight is None:
- # if image data only just use the datalim
- _tight = self._tight or (len(self.images)>0 and
- len(self.lines)==0 and
- len(self.patches)==0)
- else:
- _tight = self._tight = bool(tight)
-
- if scalex and self._autoscaleXon:
- xshared = self._shared_x_axes.get_siblings(self)
- dl = [ax.dataLim for ax in xshared]
- bb = mtransforms.BboxBase.union(dl)
- x0, x1 = self.xy_dataLim.intervalx
- xlocator = self.xaxis.get_major_locator()
- try:
- x0, x1 = xlocator.nonsingular(x0, x1)
- except AttributeError:
- x0, x1 = mtransforms.nonsingular(x0, x1, increasing=False,
- expander=0.05)
- if self._xmargin > 0:
- delta = (x1 - x0) * self._xmargin
- x0 -= delta
- x1 += delta
- if not _tight:
- x0, x1 = xlocator.view_limits(x0, x1)
- self.set_xbound(x0, x1)
-
- if scaley and self._autoscaleYon:
- yshared = self._shared_y_axes.get_siblings(self)
- dl = [ax.dataLim for ax in yshared]
- bb = mtransforms.BboxBase.union(dl)
- y0, y1 = self.xy_dataLim.intervaly
- ylocator = self.yaxis.get_major_locator()
- try:
- y0, y1 = ylocator.nonsingular(y0, y1)
- except AttributeError:
- y0, y1 = mtransforms.nonsingular(y0, y1, increasing=False,
- expander=0.05)
- if self._ymargin > 0:
- delta = (y1 - y0) * self._ymargin
- y0 -= delta
- y1 += delta
- if not _tight:
- y0, y1 = ylocator.view_limits(y0, y1)
- self.set_ybound(y0, y1)
-
- if scalez and self._autoscaleZon:
- zshared = self._shared_z_axes.get_siblings(self)
- dl = [ax.dataLim for ax in zshared]
- bb = mtransforms.BboxBase.union(dl)
- z0, z1 = self.zz_dataLim.intervalx
- zlocator = self.zaxis.get_major_locator()
- try:
- z0, z1 = zlocator.nonsingular(z0, z1)
- except AttributeError:
- z0, z1 = mtransforms.nonsingular(z0, z1, increasing=False,
- expander=0.05)
- if self._zmargin > 0:
- delta = (z1 - z0) * self._zmargin
- z0 -= delta
- z1 += delta
- if not _tight:
- z0, z1 = zlocator.view_limits(z0, z1)
- self.set_zbound(z0, z1)
-
- def get_w_lims(self):
- '''Get 3D world limits.'''
- minx, maxx = self.get_xlim3d()
- miny, maxy = self.get_ylim3d()
- minz, maxz = self.get_zlim3d()
- return minx, maxx, miny, maxy, minz, maxz
-
- def _determine_lims(self, xmin=None, xmax=None, *args, **kwargs):
- if xmax is None and cbook.iterable(xmin):
- xmin, xmax = xmin
- if xmin == xmax:
- xmin -= 0.05
- xmax += 0.05
- return (xmin, xmax)
-
- def set_xlim3d(self, left=None, right=None, emit=True, auto=False, **kw):
- """
- Set 3D x limits.
-
- See :meth:`matplotlib.axes.Axes.set_xlim` for full documentation.
-
- """
- if 'xmin' in kw:
- left = kw.pop('xmin')
- if 'xmax' in kw:
- right = kw.pop('xmax')
- if kw:
- raise ValueError("unrecognized kwargs: %s" % list(kw))
-
- if right is None and cbook.iterable(left):
- left, right = left
-
- self._process_unit_info(xdata=(left, right))
- left = self._validate_converted_limits(left, self.convert_xunits)
- right = self._validate_converted_limits(right, self.convert_xunits)
-
- old_left, old_right = self.get_xlim()
- if left is None:
- left = old_left
- if right is None:
- right = old_right
-
- if left == right:
- warnings.warn(('Attempting to set identical left==right results\n'
- 'in singular transformations; automatically expanding.\n'
- 'left=%s, right=%s') % (left, right))
- left, right = mtransforms.nonsingular(left, right, increasing=False)
- left, right = self.xaxis.limit_range_for_scale(left, right)
- self.xy_viewLim.intervalx = (left, right)
-
- if auto is not None:
- self._autoscaleXon = bool(auto)
-
- if emit:
- self.callbacks.process('xlim_changed', self)
- # Call all of the other x-axes that are shared with this one
- for other in self._shared_x_axes.get_siblings(self):
- if other is not self:
- other.set_xlim(self.xy_viewLim.intervalx,
- emit=False, auto=auto)
- if (other.figure != self.figure and
- other.figure.canvas is not None):
- other.figure.canvas.draw_idle()
- self.stale = True
- return left, right
- set_xlim = set_xlim3d
-
- def set_ylim3d(self, bottom=None, top=None, emit=True, auto=False, **kw):
- """
- Set 3D y limits.
-
- See :meth:`matplotlib.axes.Axes.set_ylim` for full documentation.
-
- """
- if 'ymin' in kw:
- bottom = kw.pop('ymin')
- if 'ymax' in kw:
- top = kw.pop('ymax')
- if kw:
- raise ValueError("unrecognized kwargs: %s" % list(kw))
-
- if top is None and cbook.iterable(bottom):
- bottom, top = bottom
-
- self._process_unit_info(ydata=(bottom, top))
- bottom = self._validate_converted_limits(bottom, self.convert_yunits)
- top = self._validate_converted_limits(top, self.convert_yunits)
-
- old_bottom, old_top = self.get_ylim()
- if bottom is None:
- bottom = old_bottom
- if top is None:
- top = old_top
-
- if top == bottom:
- warnings.warn(('Attempting to set identical bottom==top results\n'
- 'in singular transformations; automatically expanding.\n'
- 'bottom=%s, top=%s') % (bottom, top))
- bottom, top = mtransforms.nonsingular(bottom, top, increasing=False)
- bottom, top = self.yaxis.limit_range_for_scale(bottom, top)
- self.xy_viewLim.intervaly = (bottom, top)
-
- if auto is not None:
- self._autoscaleYon = bool(auto)
-
- if emit:
- self.callbacks.process('ylim_changed', self)
- # Call all of the other y-axes that are shared with this one
- for other in self._shared_y_axes.get_siblings(self):
- if other is not self:
- other.set_ylim(self.xy_viewLim.intervaly,
- emit=False, auto=auto)
- if (other.figure != self.figure and
- other.figure.canvas is not None):
- other.figure.canvas.draw_idle()
- self.stale = True
- return bottom, top
- set_ylim = set_ylim3d
-
- def set_zlim3d(self, bottom=None, top=None, emit=True, auto=False, **kw):
- """
- Set 3D z limits.
-
- See :meth:`matplotlib.axes.Axes.set_ylim` for full documentation
-
- """
- if 'zmin' in kw:
- bottom = kw.pop('zmin')
- if 'zmax' in kw:
- top = kw.pop('zmax')
- if kw:
- raise ValueError("unrecognized kwargs: %s" % list(kw))
-
- if top is None and cbook.iterable(bottom):
- bottom, top = bottom
-
- self._process_unit_info(zdata=(bottom, top))
- bottom = self._validate_converted_limits(bottom, self.convert_zunits)
- top = self._validate_converted_limits(top, self.convert_zunits)
-
- old_bottom, old_top = self.get_zlim()
- if bottom is None:
- bottom = old_bottom
- if top is None:
- top = old_top
-
- if top == bottom:
- warnings.warn(('Attempting to set identical bottom==top results\n'
- 'in singular transformations; automatically expanding.\n'
- 'bottom=%s, top=%s') % (bottom, top))
- bottom, top = mtransforms.nonsingular(bottom, top, increasing=False)
- bottom, top = self.zaxis.limit_range_for_scale(bottom, top)
- self.zz_viewLim.intervalx = (bottom, top)
-
- if auto is not None:
- self._autoscaleZon = bool(auto)
-
- if emit:
- self.callbacks.process('zlim_changed', self)
- # Call all of the other y-axes that are shared with this one
- for other in self._shared_z_axes.get_siblings(self):
- if other is not self:
- other.set_zlim(self.zz_viewLim.intervalx,
- emit=False, auto=auto)
- if (other.figure != self.figure and
- other.figure.canvas is not None):
- other.figure.canvas.draw_idle()
- self.stale = True
- return bottom, top
- set_zlim = set_zlim3d
-
- def get_xlim3d(self):
- return tuple(self.xy_viewLim.intervalx)
- get_xlim3d.__doc__ = maxes.Axes.get_xlim.__doc__
- get_xlim = get_xlim3d
- if get_xlim.__doc__ is not None:
- get_xlim.__doc__ += """
- .. versionchanged :: 1.1.0
- This function now correctly refers to the 3D x-limits
- """
-
- def get_ylim3d(self):
- return tuple(self.xy_viewLim.intervaly)
- get_ylim3d.__doc__ = maxes.Axes.get_ylim.__doc__
- get_ylim = get_ylim3d
- if get_ylim.__doc__ is not None:
- get_ylim.__doc__ += """
- .. versionchanged :: 1.1.0
- This function now correctly refers to the 3D y-limits.
- """
-
- def get_zlim3d(self):
- '''Get 3D z limits.'''
- return tuple(self.zz_viewLim.intervalx)
- get_zlim = get_zlim3d
-
- def get_zscale(self):
- """
- Return the zaxis scale string %s
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """ % (", ".join(mscale.get_scale_names()))
- return self.zaxis.get_scale()
-
- # We need to slightly redefine these to pass scalez=False
- # to their calls of autoscale_view.
- def set_xscale(self, value, **kwargs):
- self.xaxis._set_scale(value, **kwargs)
- self.autoscale_view(scaley=False, scalez=False)
- self._update_transScale()
- if maxes.Axes.set_xscale.__doc__ is not None:
- set_xscale.__doc__ = maxes.Axes.set_xscale.__doc__ + """
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
-
- def set_yscale(self, value, **kwargs):
- self.yaxis._set_scale(value, **kwargs)
- self.autoscale_view(scalex=False, scalez=False)
- self._update_transScale()
- self.stale = True
- if maxes.Axes.set_yscale.__doc__ is not None:
- set_yscale.__doc__ = maxes.Axes.set_yscale.__doc__ + """
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
-
- @docstring.dedent_interpd
- def set_zscale(self, value, **kwargs):
- """
- Set the scaling of the z-axis: %(scale)s
-
- ACCEPTS: [%(scale)s]
-
- Different kwargs are accepted, depending on the scale:
- %(scale_docs)s
-
- .. note ::
- Currently, Axes3D objects only supports linear scales.
- Other scales may or may not work, and support for these
- is improving with each release.
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
- self.zaxis._set_scale(value, **kwargs)
- self.autoscale_view(scalex=False, scaley=False)
- self._update_transScale()
- self.stale = True
-
- def set_zticks(self, *args, **kwargs):
- """
- Set z-axis tick locations.
- See :meth:`matplotlib.axes.Axes.set_yticks` for more details.
-
- .. note::
- Minor ticks are not supported.
-
- .. versionadded:: 1.1.0
- """
- return self.zaxis.set_ticks(*args, **kwargs)
-
- def get_zticks(self, minor=False):
- """
- Return the z ticks as a list of locations
- See :meth:`matplotlib.axes.Axes.get_yticks` for more details.
-
- .. note::
- Minor ticks are not supported.
-
- .. versionadded:: 1.1.0
- """
- return self.zaxis.get_ticklocs(minor=minor)
-
- def get_zmajorticklabels(self):
- """
- Get the ztick labels as a list of Text instances
-
- .. versionadded :: 1.1.0
- """
- return cbook.silent_list('Text zticklabel',
- self.zaxis.get_majorticklabels())
-
- def get_zminorticklabels(self):
- """
- Get the ztick labels as a list of Text instances
-
- .. note::
- Minor ticks are not supported. This function was added
- only for completeness.
-
- .. versionadded :: 1.1.0
- """
- return cbook.silent_list('Text zticklabel',
- self.zaxis.get_minorticklabels())
-
- def set_zticklabels(self, *args, **kwargs):
- """
- Set z-axis tick labels.
- See :meth:`matplotlib.axes.Axes.set_yticklabels` for more details.
-
- .. note::
- Minor ticks are not supported by Axes3D objects.
-
- .. versionadded:: 1.1.0
- """
- return self.zaxis.set_ticklabels(*args, **kwargs)
-
- def get_zticklabels(self, minor=False):
- """
- Get ztick labels as a list of Text instances.
- See :meth:`matplotlib.axes.Axes.get_yticklabels` for more details.
-
- .. note::
- Minor ticks are not supported.
-
- .. versionadded:: 1.1.0
- """
- return cbook.silent_list('Text zticklabel',
- self.zaxis.get_ticklabels(minor=minor))
-
- def zaxis_date(self, tz=None):
- """
- Sets up z-axis ticks and labels that treat the z data as dates.
-
- *tz* is a timezone string or :class:`tzinfo` instance.
- Defaults to rc value.
-
- .. note::
- This function is merely provided for completeness.
- Axes3D objects do not officially support dates for ticks,
- and so this may or may not work as expected.
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
- self.zaxis.axis_date(tz)
-
- def get_zticklines(self):
- """
- Get ztick lines as a list of Line2D instances.
- Note that this function is provided merely for completeness.
- These lines are re-calculated as the display changes.
-
- .. versionadded:: 1.1.0
- """
- return self.zaxis.get_ticklines()
-
- def clabel(self, *args, **kwargs):
- """
- This function is currently not implemented for 3D axes.
- Returns *None*.
- """
- return None
-
- def view_init(self, elev=None, azim=None):
- """
- Set the elevation and azimuth of the axes.
-
- This can be used to rotate the axes programmatically.
-
- 'elev' stores the elevation angle in the z plane.
- 'azim' stores the azimuth angle in the x,y plane.
-
- if elev or azim are None (default), then the initial value
- is used which was specified in the :class:`Axes3D` constructor.
- """
-
- self.dist = 10
-
- if elev is None:
- self.elev = self.initial_elev
- else:
- self.elev = elev
-
- if azim is None:
- self.azim = self.initial_azim
- else:
- self.azim = azim
-
- def set_proj_type(self, proj_type):
- """
- Set the projection type.
-
- Parameters
- ----------
- proj_type : str
- Type of projection, accepts 'persp' and 'ortho'.
-
- """
- if proj_type == 'persp':
- self._projection = proj3d.persp_transformation
- elif proj_type == 'ortho':
- self._projection = proj3d.ortho_transformation
- else:
- raise ValueError("unrecognized projection: %s" % proj_type)
-
- def get_proj(self):
- """
- Create the projection matrix from the current viewing position.
-
- elev stores the elevation angle in the z plane
- azim stores the azimuth angle in the x,y plane
-
- dist is the distance of the eye viewing point from the object
- point.
-
- """
- relev, razim = np.pi * self.elev/180, np.pi * self.azim/180
-
- xmin, xmax = self.get_xlim3d()
- ymin, ymax = self.get_ylim3d()
- zmin, zmax = self.get_zlim3d()
-
- # transform to uniform world coordinates 0-1.0,0-1.0,0-1.0
- worldM = proj3d.world_transformation(xmin, xmax,
- ymin, ymax,
- zmin, zmax)
-
- # look into the middle of the new coordinates
- R = np.array([0.5, 0.5, 0.5])
-
- xp = R[0] + np.cos(razim) * np.cos(relev) * self.dist
- yp = R[1] + np.sin(razim) * np.cos(relev) * self.dist
- zp = R[2] + np.sin(relev) * self.dist
- E = np.array((xp, yp, zp))
-
- self.eye = E
- self.vvec = R - E
- self.vvec = self.vvec / proj3d.mod(self.vvec)
-
- if abs(relev) > np.pi/2:
- # upside down
- V = np.array((0, 0, -1))
- else:
- V = np.array((0, 0, 1))
- zfront, zback = -self.dist, self.dist
-
- viewM = proj3d.view_transformation(E, R, V)
- projM = self._projection(zfront, zback)
- M0 = np.dot(viewM, worldM)
- M = np.dot(projM, M0)
- return M
-
- def mouse_init(self, rotate_btn=1, zoom_btn=3):
- """Initializes mouse button callbacks to enable 3D rotation of
- the axes. Also optionally sets the mouse buttons for 3D rotation
- and zooming.
-
- ============ =======================================================
- Argument Description
- ============ =======================================================
- *rotate_btn* The integer or list of integers specifying which mouse
- button or buttons to use for 3D rotation of the axes.
- Default = 1.
-
- *zoom_btn* The integer or list of integers specifying which mouse
- button or buttons to use to zoom the 3D axes.
- Default = 3.
- ============ =======================================================
-
- """
- self.button_pressed = None
- canv = self.figure.canvas
- if canv is not None:
- c1 = canv.mpl_connect('motion_notify_event', self._on_move)
- c2 = canv.mpl_connect('button_press_event', self._button_press)
- c3 = canv.mpl_connect('button_release_event', self._button_release)
- self._cids = [c1, c2, c3]
- else:
- warnings.warn(
- "Axes3D.figure.canvas is 'None', mouse rotation disabled. "
- "Set canvas then call Axes3D.mouse_init().")
-
- # coerce scalars into array-like, then convert into
- # a regular list to avoid comparisons against None
- # which breaks in recent versions of numpy.
- self._rotate_btn = np.atleast_1d(rotate_btn).tolist()
- self._zoom_btn = np.atleast_1d(zoom_btn).tolist()
-
- def can_zoom(self):
- """
- Return *True* if this axes supports the zoom box button functionality.
-
- 3D axes objects do not use the zoom box button.
- """
- return False
-
- def can_pan(self):
- """
- Return *True* if this axes supports the pan/zoom button functionality.
-
- 3D axes objects do not use the pan/zoom button.
- """
- return False
-
- def cla(self):
- """
- Clear axes
- """
- # Disabling mouse interaction might have been needed a long
- # time ago, but I can't find a reason for it now - BVR (2012-03)
- #self.disable_mouse_rotation()
- super(Axes3D, self).cla()
- self.zaxis.cla()
-
- if self._sharez is not None:
- self.zaxis.major = self._sharez.zaxis.major
- self.zaxis.minor = self._sharez.zaxis.minor
- z0, z1 = self._sharez.get_zlim()
- self.set_zlim(z0, z1, emit=False, auto=None)
- self.zaxis._set_scale(self._sharez.zaxis.get_scale())
- else:
- self.zaxis._set_scale('linear')
- try:
- self.set_zlim(0, 1)
- except TypeError:
- pass
-
- self._autoscaleZon = True
- self._zmargin = 0
-
- self.grid(rcParams['axes3d.grid'])
-
- def disable_mouse_rotation(self):
- """Disable mouse button callbacks.
- """
- # Disconnect the various events we set.
- for cid in self._cids:
- self.figure.canvas.mpl_disconnect(cid)
-
- self._cids = []
-
- def _button_press(self, event):
- if event.inaxes == self:
- self.button_pressed = event.button
- self.sx, self.sy = event.xdata, event.ydata
-
- def _button_release(self, event):
- self.button_pressed = None
-
- def format_zdata(self, z):
- """
- Return *z* string formatted. This function will use the
- :attr:`fmt_zdata` attribute if it is callable, else will fall
- back on the zaxis major formatter
- """
- try: return self.fmt_zdata(z)
- except (AttributeError, TypeError):
- func = self.zaxis.get_major_formatter().format_data_short
- val = func(z)
- return val
-
- def format_coord(self, xd, yd):
- """
- Given the 2D view coordinates attempt to guess a 3D coordinate.
- Looks for the nearest edge to the point and then assumes that
- the point is at the same z location as the nearest point on the edge.
- """
-
- if self.M is None:
- return ''
-
- if self.button_pressed in self._rotate_btn:
- return 'azimuth=%d deg, elevation=%d deg ' % (self.azim, self.elev)
- # ignore xd and yd and display angles instead
-
- # nearest edge
- p0, p1 = min(self.tunit_edges(),
- key=lambda edge: proj3d.line2d_seg_dist(
- edge[0], edge[1], (xd, yd)))
-
- # scale the z value to match
- x0, y0, z0 = p0
- x1, y1, z1 = p1
- d0 = np.hypot(x0-xd, y0-yd)
- d1 = np.hypot(x1-xd, y1-yd)
- dt = d0+d1
- z = d1/dt * z0 + d0/dt * z1
-
- x, y, z = proj3d.inv_transform(xd, yd, z, self.M)
-
- xs = self.format_xdata(x)
- ys = self.format_ydata(y)
- zs = self.format_zdata(z)
- return 'x=%s, y=%s, z=%s' % (xs, ys, zs)
-
- def _on_move(self, event):
- """Mouse moving
-
- button-1 rotates by default. Can be set explicitly in mouse_init().
- button-3 zooms by default. Can be set explicitly in mouse_init().
- """
-
- if not self.button_pressed:
- return
-
- if self.M is None:
- return
-
- x, y = event.xdata, event.ydata
- # In case the mouse is out of bounds.
- if x is None:
- return
-
- dx, dy = x - self.sx, y - self.sy
- w = self._pseudo_w
- h = self._pseudo_h
- self.sx, self.sy = x, y
-
- # Rotation
- if self.button_pressed in self._rotate_btn:
- # rotate viewing point
- # get the x and y pixel coords
- if dx == 0 and dy == 0:
- return
- self.elev = art3d.norm_angle(self.elev - (dy/h)*180)
- self.azim = art3d.norm_angle(self.azim - (dx/w)*180)
- self.get_proj()
- self.stale = True
- self.figure.canvas.draw_idle()
-
-# elif self.button_pressed == 2:
- # pan view
- # project xv,yv,zv -> xw,yw,zw
- # pan
-# pass
-
- # Zoom
- elif self.button_pressed in self._zoom_btn:
- # zoom view
- # hmmm..this needs some help from clipping....
- minx, maxx, miny, maxy, minz, maxz = self.get_w_lims()
- df = 1-((h - dy)/h)
- dx = (maxx-minx)*df
- dy = (maxy-miny)*df
- dz = (maxz-minz)*df
- self.set_xlim3d(minx - dx, maxx + dx)
- self.set_ylim3d(miny - dy, maxy + dy)
- self.set_zlim3d(minz - dz, maxz + dz)
- self.get_proj()
- self.figure.canvas.draw_idle()
-
- def set_zlabel(self, zlabel, fontdict=None, labelpad=None, **kwargs):
- '''
- Set zlabel. See doc for :meth:`set_ylabel` for description.
-
- '''
- if labelpad is not None : self.zaxis.labelpad = labelpad
- return self.zaxis.set_label_text(zlabel, fontdict, **kwargs)
-
- def get_zlabel(self):
- """
- Get the z-label text string.
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
- label = self.zaxis.get_label()
- return label.get_text()
-
- #### Axes rectangle characteristics
-
- def get_frame_on(self):
- """
- Get whether the 3D axes panels are drawn.
-
- .. versionadded :: 1.1.0
- """
- return self._frameon
-
- def set_frame_on(self, b):
- """
- Set whether the 3D axes panels are drawn.
-
- .. versionadded :: 1.1.0
-
- Parameters
- ----------
- b : bool
- .. ACCEPTS: bool
- """
- self._frameon = bool(b)
- self.stale = True
-
- def get_axisbelow(self):
- """
- Get whether axis below is true or not.
-
- For axes3d objects, this will always be *True*
-
- .. versionadded :: 1.1.0
- This function was added for completeness.
- """
- return True
-
- def set_axisbelow(self, b):
- """
- Set whether axis ticks and gridlines are above or below most artists.
-
- For axes3d objects, this will ignore any settings and just use *True*
-
- .. versionadded :: 1.1.0
- This function was added for completeness.
-
- Parameters
- ----------
- b : bool
- .. ACCEPTS: bool
- """
- self._axisbelow = True
- self.stale = True
-
- def grid(self, b=True, **kwargs):
- '''
- Set / unset 3D grid.
-
- .. note::
-
- Currently, this function does not behave the same as
- :meth:`matplotlib.axes.Axes.grid`, but it is intended to
- eventually support that behavior.
-
- .. versionchanged :: 1.1.0
- This function was changed, but not tested. Please report any bugs.
- '''
- # TODO: Operate on each axes separately
- if len(kwargs):
- b = True
- self._draw_grid = cbook._string_to_bool(b)
- self.stale = True
-
- def ticklabel_format(self, **kwargs):
- """
- Convenience method for manipulating the ScalarFormatter
- used by default for linear axes in Axed3D objects.
-
- See :meth:`matplotlib.axes.Axes.ticklabel_format` for full
- documentation. Note that this version applies to all three
- axes of the Axes3D object. Therefore, the *axis* argument
- will also accept a value of 'z' and the value of 'both' will
- apply to all three axes.
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
- style = kwargs.pop('style', '').lower()
- scilimits = kwargs.pop('scilimits', None)
- useOffset = kwargs.pop('useOffset', None)
- axis = kwargs.pop('axis', 'both').lower()
- if scilimits is not None:
- try:
- m, n = scilimits
- m+n+1 # check that both are numbers
- except (ValueError, TypeError):
- raise ValueError("scilimits must be a sequence of 2 integers")
- if style[:3] == 'sci':
- sb = True
- elif style in ['plain', 'comma']:
- sb = False
- if style == 'plain':
- cb = False
- else:
- cb = True
- raise NotImplementedError("comma style remains to be added")
- elif style == '':
- sb = None
- else:
- raise ValueError("%s is not a valid style value")
- try:
- if sb is not None:
- if axis in ['both', 'z']:
- self.xaxis.major.formatter.set_scientific(sb)
- if axis in ['both', 'y']:
- self.yaxis.major.formatter.set_scientific(sb)
- if axis in ['both', 'z'] :
- self.zaxis.major.formatter.set_scientific(sb)
- if scilimits is not None:
- if axis in ['both', 'x']:
- self.xaxis.major.formatter.set_powerlimits(scilimits)
- if axis in ['both', 'y']:
- self.yaxis.major.formatter.set_powerlimits(scilimits)
- if axis in ['both', 'z']:
- self.zaxis.major.formatter.set_powerlimits(scilimits)
- if useOffset is not None:
- if axis in ['both', 'x']:
- self.xaxis.major.formatter.set_useOffset(useOffset)
- if axis in ['both', 'y']:
- self.yaxis.major.formatter.set_useOffset(useOffset)
- if axis in ['both', 'z']:
- self.zaxis.major.formatter.set_useOffset(useOffset)
- except AttributeError:
- raise AttributeError(
- "This method only works with the ScalarFormatter.")
-
- def locator_params(self, axis='both', tight=None, **kwargs):
- """
- Convenience method for controlling tick locators.
-
- See :meth:`matplotlib.axes.Axes.locator_params` for full
- documentation Note that this is for Axes3D objects,
- therefore, setting *axis* to 'both' will result in the
- parameters being set for all three axes. Also, *axis*
- can also take a value of 'z' to apply parameters to the
- z axis.
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
- _x = axis in ['x', 'both']
- _y = axis in ['y', 'both']
- _z = axis in ['z', 'both']
- if _x:
- self.xaxis.get_major_locator().set_params(**kwargs)
- if _y:
- self.yaxis.get_major_locator().set_params(**kwargs)
- if _z:
- self.zaxis.get_major_locator().set_params(**kwargs)
- self.autoscale_view(tight=tight, scalex=_x, scaley=_y, scalez=_z)
-
- def tick_params(self, axis='both', **kwargs):
- """
- Convenience method for changing the appearance of ticks and
- tick labels.
-
- See :meth:`matplotlib.axes.Axes.tick_params` for more complete
- documentation.
-
- The only difference is that setting *axis* to 'both' will
- mean that the settings are applied to all three axes. Also,
- the *axis* parameter also accepts a value of 'z', which
- would mean to apply to only the z-axis.
-
- Also, because of how Axes3D objects are drawn very differently
- from regular 2D axes, some of these settings may have
- ambiguous meaning. For simplicity, the 'z' axis will
- accept settings as if it was like the 'y' axis.
-
- .. note::
- While this function is currently implemented, the core part
- of the Axes3D object may ignore some of these settings.
- Future releases will fix this. Priority will be given to
- those who file bugs.
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
- super(Axes3D, self).tick_params(axis, **kwargs)
- if axis in ['z', 'both'] :
- zkw = dict(kwargs)
- zkw.pop('top', None)
- zkw.pop('bottom', None)
- zkw.pop('labeltop', None)
- zkw.pop('labelbottom', None)
- self.zaxis.set_tick_params(**zkw)
-
- ### data limits, ticks, tick labels, and formatting
-
- def invert_zaxis(self):
- """
- Invert the z-axis.
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
- bottom, top = self.get_zlim()
- self.set_zlim(top, bottom, auto=None)
-
- def zaxis_inverted(self):
- '''
- Returns True if the z-axis is inverted.
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- '''
- bottom, top = self.get_zlim()
- return top < bottom
-
- def get_zbound(self):
- """
- Returns the z-axis numerical bounds where::
-
- lowerBound < upperBound
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
- bottom, top = self.get_zlim()
- if bottom < top:
- return bottom, top
- else:
- return top, bottom
-
- def set_zbound(self, lower=None, upper=None):
- """
- Set the lower and upper numerical bounds of the z-axis.
- This method will honor axes inversion regardless of parameter order.
- It will not change the :attr:`_autoscaleZon` attribute.
-
- .. versionadded :: 1.1.0
- This function was added, but not tested. Please report any bugs.
- """
- if upper is None and cbook.iterable(lower):
- lower,upper = lower
-
- old_lower,old_upper = self.get_zbound()
-
- if lower is None: lower = old_lower
- if upper is None: upper = old_upper
-
- if self.zaxis_inverted():
- if lower < upper:
- self.set_zlim(upper, lower, auto=None)
- else:
- self.set_zlim(lower, upper, auto=None)
- else :
- if lower < upper:
- self.set_zlim(lower, upper, auto=None)
- else :
- self.set_zlim(upper, lower, auto=None)
-
- def text(self, x, y, z, s, zdir=None, **kwargs):
- '''
- Add text to the plot. kwargs will be passed on to Axes.text,
- except for the `zdir` keyword, which sets the direction to be
- used as the z direction.
- '''
- text = super(Axes3D, self).text(x, y, s, **kwargs)
- art3d.text_2d_to_3d(text, z, zdir)
- return text
-
- text3D = text
- text2D = Axes.text
-
- def plot(self, xs, ys, *args, **kwargs):
- '''
- Plot 2D or 3D data.
-
- ========== ================================================
- Argument Description
- ========== ================================================
- *xs*, *ys* x, y coordinates of vertices
-
- *zs* z value(s), either one for all points or one for
- each point.
- *zdir* Which direction to use as z ('x', 'y' or 'z')
- when plotting a 2D set.
- ========== ================================================
-
- Other arguments are passed on to
- :func:`~matplotlib.axes.Axes.plot`
- '''
- had_data = self.has_data()
-
- # `zs` can be passed positionally or as keyword; checking whether
- # args[0] is a string matches the behavior of 2D `plot` (via
- # `_process_plot_var_args`).
- if args and not isinstance(args[0], six.string_types):
- zs = args[0]
- args = args[1:]
- if 'zs' in kwargs:
- raise TypeError("plot() for multiple values for argument 'z'")
- else:
- zs = kwargs.pop('zs', 0)
- zdir = kwargs.pop('zdir', 'z')
-
- # Match length
- zs = _backports.broadcast_to(zs, len(xs))
-
- lines = super(Axes3D, self).plot(xs, ys, *args, **kwargs)
- for line in lines:
- art3d.line_2d_to_3d(line, zs=zs, zdir=zdir)
-
- xs, ys, zs = art3d.juggle_axes(xs, ys, zs, zdir)
- self.auto_scale_xyz(xs, ys, zs, had_data)
- return lines
-
- plot3D = plot
-
- def plot_surface(self, X, Y, Z, *args, **kwargs):
- """
- Create a surface plot.
-
- By default it will be colored in shades of a solid color, but it also
- supports color mapping by supplying the *cmap* argument.
-
- .. note::
-
- The *rcount* and *ccount* kwargs, which both default to 50,
- determine the maximum number of samples used in each direction. If
- the input data is larger, it will be downsampled (by slicing) to
- these numbers of points.
-
- Parameters
- ----------
- X, Y, Z : 2d arrays
- Data values.
-
- rcount, ccount : int
- Maximum number of samples used in each direction. If the input
- data is larger, it will be downsampled (by slicing) to these
- numbers of points. Defaults to 50.
-
- .. versionadded:: 2.0
-
- rstride, cstride : int
- Downsampling stride in each direction. These arguments are
- mutually exclusive with *rcount* and *ccount*. If only one of
- *rstride* or *cstride* is set, the other defaults to 10.
-
- 'classic' mode uses a default of ``rstride = cstride = 10`` instead
- of the new default of ``rcount = ccount = 50``.
-
- color : color-like
- Color of the surface patches.
-
- cmap : Colormap
- Colormap of the surface patches.
-
- facecolors : array-like of colors.
- Colors of each individual patch.
-
- norm : Normalize
- Normalization for the colormap.
-
- vmin, vmax : float
- Bounds for the normalization.
-
- shade : bool
- Whether to shade the face colors.
-
- **kwargs :
- Other arguments are forwarded to `.Poly3DCollection`.
- """
-
- had_data = self.has_data()
-
- if Z.ndim != 2:
- raise ValueError("Argument Z must be 2-dimensional.")
- # TODO: Support masked arrays
- X, Y, Z = np.broadcast_arrays(X, Y, Z)
- rows, cols = Z.shape
-
- has_stride = 'rstride' in kwargs or 'cstride' in kwargs
- has_count = 'rcount' in kwargs or 'ccount' in kwargs
-
- if has_stride and has_count:
- raise ValueError("Cannot specify both stride and count arguments")
-
- rstride = kwargs.pop('rstride', 10)
- cstride = kwargs.pop('cstride', 10)
- rcount = kwargs.pop('rcount', 50)
- ccount = kwargs.pop('ccount', 50)
-
- if rcParams['_internal.classic_mode']:
- # Strides have priority over counts in classic mode.
- # So, only compute strides from counts
- # if counts were explicitly given
- if has_count:
- rstride = int(max(np.ceil(rows / rcount), 1))
- cstride = int(max(np.ceil(cols / ccount), 1))
- else:
- # If the strides are provided then it has priority.
- # Otherwise, compute the strides from the counts.
- if not has_stride:
- rstride = int(max(np.ceil(rows / rcount), 1))
- cstride = int(max(np.ceil(cols / ccount), 1))
-
- if 'facecolors' in kwargs:
- fcolors = kwargs.pop('facecolors')
- else:
- color = kwargs.pop('color', None)
- if color is None:
- color = self._get_lines.get_next_color()
- color = np.array(mcolors.to_rgba(color))
- fcolors = None
-
- cmap = kwargs.get('cmap', None)
- norm = kwargs.pop('norm', None)
- vmin = kwargs.pop('vmin', None)
- vmax = kwargs.pop('vmax', None)
- linewidth = kwargs.get('linewidth', None)
- shade = kwargs.pop('shade', cmap is None)
- lightsource = kwargs.pop('lightsource', None)
-
- # Shade the data
- if shade and cmap is not None and fcolors is not None:
- fcolors = self._shade_colors_lightsource(Z, cmap, lightsource)
-
- polys = []
- # Only need these vectors to shade if there is no cmap
- if cmap is None and shade :
- totpts = int(np.ceil((rows - 1) / rstride) *
- np.ceil((cols - 1) / cstride))
- v1 = np.empty((totpts, 3))
- v2 = np.empty((totpts, 3))
- # This indexes the vertex points
- which_pt = 0
-
-
- #colset contains the data for coloring: either average z or the facecolor
- colset = []
- for rs in xrange(0, rows-1, rstride):
- for cs in xrange(0, cols-1, cstride):
- ps = []
- for a in (X, Y, Z):
- ztop = a[rs,cs:min(cols, cs+cstride+1)]
- zleft = a[rs+1:min(rows, rs+rstride+1),
- min(cols-1, cs+cstride)]
- zbase = a[min(rows-1, rs+rstride), cs:min(cols, cs+cstride+1):][::-1]
- zright = a[rs:min(rows-1, rs+rstride):, cs][::-1]
- z = np.concatenate((ztop, zleft, zbase, zright))
- ps.append(z)
-
- # The construction leaves the array with duplicate points, which
- # are removed here.
- ps = list(zip(*ps))
- lastp = np.array([])
- ps2 = [ps[0]] + [ps[i] for i in xrange(1, len(ps)) if ps[i] != ps[i-1]]
- avgzsum = sum(p[2] for p in ps2)
- polys.append(ps2)
-
- if fcolors is not None:
- colset.append(fcolors[rs][cs])
- else:
- colset.append(avgzsum / len(ps2))
-
- # Only need vectors to shade if no cmap
- if cmap is None and shade:
- i1, i2, i3 = 0, int(len(ps2)/3), int(2*len(ps2)/3)
- v1[which_pt] = np.array(ps2[i1]) - np.array(ps2[i2])
- v2[which_pt] = np.array(ps2[i2]) - np.array(ps2[i3])
- which_pt += 1
- if cmap is None and shade:
- normals = np.cross(v1, v2)
- else :
- normals = []
-
- polyc = art3d.Poly3DCollection(polys, *args, **kwargs)
-
- if fcolors is not None:
- if shade:
- colset = self._shade_colors(colset, normals)
- polyc.set_facecolors(colset)
- polyc.set_edgecolors(colset)
- elif cmap:
- colset = np.array(colset)
- polyc.set_array(colset)
- if vmin is not None or vmax is not None:
- polyc.set_clim(vmin, vmax)
- if norm is not None:
- polyc.set_norm(norm)
- else:
- if shade:
- colset = self._shade_colors(color, normals)
- else:
- colset = color
- polyc.set_facecolors(colset)
-
- self.add_collection(polyc)
- self.auto_scale_xyz(X, Y, Z, had_data)
-
- return polyc
-
- def _generate_normals(self, polygons):
- '''
- Generate normals for polygons by using the first three points.
- This normal of course might not make sense for polygons with
- more than three points not lying in a plane.
- '''
-
- normals = []
- for verts in polygons:
- v1 = np.array(verts[0]) - np.array(verts[1])
- v2 = np.array(verts[2]) - np.array(verts[0])
- normals.append(np.cross(v1, v2))
- return normals
-
- def _shade_colors(self, color, normals):
- '''
- Shade *color* using normal vectors given by *normals*.
- *color* can also be an array of the same length as *normals*.
- '''
-
- shade = np.array([np.dot(n / proj3d.mod(n), [-1, -1, 0.5])
- if proj3d.mod(n) else np.nan
- for n in normals])
- mask = ~np.isnan(shade)
-
- if len(shade[mask]) > 0:
- norm = Normalize(min(shade[mask]), max(shade[mask]))
- shade[~mask] = min(shade[mask])
- color = mcolors.to_rgba_array(color)
- # shape of color should be (M, 4) (where M is number of faces)
- # shape of shade should be (M,)
- # colors should have final shape of (M, 4)
- alpha = color[:, 3]
- colors = (0.5 + norm(shade)[:, np.newaxis] * 0.5) * color
- colors[:, 3] = alpha
- else:
- colors = np.asanyarray(color).copy()
-
- return colors
-
- def _shade_colors_lightsource(self, data, cmap, lightsource):
- if lightsource is None:
- lightsource = LightSource(azdeg=135, altdeg=55)
- return lightsource.shade(data, cmap)
-
- def plot_wireframe(self, X, Y, Z, *args, **kwargs):
- """
- Plot a 3D wireframe.
-
- .. note::
-
- The *rcount* and *ccount* kwargs, which both default to 50,
- determine the maximum number of samples used in each direction. If
- the input data is larger, it will be downsampled (by slicing) to
- these numbers of points.
-
- Parameters
- ----------
- X, Y, Z : 2d arrays
- Data values.
-
- rcount, ccount : int
- Maximum number of samples used in each direction. If the input
- data is larger, it will be downsampled (by slicing) to these
- numbers of points. Setting a count to zero causes the data to be
- not sampled in the corresponding direction, producing a 3D line
- plot rather than a wireframe plot. Defaults to 50.
-
- .. versionadded:: 2.0
-
- rstride, cstride : int
- Downsampling stride in each direction. These arguments are
- mutually exclusive with *rcount* and *ccount*. If only one of
- *rstride* or *cstride* is set, the other defaults to 1. Setting a
- stride to zero causes the data to be not sampled in the
- corresponding direction, producing a 3D line plot rather than a
- wireframe plot.
-
- 'classic' mode uses a default of ``rstride = cstride = 1`` instead
- of the new default of ``rcount = ccount = 50``.
-
- **kwargs :
- Other arguments are forwarded to `.Line3DCollection`.
- """
-
- had_data = self.has_data()
- if Z.ndim != 2:
- raise ValueError("Argument Z must be 2-dimensional.")
- # FIXME: Support masked arrays
- X, Y, Z = np.broadcast_arrays(X, Y, Z)
- rows, cols = Z.shape
-
- has_stride = 'rstride' in kwargs or 'cstride' in kwargs
- has_count = 'rcount' in kwargs or 'ccount' in kwargs
-
- if has_stride and has_count:
- raise ValueError("Cannot specify both stride and count arguments")
-
- rstride = kwargs.pop('rstride', 1)
- cstride = kwargs.pop('cstride', 1)
- rcount = kwargs.pop('rcount', 50)
- ccount = kwargs.pop('ccount', 50)
-
- if rcParams['_internal.classic_mode']:
- # Strides have priority over counts in classic mode.
- # So, only compute strides from counts
- # if counts were explicitly given
- if has_count:
- rstride = int(max(np.ceil(rows / rcount), 1)) if rcount else 0
- cstride = int(max(np.ceil(cols / ccount), 1)) if ccount else 0
- else:
- # If the strides are provided then it has priority.
- # Otherwise, compute the strides from the counts.
- if not has_stride:
- rstride = int(max(np.ceil(rows / rcount), 1)) if rcount else 0
- cstride = int(max(np.ceil(cols / ccount), 1)) if ccount else 0
-
- # We want two sets of lines, one running along the "rows" of
- # Z and another set of lines running along the "columns" of Z.
- # This transpose will make it easy to obtain the columns.
- tX, tY, tZ = np.transpose(X), np.transpose(Y), np.transpose(Z)
-
- if rstride:
- rii = list(xrange(0, rows, rstride))
- # Add the last index only if needed
- if rows > 0 and rii[-1] != (rows - 1):
- rii += [rows-1]
- else:
- rii = []
- if cstride:
- cii = list(xrange(0, cols, cstride))
- # Add the last index only if needed
- if cols > 0 and cii[-1] != (cols - 1):
- cii += [cols-1]
- else:
- cii = []
-
- if rstride == 0 and cstride == 0:
- raise ValueError("Either rstride or cstride must be non zero")
-
- # If the inputs were empty, then just
- # reset everything.
- if Z.size == 0:
- rii = []
- cii = []
-
- xlines = [X[i] for i in rii]
- ylines = [Y[i] for i in rii]
- zlines = [Z[i] for i in rii]
-
- txlines = [tX[i] for i in cii]
- tylines = [tY[i] for i in cii]
- tzlines = [tZ[i] for i in cii]
-
- lines = ([list(zip(xl, yl, zl))
- for xl, yl, zl in zip(xlines, ylines, zlines)]
- + [list(zip(xl, yl, zl))
- for xl, yl, zl in zip(txlines, tylines, tzlines)])
-
- linec = art3d.Line3DCollection(lines, *args, **kwargs)
- self.add_collection(linec)
- self.auto_scale_xyz(X, Y, Z, had_data)
-
- return linec
-
- def plot_trisurf(self, *args, **kwargs):
- """
- ============= ================================================
- Argument Description
- ============= ================================================
- *X*, *Y*, *Z* Data values as 1D arrays
- *color* Color of the surface patches
- *cmap* A colormap for the surface patches.
- *norm* An instance of Normalize to map values to colors
- *vmin* Minimum value to map
- *vmax* Maximum value to map
- *shade* Whether to shade the facecolors
- ============= ================================================
-
- The (optional) triangulation can be specified in one of two ways;
- either::
-
- plot_trisurf(triangulation, ...)
-
- where triangulation is a :class:`~matplotlib.tri.Triangulation`
- object, or::
-
- plot_trisurf(X, Y, ...)
- plot_trisurf(X, Y, triangles, ...)
- plot_trisurf(X, Y, triangles=triangles, ...)
-
- in which case a Triangulation object will be created. See
- :class:`~matplotlib.tri.Triangulation` for a explanation of
- these possibilities.
-
- The remaining arguments are::
-
- plot_trisurf(..., Z)
-
- where *Z* is the array of values to contour, one per point
- in the triangulation.
-
- Other arguments are passed on to
- :class:`~mpl_toolkits.mplot3d.art3d.Poly3DCollection`
-
- **Examples:**
-
- .. plot:: gallery/mplot3d/trisurf3d.py
- .. plot:: gallery/mplot3d/trisurf3d_2.py
-
- .. versionadded:: 1.2.0
- This plotting function was added for the v1.2.0 release.
- """
-
- had_data = self.has_data()
-
- # TODO: Support custom face colours
- color = kwargs.pop('color', None)
- if color is None:
- color = self._get_lines.get_next_color()
- color = np.array(mcolors.to_rgba(color))
-
- cmap = kwargs.get('cmap', None)
- norm = kwargs.pop('norm', None)
- vmin = kwargs.pop('vmin', None)
- vmax = kwargs.pop('vmax', None)
- linewidth = kwargs.get('linewidth', None)
- shade = kwargs.pop('shade', cmap is None)
- lightsource = kwargs.pop('lightsource', None)
-
- tri, args, kwargs = Triangulation.get_from_args_and_kwargs(*args, **kwargs)
- if 'Z' in kwargs:
- z = np.asarray(kwargs.pop('Z'))
- else:
- z = np.asarray(args[0])
- # We do this so Z doesn't get passed as an arg to PolyCollection
- args = args[1:]
-
- triangles = tri.get_masked_triangles()
- xt = tri.x[triangles]
- yt = tri.y[triangles]
- zt = z[triangles]
-
- # verts = np.stack((xt, yt, zt), axis=-1)
- verts = np.concatenate((
- xt[..., np.newaxis], yt[..., np.newaxis], zt[..., np.newaxis]
- ), axis=-1)
-
- polyc = art3d.Poly3DCollection(verts, *args, **kwargs)
-
- if cmap:
- # average over the three points of each triangle
- avg_z = verts[:, :, 2].mean(axis=1)
- polyc.set_array(avg_z)
- if vmin is not None or vmax is not None:
- polyc.set_clim(vmin, vmax)
- if norm is not None:
- polyc.set_norm(norm)
- else:
- if shade:
- v1 = verts[:, 0, :] - verts[:, 1, :]
- v2 = verts[:, 1, :] - verts[:, 2, :]
- normals = np.cross(v1, v2)
- colset = self._shade_colors(color, normals)
- else:
- colset = color
- polyc.set_facecolors(colset)
-
- self.add_collection(polyc)
- self.auto_scale_xyz(tri.x, tri.y, z, had_data)
-
- return polyc
-
- def _3d_extend_contour(self, cset, stride=5):
- '''
- Extend a contour in 3D by creating
- '''
-
- levels = cset.levels
- colls = cset.collections
- dz = (levels[1] - levels[0]) / 2
-
- for z, linec in zip(levels, colls):
- topverts = art3d.paths_to_3d_segments(linec.get_paths(), z - dz)
- botverts = art3d.paths_to_3d_segments(linec.get_paths(), z + dz)
-
- color = linec.get_color()[0]
-
- polyverts = []
- normals = []
- nsteps = np.round(len(topverts[0]) / stride)
- if nsteps <= 1:
- if len(topverts[0]) > 1:
- nsteps = 2
- else:
- continue
-
- stepsize = (len(topverts[0]) - 1) / (nsteps - 1)
- for i in range(int(np.round(nsteps)) - 1):
- i1 = int(np.round(i * stepsize))
- i2 = int(np.round((i + 1) * stepsize))
- polyverts.append([topverts[0][i1],
- topverts[0][i2],
- botverts[0][i2],
- botverts[0][i1]])
-
- v1 = np.array(topverts[0][i1]) - np.array(topverts[0][i2])
- v2 = np.array(topverts[0][i1]) - np.array(botverts[0][i1])
- normals.append(np.cross(v1, v2))
-
- colors = self._shade_colors(color, normals)
- colors2 = self._shade_colors(color, normals)
- polycol = art3d.Poly3DCollection(polyverts,
- facecolors=colors,
- edgecolors=colors2)
- polycol.set_sort_zpos(z)
- self.add_collection3d(polycol)
-
- for col in colls:
- self.collections.remove(col)
-
- def add_contour_set(self, cset, extend3d=False, stride=5, zdir='z', offset=None):
- zdir = '-' + zdir
- if extend3d:
- self._3d_extend_contour(cset, stride)
- else:
- for z, linec in zip(cset.levels, cset.collections):
- if offset is not None:
- z = offset
- art3d.line_collection_2d_to_3d(linec, z, zdir=zdir)
-
- def add_contourf_set(self, cset, zdir='z', offset=None):
- zdir = '-' + zdir
- for z, linec in zip(cset.levels, cset.collections):
- if offset is not None :
- z = offset
- art3d.poly_collection_2d_to_3d(linec, z, zdir=zdir)
- linec.set_sort_zpos(z)
-
- def contour(self, X, Y, Z, *args, **kwargs):
- '''
- Create a 3D contour plot.
-
- ========== ================================================
- Argument Description
- ========== ================================================
- *X*, *Y*, Data values as numpy.arrays
- *Z*
- *extend3d* Whether to extend contour in 3D (default: False)
- *stride* Stride (step size) for extending contour
- *zdir* The direction to use: x, y or z (default)
- *offset* If specified plot a projection of the contour
- lines on this position in plane normal to zdir
- ========== ================================================
-
- The positional and other keyword arguments are passed on to
- :func:`~matplotlib.axes.Axes.contour`
-
- Returns a :class:`~matplotlib.axes.Axes.contour`
- '''
-
- extend3d = kwargs.pop('extend3d', False)
- stride = kwargs.pop('stride', 5)
- zdir = kwargs.pop('zdir', 'z')
- offset = kwargs.pop('offset', None)
-
- had_data = self.has_data()
-
- jX, jY, jZ = art3d.rotate_axes(X, Y, Z, zdir)
- cset = super(Axes3D, self).contour(jX, jY, jZ, *args, **kwargs)
- self.add_contour_set(cset, extend3d, stride, zdir, offset)
-
- self.auto_scale_xyz(X, Y, Z, had_data)
- return cset
-
- contour3D = contour
-
- def tricontour(self, *args, **kwargs):
- """
- Create a 3D contour plot.
-
- ========== ================================================
- Argument Description
- ========== ================================================
- *X*, *Y*, Data values as numpy.arrays
- *Z*
- *extend3d* Whether to extend contour in 3D (default: False)
- *stride* Stride (step size) for extending contour
- *zdir* The direction to use: x, y or z (default)
- *offset* If specified plot a projection of the contour
- lines on this position in plane normal to zdir
- ========== ================================================
-
- Other keyword arguments are passed on to
- :func:`~matplotlib.axes.Axes.tricontour`
-
- Returns a :class:`~matplotlib.axes.Axes.contour`
-
- .. versionchanged:: 1.3.0
- Added support for custom triangulations
-
- EXPERIMENTAL: This method currently produces incorrect output due to a
- longstanding bug in 3D PolyCollection rendering.
- """
-
- extend3d = kwargs.pop('extend3d', False)
- stride = kwargs.pop('stride', 5)
- zdir = kwargs.pop('zdir', 'z')
- offset = kwargs.pop('offset', None)
-
- had_data = self.has_data()
-
- tri, args, kwargs = Triangulation.get_from_args_and_kwargs(
- *args, **kwargs)
- X = tri.x
- Y = tri.y
- if 'Z' in kwargs:
- Z = kwargs.pop('Z')
- else:
- Z = args[0]
- # We do this so Z doesn't get passed as an arg to Axes.tricontour
- args = args[1:]
-
- jX, jY, jZ = art3d.rotate_axes(X, Y, Z, zdir)
- tri = Triangulation(jX, jY, tri.triangles, tri.mask)
-
- cset = super(Axes3D, self).tricontour(tri, jZ, *args, **kwargs)
- self.add_contour_set(cset, extend3d, stride, zdir, offset)
-
- self.auto_scale_xyz(X, Y, Z, had_data)
- return cset
-
- def contourf(self, X, Y, Z, *args, **kwargs):
- '''
- Create a 3D contourf plot.
-
- ========== ================================================
- Argument Description
- ========== ================================================
- *X*, *Y*, Data values as numpy.arrays
- *Z*
- *zdir* The direction to use: x, y or z (default)
- *offset* If specified plot a projection of the filled contour
- on this position in plane normal to zdir
- ========== ================================================
-
- The positional and keyword arguments are passed on to
- :func:`~matplotlib.axes.Axes.contourf`
-
- Returns a :class:`~matplotlib.axes.Axes.contourf`
-
- .. versionchanged :: 1.1.0
- The *zdir* and *offset* kwargs were added.
- '''
-
- zdir = kwargs.pop('zdir', 'z')
- offset = kwargs.pop('offset', None)
-
- had_data = self.has_data()
-
- jX, jY, jZ = art3d.rotate_axes(X, Y, Z, zdir)
- cset = super(Axes3D, self).contourf(jX, jY, jZ, *args, **kwargs)
- self.add_contourf_set(cset, zdir, offset)
-
- self.auto_scale_xyz(X, Y, Z, had_data)
- return cset
-
- contourf3D = contourf
-
- def tricontourf(self, *args, **kwargs):
- """
- Create a 3D contourf plot.
-
- ========== ================================================
- Argument Description
- ========== ================================================
- *X*, *Y*, Data values as numpy.arrays
- *Z*
- *zdir* The direction to use: x, y or z (default)
- *offset* If specified plot a projection of the contour
- lines on this position in plane normal to zdir
- ========== ================================================
-
- Other keyword arguments are passed on to
- :func:`~matplotlib.axes.Axes.tricontour`
-
- Returns a :class:`~matplotlib.axes.Axes.contour`
-
- .. versionchanged :: 1.3.0
- Added support for custom triangulations
-
- EXPERIMENTAL: This method currently produces incorrect output due to a
- longstanding bug in 3D PolyCollection rendering.
- """
- zdir = kwargs.pop('zdir', 'z')
- offset = kwargs.pop('offset', None)
-
- had_data = self.has_data()
-
- tri, args, kwargs = Triangulation.get_from_args_and_kwargs(
- *args, **kwargs)
- X = tri.x
- Y = tri.y
- if 'Z' in kwargs:
- Z = kwargs.pop('Z')
- else:
- Z = args[0]
- # We do this so Z doesn't get passed as an arg to Axes.tricontourf
- args = args[1:]
-
- jX, jY, jZ = art3d.rotate_axes(X, Y, Z, zdir)
- tri = Triangulation(jX, jY, tri.triangles, tri.mask)
-
- cset = super(Axes3D, self).tricontourf(tri, jZ, *args, **kwargs)
- self.add_contourf_set(cset, zdir, offset)
-
- self.auto_scale_xyz(X, Y, Z, had_data)
- return cset
-
- def add_collection3d(self, col, zs=0, zdir='z'):
- '''
- Add a 3D collection object to the plot.
-
- 2D collection types are converted to a 3D version by
- modifying the object and adding z coordinate information.
-
- Supported are:
- - PolyCollection
- - LineCollection
- - PatchCollection
- '''
- zvals = np.atleast_1d(zs)
- if len(zvals) > 0 :
- zsortval = min(zvals)
- else :
- zsortval = 0 # FIXME: Fairly arbitrary. Is there a better value?
-
- # FIXME: use issubclass() (although, then a 3D collection
- # object would also pass.) Maybe have a collection3d
- # abstract class to test for and exclude?
- if type(col) is mcoll.PolyCollection:
- art3d.poly_collection_2d_to_3d(col, zs=zs, zdir=zdir)
- col.set_sort_zpos(zsortval)
- elif type(col) is mcoll.LineCollection:
- art3d.line_collection_2d_to_3d(col, zs=zs, zdir=zdir)
- col.set_sort_zpos(zsortval)
- elif type(col) is mcoll.PatchCollection:
- art3d.patch_collection_2d_to_3d(col, zs=zs, zdir=zdir)
- col.set_sort_zpos(zsortval)
-
- super(Axes3D, self).add_collection(col)
-
- def scatter(self, xs, ys, zs=0, zdir='z', s=20, c=None, depthshade=True,
- *args, **kwargs):
- '''
- Create a scatter plot.
-
- ============ ========================================================
- Argument Description
- ============ ========================================================
- *xs*, *ys* Positions of data points.
- *zs* Either an array of the same length as *xs* and
- *ys* or a single value to place all points in
- the same plane. Default is 0.
- *zdir* Which direction to use as z ('x', 'y' or 'z')
- when plotting a 2D set.
- *s* Size in points^2. It is a scalar or an array of the
- same length as *x* and *y*.
-
- *c* A color. *c* can be a single color format string, or a
- sequence of color specifications of length *N*, or a
- sequence of *N* numbers to be mapped to colors using the
- *cmap* and *norm* specified via kwargs (see below). Note
- that *c* should not be a single numeric RGB or RGBA
- sequence because that is indistinguishable from an array
- of values to be colormapped. *c* can be a 2-D array in
- which the rows are RGB or RGBA, however, including the
- case of a single row to specify the same color for
- all points.
-
- *depthshade*
- Whether or not to shade the scatter markers to give
- the appearance of depth. Default is *True*.
- ============ ========================================================
-
- Keyword arguments are passed on to
- :func:`~matplotlib.axes.Axes.scatter`.
-
- Returns a :class:`~mpl_toolkits.mplot3d.art3d.Patch3DCollection`
- '''
-
- had_data = self.has_data()
-
- xs, ys, zs = np.broadcast_arrays(
- *[np.ravel(np.ma.filled(t, np.nan)) for t in [xs, ys, zs]])
- s = np.ma.ravel(s) # This doesn't have to match x, y in size.
-
- xs, ys, zs, s, c = cbook.delete_masked_points(xs, ys, zs, s, c)
-
- patches = super(Axes3D, self).scatter(
- xs, ys, s=s, c=c, *args, **kwargs)
- is_2d = not cbook.iterable(zs)
- zs = _backports.broadcast_to(zs, len(xs))
- art3d.patch_collection_2d_to_3d(patches, zs=zs, zdir=zdir,
- depthshade=depthshade)
-
- if self._zmargin < 0.05 and xs.size > 0:
- self.set_zmargin(0.05)
-
- #FIXME: why is this necessary?
- if not is_2d:
- self.auto_scale_xyz(xs, ys, zs, had_data)
-
- return patches
-
- scatter3D = scatter
-
- def bar(self, left, height, zs=0, zdir='z', *args, **kwargs):
- '''
- Add 2D bar(s).
-
- ========== ================================================
- Argument Description
- ========== ================================================
- *left* The x coordinates of the left sides of the bars.
- *height* The height of the bars.
- *zs* Z coordinate of bars, if one value is specified
- they will all be placed at the same z.
- *zdir* Which direction to use as z ('x', 'y' or 'z')
- when plotting a 2D set.
- ========== ================================================
-
- Keyword arguments are passed onto :func:`~matplotlib.axes.Axes.bar`.
-
- Returns a :class:`~mpl_toolkits.mplot3d.art3d.Patch3DCollection`
- '''
-
- had_data = self.has_data()
-
- patches = super(Axes3D, self).bar(left, height, *args, **kwargs)
-
- zs = _backports.broadcast_to(zs, len(left))
-
- verts = []
- verts_zs = []
- for p, z in zip(patches, zs):
- vs = art3d.get_patch_verts(p)
- verts += vs.tolist()
- verts_zs += [z] * len(vs)
- art3d.patch_2d_to_3d(p, z, zdir)
- if 'alpha' in kwargs:
- p.set_alpha(kwargs['alpha'])
-
- if len(verts) > 0 :
- # the following has to be skipped if verts is empty
- # NOTE: Bugs could still occur if len(verts) > 0,
- # but the "2nd dimension" is empty.
- xs, ys = list(zip(*verts))
- else :
- xs, ys = [], []
-
- xs, ys, verts_zs = art3d.juggle_axes(xs, ys, verts_zs, zdir)
- self.auto_scale_xyz(xs, ys, verts_zs, had_data)
-
- return patches
-
- def bar3d(self, x, y, z, dx, dy, dz, color=None,
- zsort='average', shade=True, *args, **kwargs):
- """Generate a 3D barplot.
-
- This method creates three dimensional barplot where the width,
- depth, height, and color of the bars can all be uniquely set.
-
- Parameters
- ----------
- x, y, z : array-like
- The coordinates of the anchor point of the bars.
-
- dx, dy, dz : scalar or array-like
- The width, depth, and height of the bars, respectively.
-
- color : sequence of valid color specifications, optional
- The color of the bars can be specified globally or
- individually. This parameter can be:
-
- - A single color value, to color all bars the same color.
- - An array of colors of length N bars, to color each bar
- independently.
- - An array of colors of length 6, to color the faces of the
- bars similarly.
- - An array of colors of length 6 * N bars, to color each face
- independently.
-
- When coloring the faces of the boxes specifically, this is
- the order of the coloring:
-
- 1. -Z (bottom of box)
- 2. +Z (top of box)
- 3. -Y
- 4. +Y
- 5. -X
- 6. +X
-
- zsort : str, optional
- The z-axis sorting scheme passed onto
- :func:`~mpl_toolkits.mplot3d.art3d.Poly3DCollection`
-
- shade : bool, optional (default = True)
- When true, this shades the dark sides of the bars (relative
- to the plot's source of light).
-
- Any additional keyword arguments are passed onto
- :func:`~mpl_toolkits.mplot3d.art3d.Poly3DCollection`
-
- Returns
- -------
- collection : Poly3DCollection
- A collection of three dimensional polygons representing
- the bars.
- """
-
- had_data = self.has_data()
-
- x, y, z, dx, dy, dz = np.broadcast_arrays(
- np.atleast_1d(x), y, z, dx, dy, dz)
- minx = np.min(x)
- maxx = np.max(x + dx)
- miny = np.min(y)
- maxy = np.max(y + dy)
- minz = np.min(z)
- maxz = np.max(z + dz)
-
- polys = []
- for xi, yi, zi, dxi, dyi, dzi in zip(x, y, z, dx, dy, dz):
- polys.extend([
- ((xi, yi, zi), (xi + dxi, yi, zi),
- (xi + dxi, yi + dyi, zi), (xi, yi + dyi, zi)),
- ((xi, yi, zi + dzi), (xi + dxi, yi, zi + dzi),
- (xi + dxi, yi + dyi, zi + dzi), (xi, yi + dyi, zi + dzi)),
-
- ((xi, yi, zi), (xi + dxi, yi, zi),
- (xi + dxi, yi, zi + dzi), (xi, yi, zi + dzi)),
- ((xi, yi + dyi, zi), (xi + dxi, yi + dyi, zi),
- (xi + dxi, yi + dyi, zi + dzi), (xi, yi + dyi, zi + dzi)),
-
- ((xi, yi, zi), (xi, yi + dyi, zi),
- (xi, yi + dyi, zi + dzi), (xi, yi, zi + dzi)),
- ((xi + dxi, yi, zi), (xi + dxi, yi + dyi, zi),
- (xi + dxi, yi + dyi, zi + dzi), (xi + dxi, yi, zi + dzi)),
- ])
-
- facecolors = []
- if color is None:
- color = [self._get_patches_for_fill.get_next_color()]
-
- if len(color) == len(x):
- # bar colors specified, need to expand to number of faces
- for c in color:
- facecolors.extend([c] * 6)
- else:
- # a single color specified, or face colors specified explicitly
- facecolors = list(mcolors.to_rgba_array(color))
- if len(facecolors) < len(x):
- facecolors *= (6 * len(x))
-
- if shade:
- normals = self._generate_normals(polys)
- sfacecolors = self._shade_colors(facecolors, normals)
- else:
- sfacecolors = facecolors
-
- col = art3d.Poly3DCollection(polys,
- zsort=zsort,
- facecolor=sfacecolors,
- *args, **kwargs)
- self.add_collection(col)
-
- self.auto_scale_xyz((minx, maxx), (miny, maxy), (minz, maxz), had_data)
-
- return col
-
- def set_title(self, label, fontdict=None, loc='center', **kwargs):
- ret = super(Axes3D, self).set_title(label, fontdict=fontdict, loc=loc,
- **kwargs)
- (x, y) = self.title.get_position()
- self.title.set_y(0.92 * y)
- return ret
- set_title.__doc__ = maxes.Axes.set_title.__doc__
-
- def quiver(self, *args, **kwargs):
- """
- Plot a 3D field of arrows.
-
- call signatures::
-
- quiver(X, Y, Z, U, V, W, **kwargs)
-
- Arguments:
-
- *X*, *Y*, *Z*:
- The x, y and z coordinates of the arrow locations (default is
- tail of arrow; see *pivot* kwarg)
-
- *U*, *V*, *W*:
- The x, y and z components of the arrow vectors
-
- The arguments could be array-like or scalars, so long as they
- they can be broadcast together. The arguments can also be
- masked arrays. If an element in any of argument is masked, then
- that corresponding quiver element will not be plotted.
-
- Keyword arguments:
-
- *length*: [1.0 | float]
- The length of each quiver, default to 1.0, the unit is
- the same with the axes
-
- *arrow_length_ratio*: [0.3 | float]
- The ratio of the arrow head with respect to the quiver,
- default to 0.3
-
- *pivot*: [ 'tail' | 'middle' | 'tip' ]
- The part of the arrow that is at the grid point; the arrow
- rotates about this point, hence the name *pivot*.
- Default is 'tail'
-
- *normalize*: bool
- When True, all of the arrows will be the same length. This
- defaults to False, where the arrows will be different lengths
- depending on the values of u,v,w.
-
- Any additional keyword arguments are delegated to
- :class:`~matplotlib.collections.LineCollection`
-
- """
- def calc_arrow(uvw, angle=15):
- """
- To calculate the arrow head. uvw should be a unit vector.
- We normalize it here:
- """
- # get unit direction vector perpendicular to (u,v,w)
- norm = np.linalg.norm(uvw[:2])
- if norm > 0:
- x = uvw[1] / norm
- y = -uvw[0] / norm
- else:
- x, y = 0, 1
-
- # compute the two arrowhead direction unit vectors
- ra = math.radians(angle)
- c = math.cos(ra)
- s = math.sin(ra)
-
- # construct the rotation matrices
- Rpos = np.array([[c+(x**2)*(1-c), x*y*(1-c), y*s],
- [y*x*(1-c), c+(y**2)*(1-c), -x*s],
- [-y*s, x*s, c]])
- # opposite rotation negates all the sin terms
- Rneg = Rpos.copy()
- Rneg[[0,1,2,2],[2,2,0,1]] = -Rneg[[0,1,2,2],[2,2,0,1]]
-
- # multiply them to get the rotated vector
- return Rpos.dot(uvw), Rneg.dot(uvw)
-
- had_data = self.has_data()
-
- # handle kwargs
- # shaft length
- length = kwargs.pop('length', 1)
- # arrow length ratio to the shaft length
- arrow_length_ratio = kwargs.pop('arrow_length_ratio', 0.3)
- # pivot point
- pivot = kwargs.pop('pivot', 'tail')
- # normalize
- normalize = kwargs.pop('normalize', False)
-
- # handle args
- argi = 6
- if len(args) < argi:
- raise ValueError('Wrong number of arguments. Expected %d got %d' %
- (argi, len(args)))
-
- # first 6 arguments are X, Y, Z, U, V, W
- input_args = args[:argi]
- # if any of the args are scalar, convert into list
- input_args = [[k] if isinstance(k, (int, float)) else k
- for k in input_args]
-
- # extract the masks, if any
- masks = [k.mask for k in input_args if isinstance(k, np.ma.MaskedArray)]
- # broadcast to match the shape
- bcast = np.broadcast_arrays(*(input_args + masks))
- input_args = bcast[:argi]
- masks = bcast[argi:]
- if masks:
- # combine the masks into one
- mask = reduce(np.logical_or, masks)
- # put mask on and compress
- input_args = [np.ma.array(k, mask=mask).compressed()
- for k in input_args]
- else:
- input_args = [k.flatten() for k in input_args]
-
- if any(len(v) == 0 for v in input_args):
- # No quivers, so just make an empty collection and return early
- linec = art3d.Line3DCollection([], *args[argi:], **kwargs)
- self.add_collection(linec)
- return linec
-
- # Following assertions must be true before proceeding
- # must all be ndarray
- assert all(isinstance(k, np.ndarray) for k in input_args)
- # must all in same shape
- assert len({k.shape for k in input_args}) == 1
-
- shaft_dt = np.linspace(0, length, num=2)
- arrow_dt = shaft_dt * arrow_length_ratio
-
- if pivot == 'tail':
- shaft_dt -= length
- elif pivot == 'middle':
- shaft_dt -= length/2.
- elif pivot != 'tip':
- raise ValueError('Invalid pivot argument: ' + str(pivot))
-
- XYZ = np.column_stack(input_args[:3])
- UVW = np.column_stack(input_args[3:argi]).astype(float)
-
- # Normalize rows of UVW
- # Note: with numpy 1.9+, could use np.linalg.norm(UVW, axis=1)
- norm = np.sqrt(np.sum(UVW**2, axis=1))
-
- # If any row of UVW is all zeros, don't make a quiver for it
- mask = norm > 0
- XYZ = XYZ[mask]
- if normalize:
- UVW = UVW[mask] / norm[mask].reshape((-1, 1))
- else:
- UVW = UVW[mask]
-
- if len(XYZ) > 0:
- # compute the shaft lines all at once with an outer product
- shafts = (XYZ - np.multiply.outer(shaft_dt, UVW)).swapaxes(0, 1)
- # compute head direction vectors, n heads by 2 sides by 3 dimensions
- head_dirs = np.array([calc_arrow(d) for d in UVW])
- # compute all head lines at once, starting from where the shaft ends
- heads = shafts[:, :1] - np.multiply.outer(arrow_dt, head_dirs)
- # stack left and right head lines together
- heads.shape = (len(arrow_dt), -1, 3)
- # transpose to get a list of lines
- heads = heads.swapaxes(0, 1)
-
- lines = list(shafts) + list(heads)
- else:
- lines = []
-
- linec = art3d.Line3DCollection(lines, *args[argi:], **kwargs)
- self.add_collection(linec)
-
- self.auto_scale_xyz(XYZ[:, 0], XYZ[:, 1], XYZ[:, 2], had_data)
-
- return linec
-
- quiver3D = quiver
-
- def voxels(self, *args, **kwargs):
- """
- ax.voxels([x, y, z,] /, filled, **kwargs)
-
- Plot a set of filled voxels
-
- All voxels are plotted as 1x1x1 cubes on the axis, with filled[0,0,0]
- placed with its lower corner at the origin. Occluded faces are not
- plotted.
-
- Call signatures::
-
- voxels(filled, facecolors=fc, edgecolors=ec, **kwargs)
- voxels(x, y, z, filled, facecolors=fc, edgecolors=ec, **kwargs)
-
- .. versionadded:: 2.1
-
- Parameters
- ----------
- filled : 3D np.array of bool
- A 3d array of values, with truthy values indicating which voxels
- to fill
-
- x, y, z : 3D np.array, optional
- The coordinates of the corners of the voxels. This should broadcast
- to a shape one larger in every dimension than the shape of `filled`.
- These can be used to plot non-cubic voxels.
-
- If not specified, defaults to increasing integers along each axis,
- like those returned by :func:`~numpy.indices`.
- As indicated by the ``/`` in the function signature, these arguments
- can only be passed positionally.
-
- facecolors, edgecolors : array_like, optional
- The color to draw the faces and edges of the voxels. Can only be
- passed as keyword arguments.
- This parameter can be:
-
- - A single color value, to color all voxels the same color. This
- can be either a string, or a 1D rgb/rgba array
- - ``None``, the default, to use a single color for the faces, and
- the style default for the edges.
- - A 3D ndarray of color names, with each item the color for the
- corresponding voxel. The size must match the voxels.
- - A 4D ndarray of rgb/rgba data, with the components along the
- last axis.
-
- **kwargs
- Additional keyword arguments to pass onto
- :func:`~mpl_toolkits.mplot3d.art3d.Poly3DCollection`
-
- Returns
- -------
- faces : dict
- A dictionary indexed by coordinate, where ``faces[i,j,k]`` is a
- `Poly3DCollection` of the faces drawn for the voxel
- ``filled[i,j,k]``. If no faces were drawn for a given voxel, either
- because it was not asked to be drawn, or it is fully occluded, then
- ``(i,j,k) not in faces``.
-
- Examples
- --------
- .. plot:: gallery/mplot3d/voxels.py
- .. plot:: gallery/mplot3d/voxels_rgb.py
- .. plot:: gallery/mplot3d/voxels_torus.py
- .. plot:: gallery/mplot3d/voxels_numpy_logo.py
- """
-
- # work out which signature we should be using, and use it to parse
- # the arguments. Name must be voxels for the correct error message
- if len(args) >= 3:
- # underscores indicate position only
- def voxels(__x, __y, __z, filled, **kwargs):
- return (__x, __y, __z), filled, kwargs
- else:
- def voxels(filled, **kwargs):
- return None, filled, kwargs
-
- xyz, filled, kwargs = voxels(*args, **kwargs)
-
- # check dimensions
- if filled.ndim != 3:
- raise ValueError("Argument filled must be 3-dimensional")
- size = np.array(filled.shape, dtype=np.intp)
-
- # check xyz coordinates, which are one larger than the filled shape
- coord_shape = tuple(size + 1)
- if xyz is None:
- x, y, z = np.indices(coord_shape)
- else:
- x, y, z = (_backports.broadcast_to(c, coord_shape) for c in xyz)
-
- def _broadcast_color_arg(color, name):
- if np.ndim(color) in (0, 1):
- # single color, like "red" or [1, 0, 0]
- return _backports.broadcast_to(
- color, filled.shape + np.shape(color))
- elif np.ndim(color) in (3, 4):
- # 3D array of strings, or 4D array with last axis rgb
- if np.shape(color)[:3] != filled.shape:
- raise ValueError(
- "When multidimensional, {} must match the shape of "
- "filled".format(name))
- return color
- else:
- raise ValueError("Invalid {} argument".format(name))
-
- # intercept the facecolors, handling defaults and broacasting
- facecolors = kwargs.pop('facecolors', None)
- if facecolors is None:
- facecolors = self._get_patches_for_fill.get_next_color()
- facecolors = _broadcast_color_arg(facecolors, 'facecolors')
-
- # broadcast but no default on edgecolors
- edgecolors = kwargs.pop('edgecolors', None)
- edgecolors = _broadcast_color_arg(edgecolors, 'edgecolors')
-
- # always scale to the full array, even if the data is only in the center
- self.auto_scale_xyz(x, y, z)
-
- # points lying on corners of a square
- square = np.array([
- [0, 0, 0],
- [0, 1, 0],
- [1, 1, 0],
- [1, 0, 0]
- ], dtype=np.intp)
-
- voxel_faces = defaultdict(list)
-
- def permutation_matrices(n):
- """ Generator of cyclic permutation matices """
- mat = np.eye(n, dtype=np.intp)
- for i in range(n):
- yield mat
- mat = np.roll(mat, 1, axis=0)
-
- # iterate over each of the YZ, ZX, and XY orientations, finding faces to
- # render
- for permute in permutation_matrices(3):
- # find the set of ranges to iterate over
- pc, qc, rc = permute.T.dot(size)
- pinds = np.arange(pc)
- qinds = np.arange(qc)
- rinds = np.arange(rc)
-
- square_rot = square.dot(permute.T)
-
- # iterate within the current plane
- for p in pinds:
- for q in qinds:
- # iterate perpendicularly to the current plane, handling
- # boundaries. We only draw faces between a voxel and an
- # empty space, to avoid drawing internal faces.
-
- # draw lower faces
- p0 = permute.dot([p, q, 0])
- i0 = tuple(p0)
- if filled[i0]:
- voxel_faces[i0].append(p0 + square_rot)
-
- # draw middle faces
- for r1, r2 in zip(rinds[:-1], rinds[1:]):
- p1 = permute.dot([p, q, r1])
- p2 = permute.dot([p, q, r2])
-
- i1 = tuple(p1)
- i2 = tuple(p2)
-
- if filled[i1] and not filled[i2]:
- voxel_faces[i1].append(p2 + square_rot)
- elif not filled[i1] and filled[i2]:
- voxel_faces[i2].append(p2 + square_rot)
-
- # draw upper faces
- pk = permute.dot([p, q, rc-1])
- pk2 = permute.dot([p, q, rc])
- ik = tuple(pk)
- if filled[ik]:
- voxel_faces[ik].append(pk2 + square_rot)
-
- # iterate over the faces, and generate a Poly3DCollection for each voxel
- polygons = {}
- for coord, faces_inds in voxel_faces.items():
- # convert indices into 3D positions
- if xyz is None:
- faces = faces_inds
- else:
- faces = []
- for face_inds in faces_inds:
- ind = face_inds[:, 0], face_inds[:, 1], face_inds[:, 2]
- face = np.empty(face_inds.shape)
- face[:, 0] = x[ind]
- face[:, 1] = y[ind]
- face[:, 2] = z[ind]
- faces.append(face)
-
- poly = art3d.Poly3DCollection(faces,
- facecolors=facecolors[coord],
- edgecolors=edgecolors[coord],
- **kwargs
- )
- self.add_collection3d(poly)
- polygons[coord] = poly
-
- return polygons
-
-
-def get_test_data(delta=0.05):
- '''
- Return a tuple X, Y, Z with a test data set.
- '''
- x = y = np.arange(-3.0, 3.0, delta)
- X, Y = np.meshgrid(x, y)
-
- Z1 = np.exp(-(X**2 + Y**2) / 2) / (2 * np.pi)
- Z2 = (np.exp(-(((X - 1) / 1.5)**2 + ((Y - 1) / 0.5)**2) / 2) /
- (2 * np.pi * 0.5 * 1.5))
- Z = Z2 - Z1
-
- X = X * 10
- Y = Y * 10
- Z = Z * 500
- return X, Y, Z
-
-
-########################################################
-# Register Axes3D as a 'projection' object available
-# for use just like any other axes
-########################################################
-import matplotlib.projections as proj
-proj.projection_registry.register(Axes3D)
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/axis3d.py b/contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/axis3d.py
deleted file mode 100644
index 50b81df9125..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/axis3d.py
+++ /dev/null
@@ -1,484 +0,0 @@
-# axis3d.py, original mplot3d version by John Porter
-# Created: 23 Sep 2005
-# Parts rewritten by Reinier Heeres <[email protected]>
-
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-
-import math
-import copy
-
-from matplotlib import lines as mlines, axis as maxis, patches as mpatches
-from matplotlib import rcParams
-from . import art3d
-from . import proj3d
-
-import numpy as np
-
-def get_flip_min_max(coord, index, mins, maxs):
- if coord[index] == mins[index]:
- return maxs[index]
- else:
- return mins[index]
-
-def move_from_center(coord, centers, deltas, axmask=(True, True, True)):
- '''Return a coordinate that is moved by "deltas" away from the center.'''
- coord = copy.copy(coord)
- for i in range(3):
- if not axmask[i]:
- continue
- if coord[i] < centers[i]:
- coord[i] -= deltas[i]
- else:
- coord[i] += deltas[i]
- return coord
-
-def tick_update_position(tick, tickxs, tickys, labelpos):
- '''Update tick line and label position and style.'''
-
- for (label, on) in [(tick.label1, tick.label1On),
- (tick.label2, tick.label2On)]:
- if on:
- label.set_position(labelpos)
-
- tick.tick1On, tick.tick2On = True, False
- tick.tick1line.set_linestyle('-')
- tick.tick1line.set_marker('')
- tick.tick1line.set_data(tickxs, tickys)
- tick.gridline.set_data(0, 0)
-
-class Axis(maxis.XAxis):
-
- # These points from the unit cube make up the x, y and z-planes
- _PLANES = (
- (0, 3, 7, 4), (1, 2, 6, 5), # yz planes
- (0, 1, 5, 4), (3, 2, 6, 7), # xz planes
- (0, 1, 2, 3), (4, 5, 6, 7), # xy planes
- )
-
- # Some properties for the axes
- _AXINFO = {
- 'x': {'i': 0, 'tickdir': 1, 'juggled': (1, 0, 2),
- 'color': (0.95, 0.95, 0.95, 0.5)},
- 'y': {'i': 1, 'tickdir': 0, 'juggled': (0, 1, 2),
- 'color': (0.90, 0.90, 0.90, 0.5)},
- 'z': {'i': 2, 'tickdir': 0, 'juggled': (0, 2, 1),
- 'color': (0.925, 0.925, 0.925, 0.5)},
- }
-
- def __init__(self, adir, v_intervalx, d_intervalx, axes, *args, **kwargs):
- # adir identifies which axes this is
- self.adir = adir
- # data and viewing intervals for this direction
- self.d_interval = d_intervalx
- self.v_interval = v_intervalx
-
- # This is a temporary member variable.
- # Do not depend on this existing in future releases!
- self._axinfo = self._AXINFO[adir].copy()
- if rcParams['_internal.classic_mode']:
- self._axinfo.update(
- {'label': {'va': 'center',
- 'ha': 'center'},
- 'tick': {'inward_factor': 0.2,
- 'outward_factor': 0.1,
- 'linewidth': rcParams['lines.linewidth'],
- 'color': 'k'},
- 'axisline': {'linewidth': 0.75,
- 'color': (0, 0, 0, 1)},
- 'grid': {'color': (0.9, 0.9, 0.9, 1),
- 'linewidth': 1.0,
- 'linestyle': '-'},
- })
- else:
- self._axinfo.update(
- {'label': {'va': 'center',
- 'ha': 'center'},
- 'tick': {'inward_factor': 0.2,
- 'outward_factor': 0.1,
- 'linewidth': rcParams.get(
- adir + 'tick.major.width',
- rcParams['xtick.major.width']),
- 'color': rcParams.get(
- adir + 'tick.color',
- rcParams['xtick.color'])},
- 'axisline': {'linewidth': rcParams['axes.linewidth'],
- 'color': rcParams['axes.edgecolor']},
- 'grid': {'color': rcParams['grid.color'],
- 'linewidth': rcParams['grid.linewidth'],
- 'linestyle': rcParams['grid.linestyle']},
- })
-
- maxis.XAxis.__init__(self, axes, *args, **kwargs)
- self.set_rotate_label(kwargs.get('rotate_label', None))
-
- def init3d(self):
- self.line = mlines.Line2D(
- xdata=(0, 0), ydata=(0, 0),
- linewidth=self._axinfo['axisline']['linewidth'],
- color=self._axinfo['axisline']['color'],
- antialiased=True)
-
- # Store dummy data in Polygon object
- self.pane = mpatches.Polygon(
- np.array([[0, 0], [0, 1], [1, 0], [0, 0]]),
- closed=False, alpha=0.8, facecolor='k', edgecolor='k')
- self.set_pane_color(self._axinfo['color'])
-
- self.axes._set_artist_props(self.line)
- self.axes._set_artist_props(self.pane)
- self.gridlines = art3d.Line3DCollection([])
- self.axes._set_artist_props(self.gridlines)
- self.axes._set_artist_props(self.label)
- self.axes._set_artist_props(self.offsetText)
- # Need to be able to place the label at the correct location
- self.label._transform = self.axes.transData
- self.offsetText._transform = self.axes.transData
-
- def get_tick_positions(self):
- majorLocs = self.major.locator()
- self.major.formatter.set_locs(majorLocs)
- majorLabels = [self.major.formatter(val, i)
- for i, val in enumerate(majorLocs)]
- return majorLabels, majorLocs
-
- def get_major_ticks(self, numticks=None):
- ticks = maxis.XAxis.get_major_ticks(self, numticks)
- for t in ticks:
- t.tick1line.set_transform(self.axes.transData)
- t.tick2line.set_transform(self.axes.transData)
- t.gridline.set_transform(self.axes.transData)
- t.label1.set_transform(self.axes.transData)
- t.label2.set_transform(self.axes.transData)
- return ticks
-
- def set_pane_pos(self, xys):
- xys = np.asarray(xys)
- xys = xys[:,:2]
- self.pane.xy = xys
- self.stale = True
-
- def set_pane_color(self, color):
- '''Set pane color to a RGBA tuple.'''
- self._axinfo['color'] = color
- self.pane.set_edgecolor(color)
- self.pane.set_facecolor(color)
- self.pane.set_alpha(color[-1])
- self.stale = True
-
- def set_rotate_label(self, val):
- '''
- Whether to rotate the axis label: True, False or None.
- If set to None the label will be rotated if longer than 4 chars.
- '''
- self._rotate_label = val
- self.stale = True
-
- def get_rotate_label(self, text):
- if self._rotate_label is not None:
- return self._rotate_label
- else:
- return len(text) > 4
-
- def _get_coord_info(self, renderer):
- minx, maxx, miny, maxy, minz, maxz = self.axes.get_w_lims()
- if minx > maxx:
- minx, maxx = maxx, minx
- if miny > maxy:
- miny, maxy = maxy, miny
- if minz > maxz:
- minz, maxz = maxz, minz
- mins = np.array((minx, miny, minz))
- maxs = np.array((maxx, maxy, maxz))
- centers = (maxs + mins) / 2.
- deltas = (maxs - mins) / 12.
- mins = mins - deltas / 4.
- maxs = maxs + deltas / 4.
-
- vals = mins[0], maxs[0], mins[1], maxs[1], mins[2], maxs[2]
- tc = self.axes.tunit_cube(vals, renderer.M)
- avgz = [tc[p1][2] + tc[p2][2] + tc[p3][2] + tc[p4][2]
- for p1, p2, p3, p4 in self._PLANES]
- highs = np.array([avgz[2*i] < avgz[2*i+1] for i in range(3)])
-
- return mins, maxs, centers, deltas, tc, highs
-
- def draw_pane(self, renderer):
- renderer.open_group('pane3d')
-
- mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer)
-
- info = self._axinfo
- index = info['i']
- if not highs[index]:
- plane = self._PLANES[2 * index]
- else:
- plane = self._PLANES[2 * index + 1]
- xys = [tc[p] for p in plane]
- self.set_pane_pos(xys)
- self.pane.draw(renderer)
-
- renderer.close_group('pane3d')
-
- def draw(self, renderer):
- self.label._transform = self.axes.transData
- renderer.open_group('axis3d')
-
- # code from XAxis
- majorTicks = self.get_major_ticks()
- majorLocs = self.major.locator()
-
- info = self._axinfo
- index = info['i']
-
- # filter locations here so that no extra grid lines are drawn
- locmin, locmax = self.get_view_interval()
- if locmin > locmax:
- locmin, locmax = locmax, locmin
-
- # Rudimentary clipping
- majorLocs = [loc for loc in majorLocs if
- locmin <= loc <= locmax]
- self.major.formatter.set_locs(majorLocs)
- majorLabels = [self.major.formatter(val, i)
- for i, val in enumerate(majorLocs)]
-
- mins, maxs, centers, deltas, tc, highs = self._get_coord_info(renderer)
-
- # Determine grid lines
- minmax = np.where(highs, maxs, mins)
-
- # Draw main axis line
- juggled = info['juggled']
- edgep1 = minmax.copy()
- edgep1[juggled[0]] = get_flip_min_max(edgep1, juggled[0], mins, maxs)
-
- edgep2 = edgep1.copy()
- edgep2[juggled[1]] = get_flip_min_max(edgep2, juggled[1], mins, maxs)
- pep = proj3d.proj_trans_points([edgep1, edgep2], renderer.M)
- centpt = proj3d.proj_transform(
- centers[0], centers[1], centers[2], renderer.M)
- self.line.set_data((pep[0][0], pep[0][1]), (pep[1][0], pep[1][1]))
- self.line.draw(renderer)
-
- # Grid points where the planes meet
- xyz0 = []
- for val in majorLocs:
- coord = minmax.copy()
- coord[index] = val
- xyz0.append(coord)
-
- # Draw labels
- peparray = np.asanyarray(pep)
- # The transAxes transform is used because the Text object
- # rotates the text relative to the display coordinate system.
- # Therefore, if we want the labels to remain parallel to the
- # axis regardless of the aspect ratio, we need to convert the
- # edge points of the plane to display coordinates and calculate
- # an angle from that.
- # TODO: Maybe Text objects should handle this themselves?
- dx, dy = (self.axes.transAxes.transform([peparray[0:2, 1]]) -
- self.axes.transAxes.transform([peparray[0:2, 0]]))[0]
-
- lxyz = 0.5*(edgep1 + edgep2)
-
- # A rough estimate; points are ambiguous since 3D plots rotate
- ax_scale = self.axes.bbox.size / self.figure.bbox.size
- ax_inches = np.multiply(ax_scale, self.figure.get_size_inches())
- ax_points_estimate = sum(72. * ax_inches)
- deltas_per_point = 48. / ax_points_estimate
- default_offset = 21.
- labeldeltas = (
- (self.labelpad + default_offset) * deltas_per_point * deltas)
- axmask = [True, True, True]
- axmask[index] = False
- lxyz = move_from_center(lxyz, centers, labeldeltas, axmask)
- tlx, tly, tlz = proj3d.proj_transform(lxyz[0], lxyz[1], lxyz[2],
- renderer.M)
- self.label.set_position((tlx, tly))
- if self.get_rotate_label(self.label.get_text()):
- angle = art3d.norm_text_angle(math.degrees(math.atan2(dy, dx)))
- self.label.set_rotation(angle)
- self.label.set_va(info['label']['va'])
- self.label.set_ha(info['label']['ha'])
- self.label.draw(renderer)
-
-
- # Draw Offset text
-
- # Which of the two edge points do we want to
- # use for locating the offset text?
- if juggled[2] == 2 :
- outeredgep = edgep1
- outerindex = 0
- else :
- outeredgep = edgep2
- outerindex = 1
-
- pos = copy.copy(outeredgep)
- pos = move_from_center(pos, centers, labeldeltas, axmask)
- olx, oly, olz = proj3d.proj_transform(
- pos[0], pos[1], pos[2], renderer.M)
- self.offsetText.set_text( self.major.formatter.get_offset() )
- self.offsetText.set_position( (olx, oly) )
- angle = art3d.norm_text_angle(math.degrees(math.atan2(dy, dx)))
- self.offsetText.set_rotation(angle)
- # Must set rotation mode to "anchor" so that
- # the alignment point is used as the "fulcrum" for rotation.
- self.offsetText.set_rotation_mode('anchor')
-
- #----------------------------------------------------------------------
- # Note: the following statement for determining the proper alignment of
- # the offset text. This was determined entirely by trial-and-error
- # and should not be in any way considered as "the way". There are
- # still some edge cases where alignment is not quite right, but this
- # seems to be more of a geometry issue (in other words, I might be
- # using the wrong reference points).
- #
- # (TT, FF, TF, FT) are the shorthand for the tuple of
- # (centpt[info['tickdir']] <= peparray[info['tickdir'], outerindex],
- # centpt[index] <= peparray[index, outerindex])
- #
- # Three-letters (e.g., TFT, FTT) are short-hand for the array of bools
- # from the variable 'highs'.
- # ---------------------------------------------------------------------
- if centpt[info['tickdir']] > peparray[info['tickdir'], outerindex] :
- # if FT and if highs has an even number of Trues
- if (centpt[index] <= peparray[index, outerindex]
- and ((len(highs.nonzero()[0]) % 2) == 0)) :
- # Usually, this means align right, except for the FTT case,
- # in which offset for axis 1 and 2 are aligned left.
- if highs.tolist() == [False, True, True] and index in (1, 2) :
- align = 'left'
- else :
- align = 'right'
- else :
- # The FF case
- align = 'left'
- else :
- # if TF and if highs has an even number of Trues
- if (centpt[index] > peparray[index, outerindex]
- and ((len(highs.nonzero()[0]) % 2) == 0)) :
- # Usually mean align left, except if it is axis 2
- if index == 2 :
- align = 'right'
- else :
- align = 'left'
- else :
- # The TT case
- align = 'right'
-
- self.offsetText.set_va('center')
- self.offsetText.set_ha(align)
- self.offsetText.draw(renderer)
-
- # Draw grid lines
- if len(xyz0) > 0:
- # Grid points at end of one plane
- xyz1 = copy.deepcopy(xyz0)
- newindex = (index + 1) % 3
- newval = get_flip_min_max(xyz1[0], newindex, mins, maxs)
- for i in range(len(majorLocs)):
- xyz1[i][newindex] = newval
-
- # Grid points at end of the other plane
- xyz2 = copy.deepcopy(xyz0)
- newindex = (index + 2) % 3
- newval = get_flip_min_max(xyz2[0], newindex, mins, maxs)
- for i in range(len(majorLocs)):
- xyz2[i][newindex] = newval
-
- lines = list(zip(xyz1, xyz0, xyz2))
- if self.axes._draw_grid:
- self.gridlines.set_segments(lines)
- self.gridlines.set_color([info['grid']['color']] * len(lines))
- self.gridlines.set_linewidth(
- [info['grid']['linewidth']] * len(lines))
- self.gridlines.set_linestyle(
- [info['grid']['linestyle']] * len(lines))
- self.gridlines.draw(renderer, project=True)
-
- # Draw ticks
- tickdir = info['tickdir']
- tickdelta = deltas[tickdir]
- if highs[tickdir]:
- ticksign = 1
- else:
- ticksign = -1
-
- for tick, loc, label in zip(majorTicks, majorLocs, majorLabels):
- if tick is None:
- continue
-
- # Get tick line positions
- pos = copy.copy(edgep1)
- pos[index] = loc
- pos[tickdir] = (
- edgep1[tickdir]
- + info['tick']['outward_factor'] * ticksign * tickdelta)
- x1, y1, z1 = proj3d.proj_transform(pos[0], pos[1], pos[2],
- renderer.M)
- pos[tickdir] = (
- edgep1[tickdir]
- - info['tick']['inward_factor'] * ticksign * tickdelta)
- x2, y2, z2 = proj3d.proj_transform(pos[0], pos[1], pos[2],
- renderer.M)
-
- # Get position of label
- default_offset = 8. # A rough estimate
- labeldeltas = (
- (tick.get_pad() + default_offset) * deltas_per_point * deltas)
-
- axmask = [True, True, True]
- axmask[index] = False
- pos[tickdir] = edgep1[tickdir]
- pos = move_from_center(pos, centers, labeldeltas, axmask)
- lx, ly, lz = proj3d.proj_transform(pos[0], pos[1], pos[2],
- renderer.M)
-
- tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly))
- tick.tick1line.set_linewidth(info['tick']['linewidth'])
- tick.tick1line.set_color(info['tick']['color'])
- tick.set_label1(label)
- tick.set_label2(label)
- tick.draw(renderer)
-
- renderer.close_group('axis3d')
- self.stale = False
-
- def get_view_interval(self):
- """return the Interval instance for this 3d axis view limits"""
- return self.v_interval
-
- def set_view_interval(self, vmin, vmax, ignore=False):
- if ignore:
- self.v_interval = vmin, vmax
- else:
- Vmin, Vmax = self.get_view_interval()
- self.v_interval = min(vmin, Vmin), max(vmax, Vmax)
-
- # TODO: Get this to work properly when mplot3d supports
- # the transforms framework.
- def get_tightbbox(self, renderer) :
- # Currently returns None so that Axis.get_tightbbox
- # doesn't return junk info.
- return None
-
-# Use classes to look at different data limits
-
-class XAxis(Axis):
- def get_data_interval(self):
- 'return the Interval instance for this axis data limits'
- return self.axes.xy_dataLim.intervalx
-
-class YAxis(Axis):
- def get_data_interval(self):
- 'return the Interval instance for this axis data limits'
- return self.axes.xy_dataLim.intervaly
-
-class ZAxis(Axis):
- def get_data_interval(self):
- 'return the Interval instance for this axis data limits'
- return self.axes.zz_dataLim.intervalx
diff --git a/contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/proj3d.py b/contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/proj3d.py
deleted file mode 100644
index a084e7f36a4..00000000000
--- a/contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/proj3d.py
+++ /dev/null
@@ -1,203 +0,0 @@
-# 3dproj.py
-#
-"""
-Various transforms used for by the 3D code
-"""
-from __future__ import (absolute_import, division, print_function,
- unicode_literals)
-
-import six
-from six.moves import zip
-
-import numpy as np
-import numpy.linalg as linalg
-
-
-
-def line2d(p0, p1):
- """
- Return 2D equation of line in the form ax+by+c = 0
- """
- # x + x1 = 0
- x0, y0 = p0[:2]
- x1, y1 = p1[:2]
- #
- if x0 == x1:
- a = -1
- b = 0
- c = x1
- elif y0 == y1:
- a = 0
- b = 1
- c = -y1
- else:
- a = (y0-y1)
- b = (x0-x1)
- c = (x0*y1 - x1*y0)
- return a, b, c
-
-def line2d_dist(l, p):
- """
- Distance from line to point
- line is a tuple of coefficients a,b,c
- """
- a, b, c = l
- x0, y0 = p
- return abs((a*x0 + b*y0 + c)/np.sqrt(a**2+b**2))
-
-
-def line2d_seg_dist(p1, p2, p0):
- """distance(s) from line defined by p1 - p2 to point(s) p0
-
- p0[0] = x(s)
- p0[1] = y(s)
-
- intersection point p = p1 + u*(p2-p1)
- and intersection point lies within segment if u is between 0 and 1
- """
-
- x21 = p2[0] - p1[0]
- y21 = p2[1] - p1[1]
- x01 = np.asarray(p0[0]) - p1[0]
- y01 = np.asarray(p0[1]) - p1[1]
-
- u = (x01*x21 + y01*y21) / (x21**2 + y21**2)
- u = np.clip(u, 0, 1)
- d = np.sqrt((x01 - u*x21)**2 + (y01 - u*y21)**2)
-
- return d
-
-
-def mod(v):
- """3d vector length"""
- return np.sqrt(v[0]**2+v[1]**2+v[2]**2)
-
-def world_transformation(xmin, xmax,
- ymin, ymax,
- zmin, zmax):
- dx, dy, dz = (xmax-xmin), (ymax-ymin), (zmax-zmin)
- return np.array([
- [1.0/dx,0,0,-xmin/dx],
- [0,1.0/dy,0,-ymin/dy],
- [0,0,1.0/dz,-zmin/dz],
- [0,0,0,1.0]])
-
-
-def view_transformation(E, R, V):
- n = (E - R)
- ## new
-# n /= mod(n)
-# u = np.cross(V,n)
-# u /= mod(u)
-# v = np.cross(n,u)
-# Mr = np.diag([1.]*4)
-# Mt = np.diag([1.]*4)
-# Mr[:3,:3] = u,v,n
-# Mt[:3,-1] = -E
- ## end new
-
- ## old
- n = n / mod(n)
- u = np.cross(V, n)
- u = u / mod(u)
- v = np.cross(n, u)
- Mr = [[u[0],u[1],u[2],0],
- [v[0],v[1],v[2],0],
- [n[0],n[1],n[2],0],
- [0, 0, 0, 1],
- ]
- #
- Mt = [[1, 0, 0, -E[0]],
- [0, 1, 0, -E[1]],
- [0, 0, 1, -E[2]],
- [0, 0, 0, 1]]
- ## end old
-
- return np.dot(Mr, Mt)
-
-def persp_transformation(zfront, zback):
- a = (zfront+zback)/(zfront-zback)
- b = -2*(zfront*zback)/(zfront-zback)
- return np.array([[1,0,0,0],
- [0,1,0,0],
- [0,0,a,b],
- [0,0,-1,0]
- ])
-
-def ortho_transformation(zfront, zback):
- # note: w component in the resulting vector will be (zback-zfront), not 1
- a = -(zfront + zback)
- b = -(zfront - zback)
- return np.array([[2,0,0,0],
- [0,2,0,0],
- [0,0,-2,0],
- [0,0,a,b]
- ])
-
-def proj_transform_vec(vec, M):
- vecw = np.dot(M, vec)
- w = vecw[3]
- # clip here..
- txs, tys, tzs = vecw[0]/w, vecw[1]/w, vecw[2]/w
- return txs, tys, tzs
-
-def proj_transform_vec_clip(vec, M):
- vecw = np.dot(M, vec)
- w = vecw[3]
- # clip here.
- txs, tys, tzs = vecw[0] / w, vecw[1] / w, vecw[2] / w
- tis = (0 <= vecw[0]) & (vecw[0] <= 1) & (0 <= vecw[1]) & (vecw[1] <= 1)
- if np.any(tis):
- tis = vecw[1] < 1
- return txs, tys, tzs, tis
-
-def inv_transform(xs, ys, zs, M):
- iM = linalg.inv(M)
- vec = vec_pad_ones(xs, ys, zs)
- vecr = np.dot(iM, vec)
- try:
- vecr = vecr/vecr[3]
- except OverflowError:
- pass
- return vecr[0], vecr[1], vecr[2]
-
-def vec_pad_ones(xs, ys, zs):
- return np.array([xs, ys, zs, np.ones_like(xs)])
-
-def proj_transform(xs, ys, zs, M):
- """
- Transform the points by the projection matrix
- """
- vec = vec_pad_ones(xs, ys, zs)
- return proj_transform_vec(vec, M)
-
-def proj_transform_clip(xs, ys, zs, M):
- """
- Transform the points by the projection matrix
- and return the clipping result
- returns txs,tys,tzs,tis
- """
- vec = vec_pad_ones(xs, ys, zs)
- return proj_transform_vec_clip(vec, M)
-transform = proj_transform
-
-def proj_points(points, M):
- return np.column_stack(proj_trans_points(points, M))
-
-def proj_trans_points(points, M):
- xs, ys, zs = zip(*points)
- return proj_transform(xs, ys, zs, M)
-
-def proj_trans_clip_points(points, M):
- xs, ys, zs = zip(*points)
- return proj_transform_clip(xs, ys, zs, M)
-
-
-def rot_x(V, alpha):
- cosa, sina = np.cos(alpha), np.sin(alpha)
- M1 = np.array([[1,0,0,0],
- [0,cosa,-sina,0],
- [0,sina,cosa,0],
- [0,0,0,1]])
-
- return np.dot(M1, V)