diff --git a/examples/animation/random_walk.py b/examples/animation/random_walk.py index ae60ce7c09ec..b26a8a71cd13 100644 --- a/examples/animation/random_walk.py +++ b/examples/animation/random_walk.py @@ -7,31 +7,29 @@ import numpy as np import matplotlib.pyplot as plt -import mpl_toolkits.mplot3d.axes3d as p3 import matplotlib.animation as animation # Fixing random state for reproducibility np.random.seed(19680801) -def Gen_RandLine(length, dims=2): +def gen_rand_line(length, dims=2): """ Create a line using a random walk algorithm length is the number of points for the line. dims is the number of dimensions the line has. """ - lineData = np.empty((dims, length)) - lineData[:, 0] = np.random.rand(dims) + line_data = np.empty((dims, length)) + line_data[:, 0] = np.random.rand(dims) for index in range(1, length): # scaling the random numbers by 0.1 so # movement is small compared to position. # subtraction by 0.5 is to change the range to [-0.5, 0.5] # to allow a line to move backwards. - step = ((np.random.rand(dims) - 0.5) * 0.1) - lineData[:, index] = lineData[:, index - 1] + step - - return lineData + step = (np.random.rand(dims) - 0.5) * 0.1 + line_data[:, index] = line_data[:, index - 1] + step + return line_data def update_lines(num, dataLines, lines): @@ -41,12 +39,13 @@ def update_lines(num, dataLines, lines): line.set_3d_properties(data[2, :num]) return lines + # Attaching 3D axis to the figure fig = plt.figure() -ax = p3.Axes3D(fig) +ax = fig.add_subplot(projection="3d") # Fifty lines of random 3-D lines -data = [Gen_RandLine(25, 3) for index in range(50)] +data = [gen_rand_line(25, 3) for index in range(50)] # Creating fifty line objects. # NOTE: Can't pass empty arrays into 3d version of plot() @@ -65,7 +64,7 @@ def update_lines(num, dataLines, lines): ax.set_title('3D Test') # Creating the Animation object -line_ani = animation.FuncAnimation(fig, update_lines, 25, fargs=(data, lines), - interval=50, blit=False) +line_ani = animation.FuncAnimation( + fig, update_lines, 25, fargs=(data, lines), interval=50) plt.show() diff --git a/lib/matplotlib/units.py b/lib/matplotlib/units.py index de40d7915d4d..4cbac7c226ab 100644 --- a/lib/matplotlib/units.py +++ b/lib/matplotlib/units.py @@ -55,9 +55,10 @@ class ConversionError(TypeError): class AxisInfo(object): """ - Information to support default axis labeling, tick labeling, and - default limits. An instance of this class must be returned by - :meth:`ConversionInterface.axisinfo`. + Information to support default axis labeling, tick labeling, and limits. + + An instance of this class must be returned by + `ConversionInterface.axisinfo`. """ def __init__(self, majloc=None, minloc=None, majfmt=None, minfmt=None, label=None, @@ -96,8 +97,7 @@ class ConversionInterface(object): @staticmethod def axisinfo(unit, axis): """ - Return an `~units.AxisInfo` instance for the axis with the - specified units. + Return an `~units.AxisInfo` for the axis with the specified units. """ return None @@ -112,19 +112,19 @@ def default_units(x, axis): def convert(obj, unit, axis): """ Convert *obj* using *unit* for the specified *axis*. - If *obj* is a sequence, return the converted sequence. - The output must be a sequence of scalars that can be used by the numpy - array layer. + + If *obj* is a sequence, return the converted sequence. The output must + be a sequence of scalars that can be used by the numpy array layer. """ return obj @staticmethod def is_numlike(x): """ - The Matplotlib datalim, autoscaling, locators etc work with - scalars which are the units converted to floats given the - current unit. The converter may be passed these floats, or - arrays of them, even when units are set. + The Matplotlib datalim, autoscaling, locators etc work with scalars + which are the units converted to floats given the current unit. The + converter may be passed these floats, or arrays of them, even when + units are set. """ if np.iterable(x): for thisx in x: @@ -134,73 +134,33 @@ def is_numlike(x): class Registry(dict): - """ - A register that maps types to conversion interfaces. - """ - def __init__(self): - dict.__init__(self) - self._cached = {} + """Register types with conversion interface.""" def get_converter(self, x): - """ - Get the converter for data that has the same type as *x*. If no - converters are registered for *x*, returns ``None``. - """ - - if not len(self): - return None # nothing registered - # DISABLED idx = id(x) - # DISABLED cached = self._cached.get(idx) - # DISABLED if cached is not None: return cached - - converter = None - classx = getattr(x, '__class__', None) - - if classx is not None: - converter = self.get(classx) - - if converter is None and hasattr(x, "values"): - # this unpacks pandas series or dataframes... - x = x.values - - # If x is an array, look inside the array for data with units + """Get the converter interface instance for *x*, or None.""" + if hasattr(x, "values"): + x = x.values # Unpack pandas Series and DataFrames. if isinstance(x, np.ndarray): + # In case x in a masked array, access the underlying data (only its + # type matters). If x is a regular ndarray, getdata() just returns + # the array itself. + x = np.ma.getdata(x).ravel() # If there are no elements in x, infer the units from its dtype if not x.size: return self.get_converter(np.array([0], dtype=x.dtype)) - xravel = x.ravel() - try: - # pass the first value of x that is not masked back to - # get_converter - if not np.all(xravel.mask): - # Get first non-masked item - converter = self.get_converter( - xravel[np.argmin(xravel.mask)]) - return converter - except AttributeError: - # not a masked_array - # Make sure we don't recurse forever -- it's possible for - # ndarray subclasses to continue to return subclasses and - # not ever return a non-subclass for a single element. - next_item = xravel[0] - if (not isinstance(next_item, np.ndarray) or - next_item.shape != x.shape): - converter = self.get_converter(next_item) - return converter - - # If we haven't found a converter yet, try to get the first element - if converter is None: - try: - thisx = cbook.safe_first_element(x) + try: # Look up in the cache. + return self[type(x)] + except KeyError: + try: # If cache lookup fails, look up based on first element... + first = cbook.safe_first_element(x) except (TypeError, StopIteration): pass else: - if classx and classx != getattr(thisx, '__class__', None): - converter = self.get_converter(thisx) - return converter - - # DISABLED self._cached[idx] = converter - return converter + # ... and avoid infinite recursion for pathological iterables + # where indexing returns instances of the same iterable class. + if type(first) is not type(x): + return self.get_converter(first) + return None registry = Registry() diff --git a/tutorials/toolkits/mplot3d.py b/tutorials/toolkits/mplot3d.py index 212481ee9fe0..44879f630795 100644 --- a/tutorials/toolkits/mplot3d.py +++ b/tutorials/toolkits/mplot3d.py @@ -14,24 +14,21 @@ Getting started --------------- -An Axes3D object is created just like any other axes using -the projection='3d' keyword. -Create a new :class:`matplotlib.figure.Figure` and -add a new axes to it of type :class:`~mpl_toolkits.mplot3d.Axes3D`:: +3D Axes (of class `Axes3D`) are created by passing the ``projection="3d"`` +keyword argument to `Figure.add_subplot`:: import matplotlib.pyplot as plt - from mpl_toolkits.mplot3d import Axes3D fig = plt.figure() ax = fig.add_subplot(111, projection='3d') -.. versionadded:: 1.0.0 - This approach is the preferred method of creating a 3D axes. +.. versionchanged:: 1.0.0 + Prior to Matplotlib 1.0.0, `Axes3D` needed to be directly instantiated with + ``from mpl_toolkits.mplot3d import Axes3D; ax = Axes3D(fig)``. -.. note:: - Prior to version 1.0.0, the method of creating a 3D axes was - different. For those using older versions of matplotlib, change - ``ax = fig.add_subplot(111, projection='3d')`` - to ``ax = Axes3D(fig)``. +.. versionchanged:: 3.2.0 + Prior to Matplotlib 3.2.0, it was necessary to explicitly import the + :mod:`mpl_toolkits.mplot3d` module to make the '3d' projection to + `Figure.add_subplot`. See the :ref:`toolkit_mplot3d-faq` for more information about the mplot3d toolkit.