diff --git a/.travis.yml b/.travis.yml index 852837464d6c..594565b46f0b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -115,7 +115,7 @@ before_install: # We could install ghostscript and inkscape here to test svg and pdf # but this makes the test time really long. # brew install ghostscript inkscape - export PATH=/usr/local/opt/ccache/libexec:$PATH + export PATH=/usr/local/opt/python/libexec/bin:/usr/local/opt/ccache/libexec:$PATH fi install: @@ -153,7 +153,7 @@ install: python -c 'import PyQt5.QtCore' && echo 'PyQt5 is available' || echo 'PyQt5 is not available' - python -mpip install -U --pre \ + python -mpip install -U \ --no-index -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-14.04 \ wxPython && python -c 'import wx' && diff --git a/doc/api/next_api_changes/2018-03-14-SS.rst b/doc/api/next_api_changes/2018-03-14-SS.rst new file mode 100644 index 000000000000..1a6032246b3d --- /dev/null +++ b/doc/api/next_api_changes/2018-03-14-SS.rst @@ -0,0 +1,5 @@ +``AutoDateLocator.get_locator`` now contains reduced datetime overlaps +```````````````````````````````````````````````````````````````````````` + +Due to issue #7712, the interval frequency of datetime ticks gets reduced in order +to avoid overlapping tick labels. diff --git a/doc/conf.py b/doc/conf.py index 5b8112788501..dcbb45ac8e28 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -153,7 +153,7 @@ def _check_deps(): project = 'Matplotlib' copyright = ('2002 - 2012 John Hunter, Darren Dale, Eric Firing, ' 'Michael Droettboom and the Matplotlib development ' - 'team; 2012 - 2017 The Matplotlib development team') + 'team; 2012 - 2018 The Matplotlib development team') # The default replacements for |version| and |release|, also used in various # other places throughout the built documents. diff --git a/doc/sphinxext/mock_gui_toolkits.py b/doc/sphinxext/mock_gui_toolkits.py index 9e786f318782..bb378e77382c 100644 --- a/doc/sphinxext/mock_gui_toolkits.py +++ b/doc/sphinxext/mock_gui_toolkits.py @@ -118,15 +118,12 @@ class ToolBar(object): class Frame(object): pass - VERSION_STRING = '2.9' - def setup(app): - sys.modules['cairocffi'] = MyCairoCffi() - sys.modules['PyQt4'] = MyPyQt4() - sys.modules['sip'] = MySip() - sys.modules['wx'] = MyWX() - sys.modules['wxversion'] = MagicMock() - - metadata = {'parallel_read_safe': True, 'parallel_write_safe': True} - return metadata + sys.modules.update( + cairocffi=MyCairoCffi(), + PyQt4=MyPyQt4(), + sip=MySip(), + wx=MyWX(), + ) + return {'parallel_read_safe': True, 'parallel_write_safe': True} diff --git a/doc/users/next_whats_new/markevery_prop_cycle.rst b/doc/users/next_whats_new/markevery_prop_cycle.rst new file mode 100644 index 000000000000..05e647cbfa80 --- /dev/null +++ b/doc/users/next_whats_new/markevery_prop_cycle.rst @@ -0,0 +1,7 @@ +Implemented support for axes.prop_cycle property markevery in rcParams +---------------------------------------------------------------------- + +The Matplotlib ``rcParams`` settings object now supports configuration +of the attribute `axes.prop_cycle` with cyclers using the `markevery` +Line2D object property. An example of this feature is provided at +`~matplotlib/examples/lines_bars_and_markers/markevery_prop_cycle.py` \ No newline at end of file diff --git a/examples/lines_bars_and_markers/markevery_prop_cycle.py b/examples/lines_bars_and_markers/markevery_prop_cycle.py new file mode 100644 index 000000000000..e680ab2a0d98 --- /dev/null +++ b/examples/lines_bars_and_markers/markevery_prop_cycle.py @@ -0,0 +1,67 @@ +""" +================================================================= +Implemented support for prop_cycle property markevery in rcParams +================================================================= + +This example demonstrates a working solution to issue #8576, providing full +support of the markevery property for axes.prop_cycle assignments through +rcParams. Makes use of the same list of markevery cases from +https://matplotlib.org/examples/pylab_examples/markevery_demo.html + +Renders a plot with shifted-sine curves along each column with +a unique markevery value for each sine curve. +""" +from cycler import cycler +import numpy as np +import matplotlib as mpl +import matplotlib.pyplot as plt + +# Define a list of markevery cases and color cases to plot +cases = [None, + 8, + (30, 8), + [16, 24, 30], + [0, -1], + slice(100, 200, 3), + 0.1, + 0.3, + 1.5, + (0.0, 0.1), + (0.45, 0.1)] + +colors = ['#1f77b4', + '#ff7f0e', + '#2ca02c', + '#d62728', + '#9467bd', + '#8c564b', + '#e377c2', + '#7f7f7f', + '#bcbd22', + '#17becf', + '#1a55FF'] + +# Create two different cyclers to use with axes.prop_cycle +markevery_cycler = cycler(markevery=cases) +color_cycler = cycler('color', colors) + +# Configure rcParams axes.prop_cycle with custom cycler +custom_cycler = color_cycler + markevery_cycler +mpl.rcParams['axes.prop_cycle'] = custom_cycler + +# Create data points and offsets +x = np.linspace(0, 2 * np.pi) +offsets = np.linspace(0, 2 * np.pi, 11, endpoint=False) +yy = np.transpose([np.sin(x + phi) for phi in offsets]) + +# Set the plot curve with markers and a title +fig = plt.figure() +ax = fig.add_axes([0.1, 0.1, 0.6, 0.75]) + +for i in range(len(cases)): + ax.plot(yy[:, i], marker='o', label=str(cases[i])) + ax.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.) + +plt.title('Support for axes.prop_cycle cycler with markevery') + +plt.show() diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index b02bb7548944..9fff55f8b4d1 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -233,6 +233,7 @@ def _is_writable_dir(p): return os.access(p, os.W_OK) and os.path.isdir(p) _verbose_msg = """\ +matplotlib.verbose is deprecated; Command line argument --verbose-LEVEL is deprecated. This functionality is now provided by the standard python logging library. To get more (or less) logging output: @@ -297,7 +298,6 @@ def _parse_commandline(): _parse_commandline() -@cbook.deprecated("2.2", message=_verbose_msg) class Verbose(object): """ A class to handle reporting. Set the fileo attribute to any file @@ -320,10 +320,12 @@ class Verbose(object): if level_str in levels: _commandLineVerbose = level_str + @cbook.deprecated("2.2", message=_verbose_msg) def __init__(self): self.set_level('silent') self.fileo = sys.stdout + @cbook.deprecated("2.2", message=_verbose_msg) def set_level(self, level): 'set the verbosity to one of the Verbose.levels strings' @@ -335,6 +337,7 @@ def set_level(self, level): else: self.level = level + @cbook.deprecated("2.2", message=_verbose_msg) def set_fileo(self, fname): std = { 'sys.stdout': sys.stdout, @@ -352,6 +355,7 @@ def set_fileo(self, fname): else: self.fileo = fileo + @cbook.deprecated("2.2", message=_verbose_msg) def report(self, s, level='helpful'): """ print message s to self.fileo if self.level>=level. Return @@ -363,6 +367,7 @@ def report(self, s, level='helpful'): return True return False + @cbook.deprecated("2.2", message=_verbose_msg) def wrap(self, fmt, func, level='helpful', always=True): """ return a callable function that wraps func and reports it @@ -386,6 +391,7 @@ def wrapper(*args, **kwargs): wrapper.__doc__ = func.__doc__ return wrapper + @cbook.deprecated("2.2", message=_verbose_msg) def ge(self, level): 'return true if self.level is >= level' return self.vald[self.level] >= self.vald[level] diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py index 3bc1070cc789..586acad10542 100644 --- a/lib/matplotlib/animation.py +++ b/lib/matplotlib/animation.py @@ -667,8 +667,9 @@ def _args(self): '-s', '%dx%d' % self.frame_size, '-pix_fmt', self.frame_format, '-r', str(self.fps)] # Logging is quieted because subprocess.PIPE has limited buffer size. - - if (_log.getEffectiveLevel() < logging.DEBUG): + # If you have a lot of frames in your animation and set logging to + # DEBUG, you will have a buffer overrun. + if (_log.getEffectiveLevel() > logging.DEBUG): args += ['-loglevel', 'quiet'] args += ['-i', 'pipe:'] + self.output_args return args diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index b15e5af483dc..406ae8675200 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -1568,6 +1568,9 @@ def set_major_formatter(self, formatter): ACCEPTS: A :class:`~matplotlib.ticker.Formatter` instance """ + if not isinstance(formatter, mticker.Formatter): + raise TypeError("formatter argument should be instance of " + "matplotlib.ticker.Formatter") self.isDefault_majfmt = False self.major.formatter = formatter formatter.set_axis(self) @@ -1579,6 +1582,9 @@ def set_minor_formatter(self, formatter): ACCEPTS: A :class:`~matplotlib.ticker.Formatter` instance """ + if not isinstance(formatter, mticker.Formatter): + raise TypeError("formatter argument should be instance of " + "matplotlib.ticker.Formatter") self.isDefault_minfmt = False self.minor.formatter = formatter formatter.set_axis(self) @@ -1590,6 +1596,9 @@ def set_major_locator(self, locator): ACCEPTS: a :class:`~matplotlib.ticker.Locator` instance """ + if not isinstance(locator, mticker.Locator): + raise TypeError("formatter argument should be instance of " + "matplotlib.ticker.Locator") self.isDefault_majloc = False self.major.locator = locator locator.set_axis(self) @@ -1601,6 +1610,9 @@ def set_minor_locator(self, locator): ACCEPTS: a :class:`~matplotlib.ticker.Locator` instance """ + if not isinstance(locator, mticker.Locator): + raise TypeError("formatter argument should be instance of " + "matplotlib.ticker.Locator") self.isDefault_minloc = False self.minor.locator = locator locator.set_axis(self) diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py index 7fec6081f405..4aa6f667a93c 100644 --- a/lib/matplotlib/backend_bases.py +++ b/lib/matplotlib/backend_bases.py @@ -2130,6 +2130,8 @@ def print_figure(self, filename, dpi=None, facecolor=None, edgecolor=None, if format is None: # get format from filename, or from backend's default filetype + if isinstance(filename, getattr(os, "PathLike", ())): + filename = os.fspath(filename) if isinstance(filename, six.string_types): format = os.path.splitext(filename)[1][1:] if format is None or format == '': diff --git a/lib/matplotlib/backends/_backend_tk.py b/lib/matplotlib/backends/_backend_tk.py index 96a82d94a7a6..968fe48a6efd 100644 --- a/lib/matplotlib/backends/_backend_tk.py +++ b/lib/matplotlib/backends/_backend_tk.py @@ -336,11 +336,10 @@ def button_press_event(self, event, dblclick=False): y = self.figure.bbox.height - event.y num = getattr(event, 'num', None) - if sys.platform=='darwin': - # 2 and 3 were reversed on the OSX platform I - # tested under tkagg - if num==2: num=3 - elif num==3: num=2 + if sys.platform == 'darwin': + # 2 and 3 were reversed on the OSX platform I tested under tkagg. + if num == 2: num = 3 + elif num == 3: num = 2 FigureCanvasBase.button_press_event(self, x, y, num, dblclick=dblclick, guiEvent=event) @@ -354,11 +353,10 @@ def button_release_event(self, event): num = getattr(event, 'num', None) - if sys.platform=='darwin': - # 2 and 3 were reversed on the OSX platform I - # tested under tkagg - if num==2: num=3 - elif num==3: num=2 + if sys.platform == 'darwin': + # 2 and 3 were reversed on the OSX platform I tested under tkagg. + if num == 2: num = 3 + elif num == 3: num = 2 FigureCanvasBase.button_release_event(self, x, y, num, guiEvent=event) @@ -387,8 +385,8 @@ def _get_key(self, event): val = event.keysym_num if val in self.keyvald: key = self.keyvald[val] - elif val == 0 and sys.platform == 'darwin' and \ - event.keycode in self._keycode_lookup: + elif (val == 0 and sys.platform == 'darwin' + and event.keycode in self._keycode_lookup): key = self._keycode_lookup[event.keycode] elif val < 256: key = chr(val) diff --git a/lib/matplotlib/backends/backend_pgf.py b/lib/matplotlib/backends/backend_pgf.py index 9ad51010124d..36cfee0ee801 100644 --- a/lib/matplotlib/backends/backend_pgf.py +++ b/lib/matplotlib/backends/backend_pgf.py @@ -30,7 +30,7 @@ # create a list of system fonts, all of these should work with xe/lua-latex system_fonts = [] -if sys.platform.startswith('win'): +if sys.platform == 'win32': from matplotlib import font_manager for f in font_manager.win32InstalledFonts(): try: diff --git a/lib/matplotlib/backends/wx_compat.py b/lib/matplotlib/backends/wx_compat.py index 9dc4a87fffe1..87f6312299f4 100644 --- a/lib/matplotlib/backends/wx_compat.py +++ b/lib/matplotlib/backends/wx_compat.py @@ -11,27 +11,12 @@ unicode_literals) import six -from distutils.version import StrictVersion, LooseVersion -missingwx = "Matplotlib backend_wx and backend_wxagg require wxPython>=2.9" +import wx +backend_version = wx.VERSION_STRING +is_phoenix = 'phoenix' in wx.PlatformInfo -try: - import wx - backend_version = wx.VERSION_STRING - is_phoenix = 'phoenix' in wx.PlatformInfo -except ImportError: - raise ImportError(missingwx) - -try: - wx_version = StrictVersion(wx.VERSION_STRING) -except ValueError: - wx_version = LooseVersion(wx.VERSION_STRING) - -# Ensure we have the correct version imported -if wx_version < str("2.9"): - raise ImportError(missingwx) - if is_phoenix: # define all the wxPython phoenix stuff @@ -157,22 +142,11 @@ def _AddTool(parent, wx_ids, text, bmp, tooltip_text): else: add_tool = parent.DoAddTool - if not is_phoenix or wx_version >= str("4.0.0b2"): - # NOTE: when support for Phoenix prior to 4.0.0b2 is dropped then - # all that is needed is this clause, and the if and else clause can - # be removed. - kwargs = dict(label=text, - bitmap=bmp, - bmpDisabled=wx.NullBitmap, - shortHelp=text, - longHelp=tooltip_text, - kind=kind) - else: - kwargs = dict(label=text, - bitmap=bmp, - bmpDisabled=wx.NullBitmap, - shortHelpString=text, - longHelpString=tooltip_text, - kind=kind) + kwargs = dict(label=text, + bitmap=bmp, + bmpDisabled=wx.NullBitmap, + shortHelp=text, + longHelp=tooltip_text, + kind=kind) return add_tool(wx_ids[text], **kwargs) diff --git a/lib/matplotlib/cbook/__init__.py b/lib/matplotlib/cbook/__init__.py index acf1ffa3c2b1..629b66b46078 100644 --- a/lib/matplotlib/cbook/__init__.py +++ b/lib/matplotlib/cbook/__init__.py @@ -829,34 +829,34 @@ def report_memory(i=0): # argument may go away pid = os.getpid() if sys.platform == 'sunos5': try: - a2 = Popen(str('ps -p %d -o osz') % pid, shell=True, + a2 = Popen('ps -p %d -o osz' % pid, shell=True, stdout=PIPE).stdout.readlines() except OSError: raise NotImplementedError( "report_memory works on Sun OS only if " "the 'ps' program is found") mem = int(a2[-1].strip()) - elif sys.platform.startswith('linux'): + elif sys.platform == 'linux': try: - a2 = Popen(str('ps -p %d -o rss,sz') % pid, shell=True, + a2 = Popen('ps -p %d -o rss,sz' % pid, shell=True, stdout=PIPE).stdout.readlines() except OSError: raise NotImplementedError( "report_memory works on Linux only if " "the 'ps' program is found") mem = int(a2[1].split()[1]) - elif sys.platform.startswith('darwin'): + elif sys.platform == 'darwin': try: - a2 = Popen(str('ps -p %d -o rss,vsz') % pid, shell=True, + a2 = Popen('ps -p %d -o rss,vsz' % pid, shell=True, stdout=PIPE).stdout.readlines() except OSError: raise NotImplementedError( "report_memory works on Mac OS only if " "the 'ps' program is found") mem = int(a2[1].split()[0]) - elif sys.platform.startswith('win'): + elif sys.platform == 'win32': try: - a2 = Popen([str("tasklist"), "/nh", "/fi", "pid eq %d" % pid], + a2 = Popen(["tasklist", "/nh", "/fi", "pid eq %d" % pid], stdout=PIPE).stdout.read() except OSError: raise NotImplementedError( diff --git a/lib/matplotlib/dates.py b/lib/matplotlib/dates.py index e0d487b197cf..3a8c0e4fc96d 100644 --- a/lib/matplotlib/dates.py +++ b/lib/matplotlib/dates.py @@ -1212,8 +1212,17 @@ def __init__(self, tz=None, minticks=5, maxticks=None, locator = AutoDateLocator() locator.intervald[HOURLY] = [3] # only show every 3 hours + + In order to avoid overlapping dates, another dictionary was + created to map date intervals to the format of the date used in + rcParams. In addition, the default width of figsize from rcparams + (rcParams["figure.figsize"][0]) is used to get a estimate of the + number of date ticks we can fit in the axis. This allows customization + by using rcParam's date format and figsize. + """ DateLocator.__init__(self, tz) + self._locator = YearLocator() self._freq = YEARLY self._freqs = [YEARLY, MONTHLY, DAILY, HOURLY, MINUTELY, @@ -1222,6 +1231,7 @@ def __init__(self, tz=None, minticks=5, maxticks=None, self.maxticks = {YEARLY: 11, MONTHLY: 12, DAILY: 11, HOURLY: 12, MINUTELY: 11, SECONDLY: 11, MICROSECONDLY: 8} + if maxticks is not None: try: self.maxticks.update(maxticks) @@ -1242,6 +1252,16 @@ def __init__(self, tz=None, minticks=5, maxticks=None, MICROSECONDLY: [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000]} + + self.eachtick = { + YEARLY: rcParams['date.autoformatter.year'], + MONTHLY: rcParams['date.autoformatter.month'], + DAILY: rcParams['date.autoformatter.day'], + HOURLY: rcParams['date.autoformatter.hour'], + MINUTELY: rcParams['date.autoformatter.minute'], + SECONDLY: rcParams['date.autoformatter.second'], + MICROSECONDLY: rcParams['date.autoformatter.microsecond']} + self._byranges = [None, range(1, 13), range(1, 32), range(0, 24), range(0, 60), range(0, 60), None] @@ -1314,11 +1334,18 @@ def get_locator(self, dmin, dmax): # bysecond, unused (for microseconds)] byranges = [None, 1, 1, 0, 0, 0, None] + # estimated font ratio since our estimation + # is on font size 10 + font_ratio = (rcParams['font.size'])/10 + + # a ratio of 10 date characters per inch is 'estimated' + maxwid = rcParams["figure.figsize"][0] * 10 + # Loop over all the frequencies and try to find one that gives at # least a minticks tick positions. Once this is found, look for # an interval from an list specific to that frequency that gives no # more than maxticks tick positions. Also, set up some ranges - # (bymonth, etc.) as appropriate to be passed to rrulewrapper. + # (bymonth, etc.) as appropriate to be passed to rrulewrapper for i, (freq, num) in enumerate(zip(self._freqs, nums)): # If this particular frequency doesn't give enough ticks, continue if num < self.minticks: @@ -1328,11 +1355,24 @@ def get_locator(self, dmin, dmax): byranges[i] = None continue + # Compute at runtime the size of date label with given format + try: + # ensure yaxis ticks are not reduced + if (self.axis.axis_name == 'x'): + date_len = len(dmin.strftime(self.eachtick[freq])) + 1 + else: + date_len = 1 + except AttributeError: + date_len = 1 + # Find the first available interval that doesn't give too many # ticks for interval in self.intervald[freq]: - if num <= interval * (self.maxticks[freq] - 1): - break + if (num <= interval * (self.maxticks[freq] - 1)): + # Using an estmation of characters per inch, reduce + # intervals untill we get no overlaps + if ((num/interval) * date_len * font_ratio <= maxwid): + break else: # We went through the whole loop without breaking, default to # the last interval in the list and raise a warning @@ -1344,7 +1384,6 @@ def get_locator(self, dmin, dmax): # Set some parameters as appropriate self._freq = freq - if self._byranges[i] and self.interval_multiples: byranges[i] = self._byranges[i][::interval] interval = 1 diff --git a/lib/matplotlib/lines.py b/lib/matplotlib/lines.py index 709061e4bc63..ec5a522d328a 100644 --- a/lib/matplotlib/lines.py +++ b/lib/matplotlib/lines.py @@ -378,9 +378,9 @@ def __init__(self, xdata, ydata, self._us_dashSeq = None self._us_dashOffset = 0 + self.set_linewidth(linewidth) self.set_linestyle(linestyle) self.set_drawstyle(drawstyle) - self.set_linewidth(linewidth) self._color = None self.set_color(color) diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index af96195b44cb..3acec6d77a48 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -73,9 +73,10 @@ ## Backend detection ## def _backend_selection(): - """ If rcParams['backend_fallback'] is true, check to see if the - current backend is compatible with the current running event - loop, and if not switches to a compatible one. + """ + If rcParams['backend_fallback'] is true, check to see if the + current backend is compatible with the current running event loop, + and if not switches to a compatible one. """ backend = rcParams['backend'] if not rcParams['backend_fallback'] or backend not in _interactive_bk: @@ -103,6 +104,7 @@ def _backend_selection(): # import Tkinter pass # what if anything do we need to do for tkinter? + _backend_selection() ## Global ## @@ -169,7 +171,7 @@ def post_execute(): def uninstall_repl_displayhook(): """ - Uninstalls the matplotlib display hook. + Uninstall the matplotlib display hook. .. warning @@ -249,20 +251,18 @@ def show(*args, **kw): def isinteractive(): - """ - Return status of interactive mode. - """ + """Return the status of interactive mode.""" return matplotlib.is_interactive() def ioff(): - """Turn interactive mode off.""" + """Turn the interactive mode off.""" matplotlib.interactive(False) uninstall_repl_displayhook() def ion(): - """Turn interactive mode on.""" + """Turn the interactive mode on.""" matplotlib.interactive(True) install_repl_displayhook() @@ -675,9 +675,7 @@ def close(*args): def clf(): - """ - Clear the current figure. - """ + """Clear the current figure.""" gcf().clf() diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index a4c86779ba4e..99e445863877 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -534,7 +534,54 @@ def validate_ps_distiller(s): _validate_negative_linestyle = ValidateInStrings('negative_linestyle', ['solid', 'dashed'], ignorecase=True) +def validate_markevery(s): + """ + Validate the markevery property of a Line2D object. + + Parameters + ---------- + s : None, int, float, slice, length-2 tuple of ints, + length-2 tuple of floats, list of ints + + Returns + ------- + s : None, int, float, slice, length-2 tuple of ints, + length-2 tuple of floats, list of ints + + """ + # Validate s against type slice + if isinstance(s, slice): + return s + # Validate s against type tuple + if isinstance(s, tuple): + tupMaxLength = 2 + tupType = type(s[0]) + if len(s) != tupMaxLength: + raise TypeError("'markevery' tuple must have a length of " + "%d" % (tupMaxLength)) + if tupType is int and not all(isinstance(e, int) for e in s): + raise TypeError("'markevery' tuple with first element of " + "type int must have all elements of type " + "int") + if tupType is float and not all(isinstance(e, float) for e in s): + raise TypeError("'markevery' tuple with first element of " + "type float must have all elements of type " + "float") + if tupType is not float and tupType is not int: + raise TypeError("'markevery' tuple contains an invalid type") + # Validate s against type list + elif isinstance(s, list): + if not all(isinstance(e, int) for e in s): + raise TypeError("'markevery' list must have all elements of " + "type int") + # Validate s against type float int and None + elif not isinstance(s, (float, int)): + if s is not None: + raise TypeError("'markevery' is of an invalid type") + + return s +validate_markeverylist = _listify_validator(validate_markevery) validate_legend_loc = ValidateInStrings( 'legend_loc', @@ -676,6 +723,7 @@ def validate_hatch(s): 'markersize': validate_floatlist, 'markeredgewidth': validate_floatlist, 'markeredgecolor': validate_colorlist, + 'markevery': validate_markeverylist, 'alpha': validate_floatlist, 'marker': validate_stringlist, 'hatch': validate_hatchlist, diff --git a/lib/matplotlib/tests/baseline_images/test_axes/date_timezone_x.png b/lib/matplotlib/tests/baseline_images/test_axes/date_timezone_x.png index b193acac1bab..b7cd6f9c3f7a 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/date_timezone_x.png and b/lib/matplotlib/tests/baseline_images/test_axes/date_timezone_x.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_axes/date_timezone_x_and_y.png b/lib/matplotlib/tests/baseline_images/test_axes/date_timezone_x_and_y.png index d39489636a7b..61c9c59f068d 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/date_timezone_x_and_y.png and b/lib/matplotlib/tests/baseline_images/test_axes/date_timezone_x_and_y.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_axes/fill_units.png b/lib/matplotlib/tests/baseline_images/test_axes/fill_units.png index 497154993f93..63a6e640a0c8 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/fill_units.png and b/lib/matplotlib/tests/baseline_images/test_axes/fill_units.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_axes/pcolor_datetime_axis.png b/lib/matplotlib/tests/baseline_images/test_axes/pcolor_datetime_axis.png index c5901ad07c98..06181011de75 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/pcolor_datetime_axis.png and b/lib/matplotlib/tests/baseline_images/test_axes/pcolor_datetime_axis.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_axes/pcolormesh_datetime_axis.png b/lib/matplotlib/tests/baseline_images/test_axes/pcolormesh_datetime_axis.png index c5901ad07c98..06181011de75 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/pcolormesh_datetime_axis.png and b/lib/matplotlib/tests/baseline_images/test_axes/pcolormesh_datetime_axis.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_contour/contour_datetime_axis.png b/lib/matplotlib/tests/baseline_images/test_contour/contour_datetime_axis.png index 91d04aa441e5..b947c81c65e8 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_contour/contour_datetime_axis.png and b/lib/matplotlib/tests/baseline_images/test_contour/contour_datetime_axis.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_dates/DateFormatter_fractionalSeconds.png b/lib/matplotlib/tests/baseline_images/test_dates/DateFormatter_fractionalSeconds.png index 67c50f3eded3..867a38bd890c 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_dates/DateFormatter_fractionalSeconds.png and b/lib/matplotlib/tests/baseline_images/test_dates/DateFormatter_fractionalSeconds.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_dates/datetime_daily_overlap.png b/lib/matplotlib/tests/baseline_images/test_dates/datetime_daily_overlap.png new file mode 100644 index 000000000000..93a4eeed96ca Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_dates/datetime_daily_overlap.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_dates/datetime_hourly_overlap.png b/lib/matplotlib/tests/baseline_images/test_dates/datetime_hourly_overlap.png new file mode 100644 index 000000000000..ccc712fcdf80 Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_dates/datetime_hourly_overlap.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_dates/datetime_minutely_overlap.png b/lib/matplotlib/tests/baseline_images/test_dates/datetime_minutely_overlap.png new file mode 100644 index 000000000000..c437895ef60e Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_dates/datetime_minutely_overlap.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_dates/datetime_monthly_overlap.png b/lib/matplotlib/tests/baseline_images/test_dates/datetime_monthly_overlap.png new file mode 100644 index 000000000000..57f0362633e2 Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_dates/datetime_monthly_overlap.png differ diff --git a/lib/matplotlib/tests/test_dates.py b/lib/matplotlib/tests/test_dates.py index e4af37827593..ff24d57bcb19 100644 --- a/lib/matplotlib/tests/test_dates.py +++ b/lib/matplotlib/tests/test_dates.py @@ -10,6 +10,7 @@ from matplotlib.testing.decorators import image_comparison import matplotlib.pyplot as plt import matplotlib.dates as mdates +from matplotlib import rcParams def test_date_numpyx(): @@ -405,12 +406,12 @@ def _create_auto_date_locator(date1, date2): '2180-01-01 00:00:00+00:00', '2200-01-01 00:00:00+00:00'] ], [datetime.timedelta(weeks=52), - ['1997-01-01 00:00:00+00:00', '1997-02-01 00:00:00+00:00', - '1997-03-01 00:00:00+00:00', '1997-04-01 00:00:00+00:00', - '1997-05-01 00:00:00+00:00', '1997-06-01 00:00:00+00:00', - '1997-07-01 00:00:00+00:00', '1997-08-01 00:00:00+00:00', - '1997-09-01 00:00:00+00:00', '1997-10-01 00:00:00+00:00', - '1997-11-01 00:00:00+00:00', '1997-12-01 00:00:00+00:00'] + ['1997-01-01 00:00:00+00:00', '1997-02-01 00:00:00+00:00', + '1997-03-01 00:00:00+00:00', '1997-04-01 00:00:00+00:00', + '1997-05-01 00:00:00+00:00', '1997-06-01 00:00:00+00:00', + '1997-07-01 00:00:00+00:00', '1997-08-01 00:00:00+00:00', + '1997-09-01 00:00:00+00:00', '1997-10-01 00:00:00+00:00', + '1997-11-01 00:00:00+00:00', '1997-12-01 00:00:00+00:00'] ], [datetime.timedelta(days=141), ['1997-01-01 00:00:00+00:00', '1997-01-22 00:00:00+00:00', @@ -453,7 +454,6 @@ def _create_auto_date_locator(date1, date2): '1997-01-01 00:00:00.001500+00:00'] ], ) - for t_delta, expected in results: d2 = d1 + t_delta locator = _create_auto_date_locator(d1, d2) @@ -612,3 +612,47 @@ def test_tz_utc(): def test_num2timedelta(x, tdelta): dt = mdates.num2timedelta(x) assert dt == tdelta + + +@image_comparison(baseline_images=['datetime_daily_overlap'], + extensions=['png']) +def test_datetime_daily_overlap(): + # issue 7712 for overlapping daily dates + plt.rcParams['date.autoformatter.day'] = "%Y-%m-%d" + plt.rcParams['xtick.major.pad'] = 8 + dates = [datetime.datetime(2018, 1, i) for i in range(1, 30)] + values = list(range(1, 30)) + plt.plot(dates, values) + + +@image_comparison(baseline_images=['datetime_monthly_overlap'], + extensions=['png']) +def test_datetime_monthly_overlap(): + # issue 7712 for overlapping monthly dates + plt.rcParams['date.autoformatter.month'] = '%Y-%m' + plt.rcParams['xtick.major.pad'] = '8' + dates = [datetime.datetime(2018, i, 1) for i in range(1, 11)] + values = list(range(1, 11)) + plt.plot(dates, values) + + +@image_comparison(baseline_images=['datetime_hourly_overlap'], + extensions=['png']) +def test_datetime_hourly_overlap(): + # issue 7712 for overlapping hourly dates + plt.rcParams['date.autoformatter.hour'] = '%m-%d %H' + plt.rcParams['xtick.major.pad'] = '8' + dates = [datetime.datetime(2018, 1, 1, i) for i in range(1, 20)] + values = list(range(1, 20)) + plt.plot(dates, values) + + +@image_comparison(baseline_images=['datetime_minutely_overlap'], + extensions=['png']) +def test_datetime_minutely_overlap(): + # issue 7712 for overlapping date ticks in second intervals + plt.rcParams['date.autoformatter.minute'] = '%d %H:%M' + plt.rcParams['xtick.major.pad'] = '8' + dates = [datetime.datetime(2018, 1, 1, 1, i) for i in range(1, 55)] + values = list(range(1, 55)) + plt.plot(dates, values) diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index 93d2639056ac..229ce192cc75 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -1,6 +1,5 @@ from __future__ import absolute_import, division, print_function -import os import sys import warnings @@ -379,6 +378,11 @@ def test_figure_repr(): @pytest.mark.skipif(sys.version_info < (3, 6), reason="requires Python 3.6+") @pytest.mark.parametrize("fmt", ["png", "pdf", "ps", "eps", "svg"]) -def test_fspath(fmt): +def test_fspath(fmt, tmpdir): from pathlib import Path - plt.savefig(Path(os.devnull), format=fmt) + out = Path(tmpdir, "test.{}".format(fmt)) + plt.savefig(out) + with out.open("rb") as file: + # All the supported formats include the format name (case-insensitive) + # in the first 100 bytes. + assert fmt.encode("ascii") in file.read(100).lower() diff --git a/lib/matplotlib/tests/test_rcparams.py b/lib/matplotlib/tests/test_rcparams.py index a4fd6fd0e96a..51ea501474e2 100644 --- a/lib/matplotlib/tests/test_rcparams.py +++ b/lib/matplotlib/tests/test_rcparams.py @@ -23,6 +23,7 @@ validate_cycler, validate_hatch, validate_hist_bins, + validate_markevery, _validate_linestyle) @@ -326,6 +327,35 @@ def generate_validator_testcases(valid): ), 'fail': (('aardvark', ValueError), ) + }, + {'validator': validate_markevery, + 'success': ((None, None), + (1, 1), + (0.1, 0.1), + ((1, 1), (1, 1)), + ((0.1, 0.1), (0.1, 0.1)), + ([1, 2, 3], [1, 2, 3]), + (slice(2), slice(None, 2, None)), + (slice(1, 2, 3), slice(1, 2, 3)) + ), + 'fail': (((1, 2, 3), TypeError), + ([1, 2, 0.3], TypeError), + (['a', 2, 3], TypeError), + ([1, 2, 'a'], TypeError), + ((0.1, 0.2, 0.3), TypeError), + ((0.1, 2, 3), TypeError), + ((1, 0.2, 0.3), TypeError), + ((1, 0.1), TypeError), + ((0.1, 1), TypeError), + (('abc'), TypeError), + ((1, 'a'), TypeError), + ((0.1, 'b'), TypeError), + (('a', 1), TypeError), + (('a', 0.1), TypeError), + ('abc', TypeError), + ('a', TypeError), + (object(), TypeError) + ) } ) diff --git a/lib/matplotlib/tests/test_ticker.py b/lib/matplotlib/tests/test_ticker.py index 32206a0c6168..da2227e6805f 100644 --- a/lib/matplotlib/tests/test_ticker.py +++ b/lib/matplotlib/tests/test_ticker.py @@ -728,3 +728,27 @@ def test_latex(self, is_latex, usetex, expected): fmt = mticker.PercentFormatter(symbol='\\{t}%', is_latex=is_latex) with matplotlib.rc_context(rc={'text.usetex': usetex}): assert fmt.format_pct(50, 100) == expected + + +def test_majformatter_type(): + fig, ax = plt.subplots() + with pytest.raises(TypeError): + ax.xaxis.set_major_formatter(matplotlib.ticker.LogLocator()) + + +def test_minformatter_type(): + fig, ax = plt.subplots() + with pytest.raises(TypeError): + ax.xaxis.set_minor_formatter(matplotlib.ticker.LogLocator()) + + +def test_majlocator_type(): + fig, ax = plt.subplots() + with pytest.raises(TypeError): + ax.xaxis.set_major_locator(matplotlib.ticker.LogFormatter()) + + +def test_minlocator_type(): + fig, ax = plt.subplots() + with pytest.raises(TypeError): + ax.xaxis.set_minor_locator(matplotlib.ticker.LogFormatter()) diff --git a/lib/matplotlib/text.py b/lib/matplotlib/text.py index 82a302c269ed..2a3c02a17af2 100644 --- a/lib/matplotlib/text.py +++ b/lib/matplotlib/text.py @@ -163,8 +163,8 @@ def __init__(self, self.set_color(color) self.set_usetex(usetex) self.set_wrap(wrap) - self._verticalalignment = verticalalignment - self._horizontalalignment = horizontalalignment + self.set_verticalalignment(verticalalignment) + self.set_horizontalalignment(horizontalalignment) self._multialignment = multialignment self._rotation = rotation self._fontproperties = fontproperties @@ -1147,9 +1147,10 @@ def set_verticalalignment(self, align): """ Set the vertical alignment - ACCEPTS: [ 'center' | 'top' | 'bottom' | 'baseline' ] + ACCEPTS: [ 'center' | 'top' | 'bottom' | 'baseline' | + 'center_baseline' ] """ - legal = ('top', 'bottom', 'center', 'baseline') + legal = ('top', 'bottom', 'center', 'baseline', 'center_baseline') if align not in legal: raise ValueError('Vertical alignment must be one of %s' % str(legal)) diff --git a/lib/mpl_toolkits/axisartist/axislines.py b/lib/mpl_toolkits/axisartist/axislines.py index 43a9ad04e04a..ee9faddf31b7 100644 --- a/lib/mpl_toolkits/axisartist/axislines.py +++ b/lib/mpl_toolkits/axisartist/axislines.py @@ -109,36 +109,26 @@ def get_tick_iterators(self, axes): """ class _Base(object): - """ - Base class for axis helper. - """ + """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. - """ + """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, - ): + 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"]: @@ -156,8 +146,6 @@ def __init__(self, self.passthru_pt = self._default_passthru_pt[loc] - - _verts = np.array([[0., 0.], [1., 1.]]) fixed_coord = 1-nth_coord @@ -166,7 +154,6 @@ def __init__(self, # axis line in transAxes self._path = Path(_verts) - def get_nth_coord(self): return self.nth_coord @@ -197,8 +184,6 @@ def get_axislabel_pos_angle(self, axes): return pos, angle_tangent - - # TICK def get_tick_transform(self, axes): @@ -221,8 +206,6 @@ def get_line(self, axes): raise RuntimeError("get_line method should be defined by the derived class") - - class AxisArtistHelperRectlinear(object): class Fixed(AxisArtistHelper.Fixed): @@ -275,8 +258,6 @@ def _f(locs, labels): return _f(majorLocs, majorLabels), _f(minorLocs, minorLabels) - - class Floating(AxisArtistHelper.Floating): def __init__(self, axes, nth_coord, passingthrough_point, axis_direction="bottom"): @@ -331,12 +312,9 @@ def get_axislabel_pos_angle(self, axes): 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""" @@ -352,7 +330,7 @@ def get_tick_iterators(self, axes): else: angle_normal, angle_tangent = 0, 90 - #angle = 90 - 90 * self.nth_coord + # angle = 90 - 90 * self.nth_coord major = self.axis.major majorLocs = major.locator() @@ -381,9 +359,6 @@ def _f(locs, labels): return _f(majorLocs, majorLabels), _f(minorLocs, minorLabels) - - - class GridHelperBase(object): def __init__(self): @@ -391,7 +366,6 @@ def __init__(self): self._old_limits = None super().__init__() - def update_lim(self, axes): x1, x2 = axes.get_xlim() y1, y2 = axes.get_ylim() @@ -401,18 +375,15 @@ def update_lim(self, axes): 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). @@ -447,14 +418,10 @@ def new_gridlines(self, ax): class GridHelperRectlinear(GridHelperBase): - def __init__(self, axes): - super().__init__() self.axes = axes - - def new_fixed_axis(self, loc, nth_coord=None, axis_direction=None, @@ -476,7 +443,6 @@ def new_fixed_axis(self, loc, return axisline - def new_floating_axis(self, nth_coord, value, axis_direction="bottom", axes=None, @@ -499,7 +465,6 @@ def new_floating_axis(self, nth_coord, value, 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. @@ -507,32 +472,25 @@ def get_gridlines(self, which="major", axis="both"): *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: @@ -541,10 +499,6 @@ def get_gridlines(self, which="major", axis="both"): return gridlines - - - - class SimpleChainedObjects(object): def __init__(self, objects): self._objects = objects @@ -581,24 +535,13 @@ def __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) - + def __init__(self, *args, grid_helper=None, **kwargs): self._axisline_on = True - - if helper: - self._grid_helper = helper - else: - self._grid_helper = GridHelperRectlinear(self) - - super().__init__(*kl, **kw) - + self._grid_helper = (grid_helper if grid_helper + else GridHelperRectlinear(self)) + super().__init__(*args, **kwargs) self.toggle_axisline(True) - def toggle_axisline(self, b=None): if b is None: b = not self._axisline_on @@ -615,11 +558,9 @@ def toggle_axisline(self, b=None): self.xaxis.set_visible(True) self.yaxis.set_visible(True) - def _init_axis(self): super()._init_axis() - def _init_axis_artists(self, axes=None): if axes is None: axes = self @@ -651,19 +592,14 @@ def new_gridlines(self, grid_helper=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 + self.gridlines = self.new_gridlines(grid_helper) def cla(self): # gridlines need to b created before cla() since cla calls grid() - self._init_gridlines() super().cla() @@ -676,7 +612,6 @@ def cla(self): 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. @@ -715,7 +650,6 @@ def get_children(self): 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, @@ -727,9 +661,7 @@ def new_fixed_axis(self, loc, offset=None): return axis - def new_floating_axis(self, nth_coord, value, - axis_direction="bottom", - ): + 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, diff --git a/setupext.py b/setupext.py index 37679d9f3bb3..a608d2fc9ab3 100644 --- a/setupext.py +++ b/setupext.py @@ -565,7 +565,7 @@ def _try_managers(*managers): .format(url, self.name)) elif sys.platform == "darwin": message = _try_managers("brew", "port") - elif sys.platform.startswith("linux"): + elif sys.platform == "linux": release = platform.linux_distribution()[0].lower() if release in ('debian', 'ubuntu'): message = _try_managers('apt-get') @@ -1421,7 +1421,7 @@ def add_flags(self, ext): if sys.platform == 'win32': # PSAPI library needed for finding Tcl / Tk at run time ext.libraries.extend(['psapi']) - elif sys.platform.startswith('linux'): + elif sys.platform == 'linux': ext.libraries.extend(['dl']) @@ -1567,33 +1567,12 @@ class BackendWxAgg(OptionalBackendPackage): name = "wxagg" def check_requirements(self): - wxversioninstalled = True - try: - import wxversion - except ImportError: - wxversioninstalled = False - - if wxversioninstalled: - try: - _wx_ensure_failed = wxversion.AlreadyImportedError - except AttributeError: - _wx_ensure_failed = wxversion.VersionError - - try: - wxversion.ensureMinimal('2.9') - except _wx_ensure_failed: - pass - try: import wx backend_version = wx.VERSION_STRING except ImportError: raise CheckFailed("requires wxPython") - if not is_min_version(backend_version, "2.9"): - raise CheckFailed( - "Requires wxPython 2.9, found %s" % backend_version) - return "version %s" % backend_version diff --git a/src/_image_wrapper.cpp b/src/_image_wrapper.cpp index 4879eee3f0fb..a4c0e81db9ad 100644 --- a/src/_image_wrapper.cpp +++ b/src/_image_wrapper.cpp @@ -352,13 +352,12 @@ static PyObject *image_pcolor(PyObject *self, PyObject *args, PyObject *kwds) numpy::array_view x; numpy::array_view y; numpy::array_view d; - unsigned int rows; - unsigned int cols; + npy_intp rows, cols; float bounds[4]; int interpolation; if (!PyArg_ParseTuple(args, - "O&O&O&II(ffff)i:pcolor", + "O&O&O&nn(ffff)i:pcolor", &x.converter, &x, &y.converter, @@ -396,13 +395,12 @@ static PyObject *image_pcolor2(PyObject *self, PyObject *args, PyObject *kwds) numpy::array_view x; numpy::array_view y; numpy::array_view d; - unsigned int rows; - unsigned int cols; + npy_intp rows, cols; float bounds[4]; numpy::array_view bg; if (!PyArg_ParseTuple(args, - "O&O&O&II(ffff)O&:pcolor2", + "O&O&O&nn(ffff)O&:pcolor2", &x.converter_contiguous, &x, &y.converter_contiguous, diff --git a/tutorials/introductory/usage.py b/tutorials/introductory/usage.py index 5d56b9f4a3b6..fde76daf7532 100644 --- a/tutorials/introductory/usage.py +++ b/tutorials/introductory/usage.py @@ -437,9 +437,8 @@ def my_plotter(ax, data1, data2, param_dict): # Qt4Agg Agg rendering to a :term:`Qt4` canvas (requires PyQt4_ or # ``pyside``). This backend can be activated in IPython with # ``%matplotlib qt4``. -# WXAgg Agg rendering to a :term:`wxWidgets` canvas (requires wxPython_; -# v4.0 (in beta) is required for Python3). This backend can be -# activated in IPython with ``%matplotlib wx``.# +# WXAgg Agg rendering to a :term:`wxWidgets` canvas (requires wxPython_ 4). +# This backend can be activated in IPython with ``%matplotlib wx``. # ========= ================================================================ # # .. _`Anti-Grain Geometry`: http://antigrain.com/ diff --git a/tutorials/text/annotations.py b/tutorials/text/annotations.py index 709aaab7c373..5706e08cdc75 100644 --- a/tutorials/text/annotations.py +++ b/tutorials/text/annotations.py @@ -516,11 +516,11 @@ You may take a look at this example :ref:`sphx_glr_gallery_text_labels_and_annotations_annotation_demo.py`. -Using ConnectorPatch --------------------- +Using ConnectionPatch +--------------------- -The ConnectorPatch is like an annotation without text. While the annotate -function is recommended in most situations, the ConnectorPatch is useful when +The ConnectionPatch is like an annotation without text. While the annotate +function is recommended in most situations, the ConnectionPatch is useful when you want to connect points in different axes. :: from matplotlib.patches import ConnectionPatch @@ -540,7 +540,7 @@ Connect Simple01 -While the ConnectorPatch instance can be added to any axes, you may want to add +While the ConnectionPatch instance can be added to any axes, you may want to add it to the axes that is latest in drawing order to prevent overlap by other axes.