diff --git a/doc/api/api_changes/README.rst b/doc/api/api_changes/README.rst new file mode 100644 index 000000000000..f317cab10d41 --- /dev/null +++ b/doc/api/api_changes/README.rst @@ -0,0 +1,9 @@ +For changes which require an entry in `api_changes.rst` please create +a file in this folder with the name :file:`YYYY-MM-DD-[initials].rst` +(ex :file:`2014-07-31-TAC.rst`) with contents following the form: :: + + Brief description of change + ``````````````````````````` + + Long description of change, justification, and work-arounds to + maintain old behavior (if any). diff --git a/doc/faq/usage_faq.rst b/doc/faq/usage_faq.rst index 26c00198dfcc..1dcd7f7b7cc9 100644 --- a/doc/faq/usage_faq.rst +++ b/doc/faq/usage_faq.rst @@ -114,6 +114,27 @@ idea). When the figure is rendered, all of the artists are drawn to the **canvas**. Most Artists are tied to an Axes; such an Artist cannot be shared by multiple Axes, or moved from one to another. +.. _input_types: + +Types of inputs to plotting functions +===================================== + +All of plotting functions expect `np.array` or `np.ma.masked_array` as +input. Classes that are 'array-like' such as `pandas` data objects +and `np.matrix` may or may not work as intended. It is best to +convert these to `np.array` objects prior to plotting. + +For example, to covert a `pandas.DataFrame` :: + + a = pandas.DataFrame(np.random.rand(4,5), columns = list('abcde')) + a_asndarray = a.values + +and to covert a `np.matrix` :: + + b = np.matrix([[1,2],[3,4]]) + b_asarray = np.asarray(b) + + .. _pylab: diff --git a/doc/users/annotations_guide.rst b/doc/users/annotations_guide.rst index fa585eb9e30e..70ef8c42fdaf 100644 --- a/doc/users/annotations_guide.rst +++ b/doc/users/annotations_guide.rst @@ -46,6 +46,8 @@ keyword arguments. Currently, following box styles are implemented. ========== ============== ========================== Class Name Attrs ========== ============== ========================== + Circle ``circle`` pad=0.3 + DArrow ``darrow`` pad=0.3 LArrow ``larrow`` pad=0.3 RArrow ``rarrow`` pad=0.3 Round ``round`` pad=0.3,rounding_size=None diff --git a/doc/users/whats_new/README.rst b/doc/users/whats_new/README.rst new file mode 100644 index 000000000000..dd8e4a8a5214 --- /dev/null +++ b/doc/users/whats_new/README.rst @@ -0,0 +1,16 @@ +This folder is for placing new portions of `whats_new.rst`. + +When adding an entry please look at the currently existing files to +see if you can extend any of them. If you create a file, name it +something like :file:`cool_new_feature.rst` if you have added a brand new +feature or something like :file:`updated_feature.rst` for extensions of +existing features. Include contents of the form: :: + + Section Title for Feature + ------------------------- + + A bunch of text about how awesome the new feature is and examples of how + to use it. + + A sub-section + ````````````` diff --git a/examples/pylab_examples/fancybox_demo2.py b/examples/pylab_examples/fancybox_demo2.py index 43a04a876b69..ae6cb99b680e 100644 --- a/examples/pylab_examples/fancybox_demo2.py +++ b/examples/pylab_examples/fancybox_demo2.py @@ -2,13 +2,14 @@ import matplotlib.pyplot as plt styles = mpatch.BoxStyle.get_styles() +spacing = 1.2 -figheight = (len(styles)+.5) +figheight = (spacing * len(styles) + .5) fig1 = plt.figure(1, (4/1.5, figheight/1.5)) fontsize = 0.3 * 72 -for i, (stylename, styleclass) in enumerate(styles.items()): - fig1.text(0.5, (float(len(styles)) - 0.5 - i)/figheight, stylename, +for i, stylename in enumerate(sorted(styles.keys())): + fig1.text(0.5, (spacing * (float(len(styles)) - i) - 0.5)/figheight, stylename, ha="center", size=fontsize, transform=fig1.transFigure, diff --git a/examples/user_interfaces/embedding_in_tk2.py b/examples/user_interfaces/embedding_in_tk2.py index 9e2a524a1b2d..c762873e5972 100644 --- a/examples/user_interfaces/embedding_in_tk2.py +++ b/examples/user_interfaces/embedding_in_tk2.py @@ -3,7 +3,7 @@ matplotlib.use('TkAgg') from numpy import arange, sin, pi -from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.figure import Figure import sys @@ -12,19 +12,20 @@ else: import tkinter as Tk -def destroy(e): sys.exit() + +def destroy(e): + sys.exit() root = Tk.Tk() root.wm_title("Embedding in TK") -#root.bind("", destroy) -f = Figure(figsize=(5,4), dpi=100) +f = Figure(figsize=(5, 4), dpi=100) a = f.add_subplot(111) -t = arange(0.0,3.0,0.01) +t = arange(0.0, 3.0, 0.01) s = sin(2*pi*t) -a.plot(t,s) +a.plot(t, s) a.set_title('Tk embedding') a.set_xlabel('X axis label') a.set_ylabel('Y label') @@ -35,8 +36,6 @@ def destroy(e): sys.exit() canvas.show() canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) -#toolbar = NavigationToolbar2TkAgg( canvas, root ) -#toolbar.update() canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) button = Tk.Button(master=root, text='Quit', command=sys.exit) diff --git a/examples/user_interfaces/embedding_in_wx2.py b/examples/user_interfaces/embedding_in_wx2.py index 2fe9d09376b6..6e2b90941d79 100644 --- a/examples/user_interfaces/embedding_in_wx2.py +++ b/examples/user_interfaces/embedding_in_wx2.py @@ -4,9 +4,14 @@ toolbar - comment out the setA_toolbar line for no toolbar """ -# Used to guarantee to use at least Wx2.8 -import wxversion -wxversion.ensureMinimal('2.8') +import sys +if sys.version_info.major < 3: + # Used to guarantee to use at least Wx2.8 + import wxversion + wxversion.ensureMinimal('2.8') + #wxversion.select('2.8') + #wxversion.select('2.9.5') + #wxversion.select('3.0.2-phoenix', optionsRequired=True) from numpy import arange, sin, pi @@ -25,6 +30,10 @@ from matplotlib.figure import Figure import wx +print(wx.VERSION_STRING) +print(wx.PlatformInfo) +print(matplotlib.__version__) + class CanvasFrame(wx.Frame): @@ -32,7 +41,10 @@ def __init__(self): wx.Frame.__init__(self,None,-1, 'CanvasFrame',size=(550,350)) - self.SetBackgroundColour(wx.NamedColour("WHITE")) + if 'phoenix' in wx.PlatformInfo: + self.SetBackgroundColour(wx.Colour("WHITE")) + else: + self.SetBackgroundColour(wx.NamedColour("WHITE")) self.figure = Figure() self.axes = self.figure.add_subplot(111) @@ -48,7 +60,11 @@ def __init__(self): self.Fit() self.add_toolbar() # comment this out for no toolbar + self.Bind(wx.EVT_PAINT, self.OnPaint) + def OnPaint(self, event): + self.canvas.draw() + event.Skip() def add_toolbar(self): self.toolbar = NavigationToolbar2Wx(self.canvas) @@ -61,8 +77,12 @@ def add_toolbar(self): else: # On Windows platform, default window size is incorrect, so set # toolbar width to figure width. - tw, th = self.toolbar.GetSizeTuple() - fw, fh = self.canvas.GetSizeTuple() + if 'phoenix' in wx.PlatformInfo: + tw, th = self.toolbar.GetSize() + fw, fh = self.canvas.GetSize() + else: + tw, th = self.toolbar.GetSizeTuple() + fw, fh = self.canvas.GetSizeTuple() # By adding toolbar in sizer, we are able to put it at the bottom # of the frame - so appearance is closer to GTK version. # As noted above, doesn't work for Mac. diff --git a/examples/user_interfaces/embedding_in_wx3.py b/examples/user_interfaces/embedding_in_wx3.py index 931e043a5fd3..0f4060dd411d 100755 --- a/examples/user_interfaces/embedding_in_wx3.py +++ b/examples/user_interfaces/embedding_in_wx3.py @@ -23,7 +23,10 @@ # Used to guarantee to use at least Wx2.8 import wxversion -wxversion.ensureMinimal('2.8') +#wxversion.ensureMinimal('2.8') +#wxversion.select('2.8') +#wxversion.select('2.9.5') # 2.9.x classic +wxversion.select('3.0.1-msw-phoenix', optionsRequired=True) # 3.0 phoenix import sys, time, os, gc import matplotlib @@ -35,6 +38,9 @@ import numpy as np import wx + +print(wx.VERSION_STRING) + import wx.xrc as xrc ERR_TOL = 1e-5 # floating point slop for peak-detection @@ -61,6 +67,11 @@ def __init__(self, parent): sizer.Add(self.toolbar, 0, wx.GROW) self.SetSizer(sizer) self.Fit() + self.Bind(wx.EVT_PAINT, self.OnPaint) + + def OnPaint(self, event): + self.canvas.draw() + event.Skip() def init_plot_data(self): a = self.fig.add_subplot(111) @@ -132,14 +143,22 @@ def OnInit(self): # whiz button ------------------ whiz_button = xrc.XRCCTRL(self.frame,"whiz_button") - wx.EVT_BUTTON(whiz_button, whiz_button.GetId(), - self.plotpanel.OnWhiz) + + if 'phoenix' in wx.PlatformInfo: + whiz_button.Bind(wx.EVT_BUTTON, self.plotpanel.OnWhiz) + else: + wx.EVT_BUTTON(whiz_button, whiz_button.GetId(), + self.plotpanel.OnWhiz) # bang button ------------------ bang_button = xrc.XRCCTRL(self.frame,"bang_button") - wx.EVT_BUTTON(bang_button, bang_button.GetId(), - self.OnBang) + if 'phoenix' in wx.PlatformInfo: + bang_button.Bind(wx.EVT_BUTTON, self.OnBang) + + else: + wx.EVT_BUTTON(bang_button, bang_button.GetId(), + self.OnBang) # final setup ------------------ diff --git a/examples/user_interfaces/embedding_in_wx4.py b/examples/user_interfaces/embedding_in_wx4.py index 578be3b5da13..563c8c63cb31 100644 --- a/examples/user_interfaces/embedding_in_wx4.py +++ b/examples/user_interfaces/embedding_in_wx4.py @@ -4,9 +4,14 @@ toolbar """ -# Used to guarantee to use at least Wx2.8 -import wxversion -wxversion.ensureMinimal('2.8') +import sys +if sys.version_info.major < 3: + # Used to guarantee to use at least Wx2.8 + import wxversion + wxversion.ensureMinimal('2.8') + #wxversion.select('2.8') + #wxversion.select('2.9.5') + #wxversion.select('3.0.2-phoenix', optionsRequired=True) from numpy import arange, sin, pi @@ -32,9 +37,15 @@ def __init__(self, canvas, cankill): # for simplicity I'm going to reuse a bitmap from wx, you'll # probably want to add your own. - self.AddSimpleTool(self.ON_CUSTOM, _load_bitmap('stock_left.xpm'), - 'Click me', 'Activate custom contol') - wx.EVT_TOOL(self, self.ON_CUSTOM, self._on_custom) + if 'phoenix' in wx.PlatformInfo: + self.AddTool(self.ON_CUSTOM, 'Click me', + _load_bitmap('stock_left.xpm'), + 'Activate custom contol') + self.Bind(wx.EVT_TOOL, self._on_custom, id=self.ON_CUSTOM) + else: + self.AddSimpleTool(self.ON_CUSTOM, _load_bitmap('stock_left.xpm'), + 'Click me', 'Activate custom contol') + wx.EVT_TOOL(self, self.ON_CUSTOM, self._on_custom) def _on_custom(self, evt): # add some text to the axes in a random location in axes (0,1) @@ -61,7 +72,10 @@ def __init__(self): wx.Frame.__init__(self,None,-1, 'CanvasFrame',size=(550,350)) - self.SetBackgroundColour(wx.NamedColour("WHITE")) + if 'phoenix' in wx.PlatformInfo: + self.SetBackgroundColour(wx.Colour("WHITE")) + else: + self.SetBackgroundColour(wx.NamedColour("WHITE")) self.figure = Figure(figsize=(5,4), dpi=100) self.axes = self.figure.add_subplot(111) @@ -75,7 +89,7 @@ def __init__(self): self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND) # Capture the paint message - wx.EVT_PAINT(self, self.OnPaint) + self.Bind(wx.EVT_PAINT, self.OnPaint) self.toolbar = MyNavigationToolbar(self.canvas, True) self.toolbar.Realize() @@ -87,8 +101,12 @@ def __init__(self): else: # On Windows platform, default window size is incorrect, so set # toolbar width to figure width. - tw, th = self.toolbar.GetSizeTuple() - fw, fh = self.canvas.GetSizeTuple() + if 'phoenix' in wx.PlatformInfo: + tw, th = self.toolbar.GetSize() + fw, fh = self.canvas.GetSize() + else: + tw, th = self.toolbar.GetSizeTuple() + fw, fh = self.canvas.GetSizeTuple() # By adding toolbar in sizer, we are able to put it at the bottom # of the frame - so appearance is closer to GTK version. # As noted above, doesn't work for Mac. diff --git a/examples/user_interfaces/embedding_in_wx5.py b/examples/user_interfaces/embedding_in_wx5.py index fd3969aca881..c57fb32089cb 100644 --- a/examples/user_interfaces/embedding_in_wx5.py +++ b/examples/user_interfaces/embedding_in_wx5.py @@ -1,9 +1,22 @@ -# Used to guarantee to use at least Wx2.8 -import wxversion -wxversion.ensureMinimal('2.8') +#!/usr/bin/env python + +import sys +if sys.version_info.major < 3: + # Used to guarantee to use at least Wx2.8 + import wxversion + wxversion.ensureMinimal('2.8') + #wxversion.select('2.8') + #wxversion.select('2.9.5') + #wxversion.select('3.0.2-phoenix', optionsRequired=True) import wx -import wx.aui +print(wx.VERSION_STRING) + +if 'phoenix' in wx.PlatformInfo: + import wx.lib.agw.aui as aui +else: + import wx.aui as aui + import matplotlib as mpl from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas from matplotlib.backends.backend_wxagg import NavigationToolbar2Wx as Toolbar @@ -20,23 +33,30 @@ def __init__(self, parent, id = -1, dpi = None, **kwargs): sizer.Add(self.canvas,1,wx.EXPAND) sizer.Add(self.toolbar, 0 , wx.LEFT | wx.EXPAND) self.SetSizer(sizer) + self.Bind(wx.EVT_PAINT, self.OnPaint) + + def OnPaint(self, event): + self.canvas.draw() + event.Skip() + class PlotNotebook(wx.Panel): def __init__(self, parent, id = -1): wx.Panel.__init__(self, parent, id=id) - self.nb = wx.aui.AuiNotebook(self) + self.nb = aui.AuiNotebook(self) sizer = wx.BoxSizer() sizer.Add(self.nb, 1, wx.EXPAND) self.SetSizer(sizer) def add(self,name="plot"): - page = Plot(self.nb) - self.nb.AddPage(page,name) - return page.figure + page = Plot(self.nb) + self.nb.AddPage(page,name) + return page.figure def demo(): - app = wx.PySimpleApp() + import wx.lib.mixins.inspection as wit + app = wit.InspectableApp() frame = wx.Frame(None,-1,'Plotter') plotter = PlotNotebook(frame) axes1 = plotter.add('figure 1').gca() diff --git a/examples/user_interfaces/fourier_demo_wx.py b/examples/user_interfaces/fourier_demo_wx.py index aa52809ff1c0..268a01be5526 100644 --- a/examples/user_interfaces/fourier_demo_wx.py +++ b/examples/user_interfaces/fourier_demo_wx.py @@ -1,6 +1,18 @@ +#!/usr/bin/env python import numpy as np -import wx +import sys +if sys.version_info.major < 3: + # Used to guarantee to use at least Wx2.8 + import wxversion + wxversion.ensureMinimal('2.8') + #wxversion.select('2.8') + #wxversion.select('2.9.5') + #wxversion.select('3.0.2-phoenix', optionsRequired=True) + + +import wx +print(wx.VERSION_STRING) import matplotlib matplotlib.interactive(False) matplotlib.use('WXAgg') @@ -11,7 +23,7 @@ class Knob: """ - Knob - simple class with a "setKnob" method. + Knob - simple class with a "setKnob" method. A Knob instance is attached to a Param instance, e.g., param.attach(knob) Base class is for documentation purposes. """ @@ -24,8 +36,8 @@ class Param: The idea of the "Param" class is that some parameter in the GUI may have several knobs that both control it and reflect the parameter's state, e.g. a slider, text, and dragging can all change the value of the frequency in - the waveform of this example. - The class allows a cleaner way to update/"feedback" to the other knobs when + the waveform of this example. + The class allows a cleaner way to update/"feedback" to the other knobs when one is being changed. Also, this class handles min/max constraints for all the knobs. Idea - knob list - in "set" method, knob object is passed as well @@ -39,10 +51,10 @@ def __init__(self, initialValue=None, minimum=0., maximum=1.): raise ValueError('illegal initial value') self.value = initialValue self.knobs = [] - + def attach(self, knob): self.knobs += [knob] - + def set(self, value, knob=None): self.value = value self.value = self.constrain(value) @@ -64,9 +76,10 @@ def __init__(self, parent, label, param): self.sliderLabel = wx.StaticText(parent, label=label) self.sliderText = wx.TextCtrl(parent, -1, style=wx.TE_PROCESS_ENTER) self.slider = wx.Slider(parent, -1) - self.slider.SetMax(param.maximum*1000) + #self.slider.SetMax(param.maximum*1000) + self.slider.SetRange(0, param.maximum*1000) self.setKnob(param.value) - + sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(self.sliderLabel, 0, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, border=2) sizer.Add(self.sliderText, 0, wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, border=2) @@ -82,11 +95,11 @@ def __init__(self, parent, label, param): def sliderHandler(self, evt): value = evt.GetInt() / 1000. self.param.set(value) - + def sliderTextHandler(self, evt): value = float(self.sliderText.GetValue()) self.param.set(value) - + def setKnob(self, value): self.sliderText.SetValue('%g'%value) self.slider.SetValue(value*1000) @@ -109,7 +122,7 @@ def __init__(self, *args, **kwargs): sizer.Add(self.amplitudeSliderGroup.sizer, 0, \ wx.EXPAND | wx.ALIGN_CENTER | wx.ALL, border=5) self.SetSizer(sizer) - + class FourierDemoWindow(wx.Window, Knob): def __init__(self, *args, **kwargs): @@ -125,7 +138,7 @@ def __init__(self, *args, **kwargs): self.f0 = Param(2., minimum=0., maximum=6.) self.A = Param(1., minimum=0.01, maximum=2.) self.draw() - + # Not sure I like having two params attached to the same Knob, # but that is what we have here... it works but feels kludgy - # although maybe it's not too bad since the knob changes both params @@ -133,10 +146,16 @@ def __init__(self, *args, **kwargs): self.f0.attach(self) self.A.attach(self) self.Bind(wx.EVT_SIZE, self.sizeHandler) - + + self.Bind(wx.EVT_PAINT, self.OnPaint) + + def OnPaint(self, event): + self.canvas.draw() + event.Skip() + def sizeHandler(self, *args, **kwargs): self.canvas.SetSize(self.GetSize()) - + def mouseDown(self, evt): if self.lines[0] in self.figure.hitlist(evt): self.state = 'frequency' @@ -159,7 +178,7 @@ def mouseMotion(self, evt): elif self.state == 'time': if (x-x0)/x0 != -1.: self.f0.set(1./(1./f0Init+(1./f0Init*(x-x0)/x0))) - + def mouseUp(self, evt): self.state = '' @@ -209,6 +228,6 @@ def OnInit(self): self.frame1 = FourierDemoFrame(parent=None, title="Fourier Demo", size=(640, 480)) self.frame1.Show() return True - + app = App() app.MainLoop() diff --git a/examples/user_interfaces/wxcursor_demo.py b/examples/user_interfaces/wxcursor_demo.py index 4d610ffc44d8..93be5f001364 100644 --- a/examples/user_interfaces/wxcursor_demo.py +++ b/examples/user_interfaces/wxcursor_demo.py @@ -1,6 +1,12 @@ """ Example to draw a cursor and report the data coords in wx """ +# Used to guarantee to use at least Wx2.8 +import wxversion +wxversion.ensureMinimal('2.8') +#wxversion.select('2.8') +#wxversion.select('2.9.5') # 2.9.x classic +#wxversion.select('2.9.6-msw-phoenix') # 2.9.x phoenix import matplotlib matplotlib.use('WXAgg') @@ -11,14 +17,17 @@ from numpy import arange, sin, pi import wx +print wx.VERSION_STRING class CanvasFrame(wx.Frame): def __init__(self, ): wx.Frame.__init__(self,None,-1, 'CanvasFrame',size=(550,350)) - - self.SetBackgroundColour(wx.NamedColour("WHITE")) + if 'phoenix' in wx.PlatformInfo: + self.SetBackgroundColour(wx.Colour("WHITE")) + else: + self.SetBackgroundColour(wx.NamedColour("WHITE")) self.figure = Figure() self.axes = self.figure.add_subplot(111) @@ -41,14 +50,23 @@ def __init__(self, ): self.statusBar = wx.StatusBar(self, -1) self.statusBar.SetFieldsCount(1) + self.statusBar.SetStatusWidths([-1]) self.SetStatusBar(self.statusBar) self.toolbar = NavigationToolbar2Wx(self.figure_canvas) self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND) self.toolbar.Show() - + self.Bind(wx.EVT_PAINT, self.OnPaint) + + def OnPaint(self, event): + self.figure_canvas.draw() + event.Skip() + def ChangeCursor(self, event): - self.figure_canvas.SetCursor(wx.StockCursor(wx.CURSOR_BULLSEYE)) + if 'phoenix' in wx.PlatformInfo: + self.figure_canvas.SetCursor(wx.Cursor(wx.CURSOR_BULLSEYE)) + else: + self.figure_canvas.SetCursor(wx.StockCursor(wx.CURSOR_BULLSEYE)) def UpdateStatusBar(self, event): if event.inaxes: diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 25d7e04f3103..7d31f01f05f9 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -106,7 +106,7 @@ import sys import distutils.version -__version__ = '1.4.x' +__version__ = '1.5.x' __version__numpy__ = '1.6' # minimum required numpy version try: diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 80ceed5de7e3..6f2b24c1793f 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -1010,20 +1010,31 @@ def _update_ticks(self, renderer): # the idea that one would rather potentially lose a tick # from one side of the axis or another, rather than see a # stack trace. - try: - ds1 = self._get_pixel_distance_along_axis(interval_expanded[0], -0.5) - except: - warnings.warn("Unable to find pixel distance along axis for interval padding; assuming no interval padding needed.") - ds1 = 0.0 - if np.isnan(ds1): - ds1 = 0.0 - try: - ds2 = self._get_pixel_distance_along_axis(interval_expanded[1], +0.5) - except: - warnings.warn("Unable to find pixel distance along axis for interval padding; assuming no interval padding needed.") - ds2 = 0.0 - if np.isnan(ds2): - ds2 = 0.0 + # We also catch users warnings here. These are the result of + # invalid numpy calculations that may be the result of out of + # bounds on axis with finite allowed intervals such as geo + # projections i.e. Mollweide. + with np.errstate(invalid='ignore'): + try: + ds1 = self._get_pixel_distance_along_axis( + interval_expanded[0], -0.5) + except: + warnings.warn("Unable to find pixel distance along axis for\ + interval padding of ticks; assuming no interval padding\ + needed.") + ds1 = 0.0 + if np.isnan(ds1): + ds1 = 0.0 + try: + ds2 = self._get_pixel_distance_along_axis( + interval_expanded[1], +0.5) + except: + warnings.warn("Unable to find pixel distance along axis for\ + interval padding of ticks; assuming no interval padding\ + needed.") + ds2 = 0.0 + if np.isnan(ds2): + ds2 = 0.0 interval_expanded = (interval_expanded[0] - ds1, interval_expanded[1] + ds2) diff --git a/lib/matplotlib/backends/backend_qt5.py b/lib/matplotlib/backends/backend_qt5.py index 03f5aa821f91..b1bc794eb486 100644 --- a/lib/matplotlib/backends/backend_qt5.py +++ b/lib/matplotlib/backends/backend_qt5.py @@ -610,8 +610,8 @@ def _init_toolbar(self): self.locLabel.setAlignment( QtCore.Qt.AlignRight | QtCore.Qt.AlignTop) self.locLabel.setSizePolicy( - QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Ignored)) + QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, + QtWidgets.QSizePolicy.Ignored)) labelAction = self.addWidget(self.locLabel) labelAction.setVisible(True) diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py index d99f04f07ea9..69f2b2803237 100644 --- a/lib/matplotlib/backends/backend_wx.py +++ b/lib/matplotlib/backends/backend_wx.py @@ -40,38 +40,36 @@ import traceback, pdb _DEBUG_lvls = {1 : 'Low ', 2 : 'Med ', 3 : 'High', 4 : 'Error' } -if six.PY3: - warnings.warn( - "The wx and wxagg backends have not been tested with Python 3.x", - ImportWarning) - -missingwx = "Matplotlib backend_wx and backend_wxagg require wxPython >=2.8" -missingwxversion = ("Matplotlib backend_wx and backend_wxagg " +if sys.version_info.major < 3: + # wxPython-Phoenix, does currently not support wxversion + missingwx = "Matplotlib backend_wx and backend_wxagg require wxPython >=2.8" + missingwxversion = ("Matplotlib backend_wx and backend_wxagg " "require wxversion, which was not found.") -if not hasattr(sys, 'frozen'): # i.e., not py2exe - try: - import wxversion - except ImportError: - raise ImportError(missingwxversion) - - # Some early versions of wxversion lack AlreadyImportedError. - # It was added around 2.8.4? - try: - _wx_ensure_failed = wxversion.AlreadyImportedError - except AttributeError: - _wx_ensure_failed = wxversion.VersionError - - try: - wxversion.ensureMinimal(str('2.8')) - except _wx_ensure_failed: - pass - # We don't really want to pass in case of VersionError, but when - # AlreadyImportedError is not available, we have to. + if not hasattr(sys, 'frozen'): # i.e., not py2exe + try: + import wxversion + except ImportError: + raise ImportError(missingwxversion) + + # Some early versions of wxversion lack AlreadyImportedError. + # It was added around 2.8.4? + try: + _wx_ensure_failed = wxversion.AlreadyImportedError + except AttributeError: + _wx_ensure_failed = wxversion.VersionError + + try: + wxversion.ensureMinimal(str('2.8')) + except _wx_ensure_failed: + pass + # We don't really want to pass in case of VersionError, but when + # AlreadyImportedError is not available, we have to. try: import wx backend_version = wx.VERSION_STRING + is_phoenix = 'phoenix' in wx.PlatformInfo except ImportError: raise ImportError(missingwx) @@ -667,8 +665,6 @@ class FigureCanvasWx(FigureCanvasBase, wx.Panel): wx.WXK_DELETE : 'delete', wx.WXK_HOME : 'home', wx.WXK_END : 'end', - wx.WXK_PRIOR : 'pageup', - wx.WXK_NEXT : 'pagedown', wx.WXK_PAGEUP : 'pageup', wx.WXK_PAGEDOWN : 'pagedown', wx.WXK_NUMPAD0 : '0', @@ -691,8 +687,6 @@ class FigureCanvasWx(FigureCanvasBase, wx.Panel): wx.WXK_NUMPAD_RIGHT : 'right', wx.WXK_NUMPAD_DOWN : 'down', wx.WXK_NUMPAD_LEFT : 'left', - wx.WXK_NUMPAD_PRIOR : 'pageup', - wx.WXK_NUMPAD_NEXT : 'pagedown', wx.WXK_NUMPAD_PAGEUP : 'pageup', wx.WXK_NUMPAD_PAGEDOWN : 'pagedown', wx.WXK_NUMPAD_HOME : 'home', @@ -736,7 +730,10 @@ def do_nothing(*args, **kwargs): # Create the drawing bitmap - self.bitmap =wx.EmptyBitmap(w, h) + if is_phoenix: + self.bitmap =wx.Bitmap(w, h) + else: + self.bitmap =wx.EmptyBitmap(w, h) DEBUG_MSG("__init__() - bitmap w:%d h:%d" % (w,h), 2, self) # TODO: Add support for 'point' inspection and plot navigation. self._isDrawn = False @@ -873,7 +870,10 @@ def start_event_loop(self, timeout=0): bind(self, wx.EVT_TIMER, self.stop_event_loop, id=id) # Event loop handler for start/stop event loop - self._event_loop = wx.EventLoop() + if is_phoenix: + self._event_loop = wx.GUIEventLoop() + else: + self._event_loop = wx.EventLoop() self._event_loop.Run() timer.Stop() @@ -897,7 +897,7 @@ def _get_imagesave_wildcards(self): 'return the wildcard string for the filesave dialog' default_filetype = self.get_default_filetype() filetypes = self.get_supported_filetypes_grouped() - sorted_filetypes = list(six.iteritems(filetypes)) + sorted_filetypes = filetypes.items() sorted_filetypes.sort() wildcards = [] extensions = [] @@ -923,10 +923,7 @@ def gui_repaint(self, drawDC=None): if drawDC is None: drawDC=wx.ClientDC(self) - drawDC.BeginDrawing() drawDC.DrawBitmap(self.bitmap, 0, 0) - drawDC.EndDrawing() - #wx.GetApp().Yield() else: pass @@ -979,7 +976,11 @@ def _print_image(self, filename, filetype, *args, **kwargs): width = int(math.ceil(width)) height = int(math.ceil(height)) - self.bitmap = wx.EmptyBitmap(width, height) + if is_phoenix: + self.bitmap =wx.Bitmap(width, height) + else: + self.bitmap =wx.EmptyBitmap(width, height) + renderer = RendererWx(self.bitmap, self.figure.dpi) gc = renderer.new_gc() @@ -1052,7 +1053,11 @@ def _onSize(self, evt): DEBUG_MSG("_onSize()", 2, self) # Create a new, correctly sized bitmap self._width, self._height = self.GetClientSize() - self.bitmap =wx.EmptyBitmap(self._width, self._height) + if is_phoenix: + self.bitmap =wx.Bitmap(self._width, self._height) + else: + self.bitmap =wx.EmptyBitmap(self._width, self._height) + self._isDrawn = False if self._width <= 1 or self._height <= 1: return # Empty figure @@ -1636,12 +1641,25 @@ def _init_toolbar(self): self.AddSeparator() continue self.wx_ids[text] = wx.NewId() - if text in ['Pan', 'Zoom']: - self.AddCheckTool(self.wx_ids[text], _load_bitmap(image_file + '.png'), - shortHelp=text, longHelp=tooltip_text) + if is_phoenix: + if text in ['Pan', 'Zoom']: + kind = wx.ITEM_CHECK + else: + kind = wx.ITEM_NORMAL + self.AddTool(self.wx_ids[text], label=text, + bitmap=_load_bitmap(image_file + '.png'), + bmpDisabled=wx.NullBitmap, + shortHelpString=text, + longHelpString=tooltip_text, + kind=kind) else: - self.AddSimpleTool(self.wx_ids[text], _load_bitmap(image_file + '.png'), - text, tooltip_text) + if text in ['Pan', 'Zoom']: + self.AddCheckTool(self.wx_ids[text], _load_bitmap(image_file + '.png'), + shortHelp=text, longHelp=tooltip_text) + else: + self.AddSimpleTool(self.wx_ids[text], _load_bitmap(image_file + '.png'), + text, tooltip_text) + bind(self, wx.EVT_TOOL, getattr(self, callback), id=self.wx_ids[text]) self.Realize() @@ -1700,7 +1718,10 @@ def save_figure(self, *args): error_msg_wx(str(e)) def set_cursor(self, cursor): - cursor =wx.StockCursor(cursord[cursor]) + if is_phoenix: + cursor = wx.Cursor(cursord[cursor]) + else: + cursor = wx.StockCursor(cursord[cursor]) self.canvas.SetCursor( cursor ) def release(self, event): @@ -1737,7 +1758,6 @@ def draw_rubberband(self, event, x0, y0, x1, y1): dc.ResetBoundingBox() - dc.BeginDrawing() height = self.canvas.figure.bbox.height y1 = height - y1 y0 = height - y0 @@ -1754,7 +1774,6 @@ def draw_rubberband(self, event, x0, y0, x1, y1): else: dc.DrawRectangle(*lastrect) #erase last self.lastrect = rect dc.DrawRectangle(*rect) - dc.EndDrawing() def set_status_bar(self, statbar): self.statbar = statbar diff --git a/lib/matplotlib/backends/backend_wxagg.py b/lib/matplotlib/backends/backend_wxagg.py index 5dd01030560b..6e9fe58093cb 100644 --- a/lib/matplotlib/backends/backend_wxagg.py +++ b/lib/matplotlib/backends/backend_wxagg.py @@ -12,6 +12,7 @@ FigureFrameWx, DEBUG_MSG, NavigationToolbar2Wx, error_msg_wx, \ draw_if_interactive, show, Toolbar, backend_version import wx +is_phoenix = 'phoenix' in wx.PlatformInfo class FigureFrameWxAgg(FigureFrameWx): @@ -136,7 +137,10 @@ def _convert_agg_to_wx_image(agg, bbox): """ if bbox is None: # agg => rgb -> image - image = wx.EmptyImage(int(agg.width), int(agg.height)) + if is_phoenix: + image = wx.Image(int(agg.width), int(agg.height)) + else: + image = wx.EmptyImage(int(agg.width), int(agg.height)) image.SetData(agg.tostring_rgb()) return image else: @@ -153,8 +157,12 @@ def _convert_agg_to_wx_bitmap(agg, bbox): """ if bbox is None: # agg => rgba buffer -> bitmap - return wx.BitmapFromBufferRGBA(int(agg.width), int(agg.height), - agg.buffer_rgba()) + if is_phoenix: + return wx.Bitmap.FromBufferRGBA(int(agg.width), int(agg.height), + agg.buffer_rgba()) + else: + return wx.BitmapFromBufferRGBA(int(agg.width), int(agg.height), + agg.buffer_rgba()) else: # agg => rgba buffer -> bitmap => clipped bitmap return _WX28_clipped_agg_as_bitmap(agg, bbox) @@ -170,12 +178,19 @@ def _WX28_clipped_agg_as_bitmap(agg, bbox): r = l + width t = b + height - srcBmp = wx.BitmapFromBufferRGBA(int(agg.width), int(agg.height), - agg.buffer_rgba()) + if is_phoenix: + srcBmp = wx.Bitmap.FromBufferRGBA(int(agg.width), int(agg.height), + agg.buffer_rgba()) + else: + srcBmp = wx.BitmapFromBufferRGBA(int(agg.width), int(agg.height), + agg.buffer_rgba()) srcDC = wx.MemoryDC() srcDC.SelectObject(srcBmp) - destBmp = wx.EmptyBitmap(int(width), int(height)) + if is_phoenix: + destBmp = wx.Bitmap(int(width), int(height)) + else: + destBmp = wx.EmptyBitmap(int(width), int(height)) destDC = wx.MemoryDC() destDC.SelectObject(destBmp) diff --git a/lib/matplotlib/bezier.py b/lib/matplotlib/bezier.py index 034aa1d45cd1..ce2c9d5052a1 100644 --- a/lib/matplotlib/bezier.py +++ b/lib/matplotlib/bezier.py @@ -256,7 +256,7 @@ def split_path_inout(path, inside, tolerence=0.01, reorder_inout=False): for ctl_points, command in path_iter: iold = i - i += len(ctl_points) / 2 + i += len(ctl_points) // 2 if inside(ctl_points[-2:]) != begin_inside: bezier_path = concat([ctl_points_old[-2:], ctl_points]) break diff --git a/lib/matplotlib/cbook.py b/lib/matplotlib/cbook.py index 192f1d3037d1..4cd1fcca9afe 100644 --- a/lib/matplotlib/cbook.py +++ b/lib/matplotlib/cbook.py @@ -1737,7 +1737,7 @@ def simple_linear_interpolation(a, steps): if steps == 1: return a - steps = np.floor(steps) + steps = int(np.floor(steps)) new_length = ((len(a) - 1) * steps) + 1 new_shape = list(a.shape) new_shape[0] = new_length @@ -1747,7 +1747,6 @@ def simple_linear_interpolation(a, steps): a0 = a[0:-1] a1 = a[1:] delta = ((a1 - a0) / steps) - steps = int(steps) for i in range(1, steps): result[i::steps] = delta * i + a0 result[steps::steps] = a1 diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index dbc96197c134..5d165b8f69a0 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -222,7 +222,8 @@ def is_color_like(c): def rgb2hex(rgb): 'Given an rgb or rgba sequence of 0-1 floats, return the hex string' - return '#%02x%02x%02x' % tuple([np.round(val * 255) for val in rgb[:3]]) + a = '#%02x%02x%02x' % tuple([int(np.round(val * 255)) for val in rgb[:3]]) + return a hexColorPattern = re.compile("\A#[a-fA-F0-9]{6}\Z") diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py index 383978cbc44d..0d74a3a8461d 100644 --- a/lib/matplotlib/contour.py +++ b/lib/matplotlib/contour.py @@ -474,20 +474,21 @@ def calc_label_rot_and_inline(self, slc, ind, lw, lc=None, spacing=5): xy2 = mlab.less_simple_linear_interpolation( pl, lc, [xi[1]]) - # Make integer + # Round to integer values but keep as float + # To allow check against nan below I = [np.floor(I[0]), np.ceil(I[1])] # Actually break contours if closed: # This will remove contour if shorter than label if np.all(~np.isnan(I)): - nlc.append(np.r_[xy2, lc[I[1]:I[0] + 1], xy1]) + nlc.append(np.r_[xy2, lc[int(I[1]):int(I[0]) + 1], xy1]) else: # These will remove pieces of contour if they have length zero if not np.isnan(I[0]): - nlc.append(np.r_[lc[:I[0] + 1], xy1]) + nlc.append(np.r_[lc[:int(I[0]) + 1], xy1]) if not np.isnan(I[1]): - nlc.append(np.r_[xy2, lc[I[1]:]]) + nlc.append(np.r_[xy2, lc[int(I[1]):]]) # The current implementation removes contours completely # covered by labels. Uncomment line below to keep diff --git a/lib/matplotlib/hatch.py b/lib/matplotlib/hatch.py index e6df8bcfce6d..6729b610997c 100644 --- a/lib/matplotlib/hatch.py +++ b/lib/matplotlib/hatch.py @@ -21,7 +21,7 @@ class HatchPatternBase: class HorizontalHatch(HatchPatternBase): def __init__(self, hatch, density): - self.num_lines = (hatch.count('-') + hatch.count('+')) * density + self.num_lines = int((hatch.count('-') + hatch.count('+')) * density) self.num_vertices = self.num_lines * 2 def set_vertices_and_codes(self, vertices, codes): @@ -38,7 +38,7 @@ def set_vertices_and_codes(self, vertices, codes): class VerticalHatch(HatchPatternBase): def __init__(self, hatch, density): - self.num_lines = (hatch.count('|') + hatch.count('+')) * density + self.num_lines = int((hatch.count('|') + hatch.count('+')) * density) self.num_vertices = self.num_lines * 2 def set_vertices_and_codes(self, vertices, codes): @@ -55,8 +55,8 @@ def set_vertices_and_codes(self, vertices, codes): class NorthEastHatch(HatchPatternBase): def __init__(self, hatch, density): - self.num_lines = (hatch.count('/') + hatch.count('x') + - hatch.count('X')) * density + self.num_lines = int((hatch.count('/') + hatch.count('x') + + hatch.count('X')) * density) if self.num_lines: self.num_vertices = (self.num_lines + 1) * 2 else: @@ -74,8 +74,8 @@ def set_vertices_and_codes(self, vertices, codes): class SouthEastHatch(HatchPatternBase): def __init__(self, hatch, density): - self.num_lines = (hatch.count('\\') + hatch.count('x') + - hatch.count('X')) * density + self.num_lines = int((hatch.count('\\') + hatch.count('x') + + hatch.count('X')) * density) self.num_vertices = (self.num_lines + 1) * 2 if self.num_lines: self.num_vertices = (self.num_lines + 1) * 2 @@ -100,8 +100,8 @@ def __init__(self, hatch, density): self.num_shapes = 0 self.num_vertices = 0 else: - self.num_shapes = ((self.num_rows / 2 + 1) * (self.num_rows + 1) + - (self.num_rows / 2) * (self.num_rows)) + self.num_shapes = ((self.num_rows // 2 + 1) * (self.num_rows + 1) + + (self.num_rows // 2) * (self.num_rows)) self.num_vertices = (self.num_shapes * len(self.shape_vertices) * (self.filled and 1 or 2)) diff --git a/lib/matplotlib/markers.py b/lib/matplotlib/markers.py index a039f2246ee6..b038d7ae8f53 100644 --- a/lib/matplotlib/markers.py +++ b/lib/matplotlib/markers.py @@ -45,6 +45,8 @@ "" nothing ``'$...$'`` render the string using mathtext. `verts` a list of (x, y) pairs used for Path vertices. + The center of the marker is located at (0,0) and + the size is normalized. path a `~matplotlib.path.Path` instance. (`numsides`, `style`, `angle`) see below ============================== =============================================== @@ -269,7 +271,7 @@ def _set_custom_marker(self, path): verts = path.vertices rescale = max(np.max(np.abs(verts[:, 0])), np.max(np.abs(verts[:, 1]))) - self._transform = Affine2D().scale(1.0 / rescale) + self._transform = Affine2D().scale(0.5 / rescale) self._path = path def _set_path_marker(self): diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index aea11327dfdb..339f111c2a2f 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -2003,6 +2003,57 @@ def transmute(self, x0, y0, width, height, mutation_size): _style_list["rarrow"] = RArrow + class DArrow(_Base): + """ + (Double) Arrow Box + """ + # This source is copied from LArrow, + # modified to add a right arrow to the bbox. + + def __init__(self, pad=0.3): + self.pad = pad + super(BoxStyle.DArrow, self).__init__() + + def transmute(self, x0, y0, width, height, mutation_size): + + # padding + pad = mutation_size * self.pad + + # width and height with padding added. + # The width is padded by the arrows, so we don't need to pad it. + height = height + 2. * pad + + # boundary of the padded box + x0, y0 = x0 - pad, y0 - pad + x1, y1 = x0 + width, y0 + height + + dx = (y1 - y0)/2. + dxx = dx * .5 + # adjust x0. 1.4 <- sqrt(2) + x0 = x0 + pad / 1.4 + + cp = [(x0 + dxx, y0), (x1, y0), # bot-segment + (x1, y0 - dxx), (x1 + dx + dxx, y0 + dx), + (x1, y1 + dxx), # right-arrow + (x1, y1), (x0 + dxx, y1), # top-segment + (x0 + dxx, y1 + dxx), (x0 - dx, y0 + dx), + (x0 + dxx, y0 - dxx), # left-arrow + (x0 + dxx, y0), (x0 + dxx, y0)] # close-poly + + com = [Path.MOVETO, Path.LINETO, + Path.LINETO, Path.LINETO, + Path.LINETO, + Path.LINETO, Path.LINETO, + Path.LINETO, Path.LINETO, + Path.LINETO, + Path.LINETO, Path.CLOSEPOLY] + + path = Path(cp, com) + + return path + + _style_list['darrow'] = DArrow + class Round(_Base): """ A box with round corners. diff --git a/lib/matplotlib/tests/baseline_images/test_arrow_patches/boxarrow_test_image.png b/lib/matplotlib/tests/baseline_images/test_arrow_patches/boxarrow_test_image.png new file mode 100644 index 000000000000..3ddad736d44a Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_arrow_patches/boxarrow_test_image.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_axes/vertex_markers.png b/lib/matplotlib/tests/baseline_images/test_axes/vertex_markers.png index 538c07ec5aec..49348ebe6ef6 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/vertex_markers.png and b/lib/matplotlib/tests/baseline_images/test_axes/vertex_markers.png differ diff --git a/lib/matplotlib/tests/test_arrow_patches.py b/lib/matplotlib/tests/test_arrow_patches.py index 4a6c4a94e0dd..a81a6dd41502 100644 --- a/lib/matplotlib/tests/test_arrow_patches.py +++ b/lib/matplotlib/tests/test_arrow_patches.py @@ -30,6 +30,27 @@ def test_fancyarrow(): ax.tick_params(labelleft=False, labelbottom=False) +@image_comparison(baseline_images=['boxarrow_test_image'], extensions=['png']) +def test_boxarrow(): + + styles = matplotlib.patches.BoxStyle.get_styles() + + n = len(styles) + spacing = 1.2 + + figheight = (n * spacing + .5) + fig1 = plt.figure(1, figsize=(4 / 1.5, figheight / 1.5)) + + fontsize = 0.3 * 72 + + for i, stylename in enumerate(sorted(styles.keys())): + fig1.text(0.5, ((n - i) * spacing - 0.5)/figheight, stylename, + ha="center", + size=fontsize, + transform=fig1.transFigure, + bbox=dict(boxstyle=stylename, fc="w", ec="k")) + + if __name__ == '__main__': import nose nose.runmodule(argv=['-s', '--with-doctest'], exit=False) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 846cef470dad..f0017464dc92 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -523,7 +523,7 @@ def test_nonfinite_limits(): y = np.log(x) finally: np.seterr(**olderr) - x[len(x)/2] = np.nan + x[len(x)//2] = np.nan fig = plt.figure() ax = fig.add_subplot(111) ax.plot(x, y) diff --git a/lib/matplotlib/tests/test_delaunay.py b/lib/matplotlib/tests/test_delaunay.py index 49f10f811c93..373f77404fe0 100644 --- a/lib/matplotlib/tests/test_delaunay.py +++ b/lib/matplotlib/tests/test_delaunay.py @@ -3,10 +3,16 @@ import six from six.moves import xrange +import warnings import numpy as np from matplotlib.testing.decorators import image_comparison, knownfailureif -from matplotlib.delaunay.triangulate import Triangulation +from matplotlib.cbook import MatplotlibDeprecationWarning + +with warnings.catch_warnings(): + # the module is deprecated. The tests should be removed when the module is. + warnings.simplefilter('ignore', MatplotlibDeprecationWarning) + from matplotlib.delaunay.triangulate import Triangulation from matplotlib import pyplot as plt import matplotlib as mpl diff --git a/lib/matplotlib/tests/test_mlab.py b/lib/matplotlib/tests/test_mlab.py index 0cc991f05ebf..e35661d56622 100644 --- a/lib/matplotlib/tests/test_mlab.py +++ b/lib/matplotlib/tests/test_mlab.py @@ -6,6 +6,7 @@ import tempfile from numpy.testing import assert_allclose, assert_array_equal +import numpy.ma.testutils as matest import numpy as np from nose.tools import (assert_equal, assert_almost_equal, assert_not_equal, assert_true, assert_raises) @@ -1325,8 +1326,8 @@ def createStim(self, fstims, iscomplex, sides, nsides, len_x=None, freqs_specgram = freqs_density # time points for specgram - t_start = NFFT_specgram_real/2 - t_stop = len(x) - NFFT_specgram_real/2+1 + t_start = NFFT_specgram_real//2 + t_stop = len(x) - NFFT_specgram_real//2+1 t_step = NFFT_specgram_real - nover_specgram_real t_specgram = x[t_start:t_stop:t_step] if NFFT_specgram_real % 2: @@ -2714,7 +2715,7 @@ def get_z(x, y): z_masked = np.ma.array(z, mask=[False, False, False, True, False]) correct_zi_masked = np.ma.masked_where(xi + yi > 1.0, get_z(xi, yi)) zi = mlab.griddata(x, y, z_masked, xi, yi, interp='linear') - np.testing.assert_array_almost_equal(zi, correct_zi_masked) + matest.assert_array_almost_equal(zi, correct_zi_masked) np.testing.assert_array_equal(np.ma.getmask(zi), np.ma.getmask(correct_zi_masked)) diff --git a/lib/matplotlib/tests/test_rcparams.py b/lib/matplotlib/tests/test_rcparams.py index 9d6d0613db76..928393ecd5c7 100644 --- a/lib/matplotlib/tests/test_rcparams.py +++ b/lib/matplotlib/tests/test_rcparams.py @@ -5,6 +5,7 @@ import os import sys +import warnings import matplotlib as mpl from matplotlib.tests import assert_str_equal @@ -97,29 +98,36 @@ def test_RcParams_class(): def test_Bug_2543(): # Test that it possible to add all values to itself / deepcopy - # This was not possible because validate_bool_maybe_none did not + # This was not possible because validate_bool_maybe_none did not # accept None as an argument. # https://github.com/matplotlib/matplotlib/issues/2543 - with mpl.rc_context(): - _copy = mpl.rcParams.copy() - for key in six.iterkeys(_copy): - mpl.rcParams[key] = _copy[key] - mpl.rcParams['text.dvipnghack'] = None - with mpl.rc_context(): - from copy import deepcopy - _deep_copy = deepcopy(mpl.rcParams) - from matplotlib.rcsetup import validate_bool_maybe_none, validate_bool - # real test is that this does not raise - assert_true(validate_bool_maybe_none(None) is None) - assert_true(validate_bool_maybe_none("none") is None) - _fonttype = mpl.rcParams['svg.fonttype'] - assert_true(_fonttype == mpl.rcParams['svg.embed_char_paths']) - with mpl.rc_context(): - mpl.rcParams['svg.embed_char_paths'] = False - assert_true(mpl.rcParams['svg.fonttype'] == "none") + # We filter warnings at this stage since a number of them are raised + # for deprecated rcparams as they should. We dont want these in the + # printed in the test suite. + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', + message='.*(deprecated|obsolete)', + category=UserWarning) + with mpl.rc_context(): + _copy = mpl.rcParams.copy() + for key in six.iterkeys(_copy): + mpl.rcParams[key] = _copy[key] + mpl.rcParams['text.dvipnghack'] = None + with mpl.rc_context(): + from copy import deepcopy + _deep_copy = deepcopy(mpl.rcParams) + from matplotlib.rcsetup import validate_bool_maybe_none, validate_bool + # real test is that this does not raise + assert_true(validate_bool_maybe_none(None) is None) + assert_true(validate_bool_maybe_none("none") is None) + _fonttype = mpl.rcParams['svg.fonttype'] + assert_true(_fonttype == mpl.rcParams['svg.embed_char_paths']) + with mpl.rc_context(): + mpl.rcParams['svg.embed_char_paths'] = False + assert_true(mpl.rcParams['svg.fonttype'] == "none") def test_Bug_2543_newer_python(): - # only split from above because of the usage of assert_raises + # only split from above because of the usage of assert_raises # as a context manager, which only works in 2.7 and above if sys.version_info[:2] < (2, 7): raise nose.SkipTest("assert_raises as context manager not supported with Python < 2.7") @@ -130,8 +138,8 @@ def test_Bug_2543_newer_python(): validate_bool(None) with assert_raises(ValueError): with mpl.rc_context(): - mpl.rcParams['svg.fonttype'] = True - + mpl.rcParams['svg.fonttype'] = True + if __name__ == '__main__': import nose nose.runmodule(argv=['-s', '--with-doctest'], exit=False) diff --git a/lib/matplotlib/tests/test_simplification.py b/lib/matplotlib/tests/test_simplification.py index a1bc217bf6fd..e99ac097a989 100644 --- a/lib/matplotlib/tests/test_simplification.py +++ b/lib/matplotlib/tests/test_simplification.py @@ -153,7 +153,7 @@ def test_start_with_moveto(): decodebytes = base64.decodestring verts = np.fromstring(decodebytes(data), dtype='= 1) * (xs <= 2) * (ys >= 1) * (ys <= 2) assert_array_equal(zs.mask, mask) @@ -697,7 +698,8 @@ def z(x, y): interp_z0[interp_key] = interp(xs0, ys0) # storage else: interpz = interp(xs, ys) - assert_array_almost_equal(interpz, interp_z0[interp_key]) + matest.assert_array_almost_equal(interpz, + interp_z0[interp_key]) scale_factor = 987654.3210 for scaled_axis in ('x', 'y'): @@ -723,7 +725,7 @@ def z(x, y): # 1 axis... for interp_key in ['lin', 'min_E', 'geom']: interpz = dic_interp[interp_key](xs, ys) - assert_array_almost_equal(interpz, interp_z0[interp_key]) + matest.assert_array_almost_equal(interpz, interp_z0[interp_key]) @image_comparison(baseline_images=['tri_smooth_contouring'], diff --git a/lib/matplotlib/tri/trirefine.py b/lib/matplotlib/tri/trirefine.py index ae2f257a1f5e..11e3fff3e468 100644 --- a/lib/matplotlib/tri/trirefine.py +++ b/lib/matplotlib/tri/trirefine.py @@ -231,7 +231,7 @@ def _refine_triangulation_once(triangulation, ancestors=None): # points # hint: each apex is shared by 2 masked_triangles except the borders. borders = np.sum(neighbors == -1) - added_pts = (3*ntri + borders) / 2 + added_pts = (3*ntri + borders) // 2 refi_npts = npts + added_pts refi_x = np.zeros(refi_npts) refi_y = np.zeros(refi_npts) diff --git a/setupext.py b/setupext.py index 0ae553ade51c..210329d58ac3 100755 --- a/setupext.py +++ b/setupext.py @@ -942,7 +942,7 @@ def check(self): return self._check_for_pkg_config( 'freetype2', 'ft2build.h', - min_version='2.4', version=version) + min_version='2.3', version=version) def version_from_header(self): version = 'Failed to identify version.' diff --git a/src/ft2font.cpp b/src/ft2font.cpp index 58d8be8b7564..7f33d6798f26 100644 --- a/src/ft2font.cpp +++ b/src/ft2font.cpp @@ -850,6 +850,7 @@ PYCXX_NOARGS_METHOD_DECL(FT2Font, get_path) FT2Font::FT2Font(Py::PythonClassInstance *self, Py::Tuple &args, Py::Dict &kwds) : Py::PythonClass(self, args, kwds), + face(NULL), image() { FT_Open_Args open_args; @@ -979,11 +980,13 @@ FT2Font::~FT2Font() { _VERBOSE("FT2Font::~FT2Font"); - FT_Done_Face(face); + if (face) { + FT_Done_Face(face); - for (size_t i = 0; i < glyphs.size(); i++) - { - FT_Done_Glyph(glyphs[i]); + for (size_t i = 0; i < glyphs.size(); i++) + { + FT_Done_Glyph(glyphs[i]); + } } if (stream.descriptor.pointer != NULL) {