__init__.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. """
  2. Non-separable transforms that map from data space to screen space.
  3. Projections are defined as `~.axes.Axes` subclasses. They include the
  4. following elements:
  5. - A transformation from data coordinates into display coordinates.
  6. - An inverse of that transformation. This is used, for example, to convert
  7. mouse positions from screen space back into data space.
  8. - Transformations for the gridlines, ticks and ticklabels. Custom projections
  9. will often need to place these elements in special locations, and Matplotlib
  10. has a facility to help with doing so.
  11. - Setting up default values (overriding `~.axes.Axes.cla`), since the defaults
  12. for a rectilinear Axes may not be appropriate.
  13. - Defining the shape of the Axes, for example, an elliptical Axes, that will be
  14. used to draw the background of the plot and for clipping any data elements.
  15. - Defining custom locators and formatters for the projection. For example, in
  16. a geographic projection, it may be more convenient to display the grid in
  17. degrees, even if the data is in radians.
  18. - Set up interactive panning and zooming. This is left as an "advanced"
  19. feature left to the reader, but there is an example of this for polar plots
  20. in `matplotlib.projections.polar`.
  21. - Any additional methods for additional convenience or features.
  22. Once the projection Axes is defined, it can be used in one of two ways:
  23. - By defining the class attribute ``name``, the projection Axes can be
  24. registered with `matplotlib.projections.register_projection` and subsequently
  25. simply invoked by name::
  26. fig.add_subplot(projection="my_proj_name")
  27. - For more complex, parameterisable projections, a generic "projection" object
  28. may be defined which includes the method ``_as_mpl_axes``. ``_as_mpl_axes``
  29. should take no arguments and return the projection's Axes subclass and a
  30. dictionary of additional arguments to pass to the subclass' ``__init__``
  31. method. Subsequently a parameterised projection can be initialised with::
  32. fig.add_subplot(projection=MyProjection(param1=param1_value))
  33. where MyProjection is an object which implements a ``_as_mpl_axes`` method.
  34. A full-fledged and heavily annotated example is in
  35. :doc:`/gallery/misc/custom_projection`. The polar plot functionality in
  36. `matplotlib.projections.polar` may also be of interest.
  37. """
  38. from .. import axes, _docstring
  39. from .geo import AitoffAxes, HammerAxes, LambertAxes, MollweideAxes
  40. from .polar import PolarAxes
  41. try:
  42. from mpl_toolkits.mplot3d import Axes3D
  43. except Exception:
  44. import warnings
  45. warnings.warn("Unable to import Axes3D. This may be due to multiple versions of "
  46. "Matplotlib being installed (e.g. as a system package and as a pip "
  47. "package). As a result, the 3D projection is not available.")
  48. Axes3D = None
  49. class ProjectionRegistry:
  50. """A mapping of registered projection names to projection classes."""
  51. def __init__(self):
  52. self._all_projection_types = {}
  53. def register(self, *projections):
  54. """Register a new set of projections."""
  55. for projection in projections:
  56. name = projection.name
  57. self._all_projection_types[name] = projection
  58. def get_projection_class(self, name):
  59. """Get a projection class from its *name*."""
  60. return self._all_projection_types[name]
  61. def get_projection_names(self):
  62. """Return the names of all projections currently registered."""
  63. return sorted(self._all_projection_types)
  64. projection_registry = ProjectionRegistry()
  65. projection_registry.register(
  66. axes.Axes,
  67. PolarAxes,
  68. AitoffAxes,
  69. HammerAxes,
  70. LambertAxes,
  71. MollweideAxes,
  72. )
  73. if Axes3D is not None:
  74. projection_registry.register(Axes3D)
  75. else:
  76. # remove from namespace if not importable
  77. del Axes3D
  78. def register_projection(cls):
  79. projection_registry.register(cls)
  80. def get_projection_class(projection=None):
  81. """
  82. Get a projection class from its name.
  83. If *projection* is None, a standard rectilinear projection is returned.
  84. """
  85. if projection is None:
  86. projection = 'rectilinear'
  87. try:
  88. return projection_registry.get_projection_class(projection)
  89. except KeyError as err:
  90. raise ValueError("Unknown projection %r" % projection) from err
  91. get_projection_names = projection_registry.get_projection_names
  92. _docstring.interpd.register(projection_names=get_projection_names())