Merge branch 'dougthor42-refactor-lib.plot-part3'

This commit is contained in:
Robin Dunn
2017-09-08 19:29:34 -07:00
6 changed files with 286 additions and 266 deletions

View File

@@ -2,10 +2,7 @@
# pylint: disable=C0413
# C0413: Import should be placed at the top of the module
"""
wx.lib.plot
===========
This is a simple plotting library for the wxPython Phoenix project.
A simple plotting library for the wxPython Phoenix project.
"""
__version__ = "0.0.1"
@@ -42,7 +39,7 @@ from .polyobjects import PlotGraphics
from .polyobjects import PlotPrintout
from .utils import TempStyle
from .utils import PendingDeprecation
from .utils import pendingDeprecation
# For backwards compat.
BoxPlot = PolyBoxPlot

View File

@@ -28,7 +28,8 @@ except ImportError:
imported. It probably is not installed (it's not part of the
standard Python distribution). See the Numeric Python site
(http://numpy.scipy.org) for information on downloading source or
binaries."""
binaries, or just try `pip install numpy` and it will probably
work."""
raise ImportError("NumPy not found.\n" + msg)
@@ -509,7 +510,8 @@ class PlotDemoMainFrame(wx.Frame):
'Enables the display of the axes values')
submenu = wx.Menu()
submenu_items = ("Bottom", "Left", "Top", "Right")
submenu_items = ("Bottom", "Left", "Top", "Right",
"Bottom+Left", "All")
help_txt = "Enables {} ticks"
self.ticksSubMenu = submenu
for _i, item in enumerate(submenu_items, 2501):
@@ -524,6 +526,8 @@ class PlotDemoMainFrame(wx.Frame):
self.Bind(wx.EVT_MENU, self.OnEnableTicksLeft, id=2502)
self.Bind(wx.EVT_MENU, self.OnEnableTicksTop, id=2503)
self.Bind(wx.EVT_MENU, self.OnEnableTicksRight, id=2504)
self.Bind(wx.EVT_MENU, self.OnEnableTicksBottomLeft, id=2505)
self.Bind(wx.EVT_MENU, self.OnEnableTicksAll, id=2506)
menu.Append(250, 'Enable Ticks', submenu,
'Enables the display of the ticks')
@@ -829,8 +833,8 @@ class PlotDemoMainFrame(wx.Frame):
self.ticksSubMenu.Check(2502, self.client.enableTicks[1])
self.ticksSubMenu.Check(2503, self.client.enableTicks[2])
self.ticksSubMenu.Check(2504, self.client.enableTicks[3])
# self.ticksSubMenu.Check(2505, all(self.client.enableTicks[:2]))
# self.axesSubMenu.Check(2506, all(self.client.enableTicks))
self.ticksSubMenu.Check(2505, all(self.client.enableTicks[:2]))
self.ticksSubMenu.Check(2506, all(self.client.enableTicks))
def OnEnableTicksBottom(self, event):
old = self.client.enableTicks
@@ -856,6 +860,17 @@ class PlotDemoMainFrame(wx.Frame):
old[2], event.IsChecked())
self._checkOtherTicksMenuItems()
def OnEnableTicksBottomLeft(self, event):
checked = event.IsChecked()
old = self.client.enableTicks
self.client.enableTicks = (checked, checked, old[2], old[3])
self._checkOtherTicksMenuItems()
def OnEnableTicksAll(self, event):
checked = event.IsChecked()
self.client.enableTicks = tuple([checked] * 4)
self._checkOtherTicksMenuItems()
# -----------------------------------------------------------------------
### Enable AxesValues Events
# -----------------------------------------------------------------------

View File

@@ -15,7 +15,7 @@ from wx.lib import plot as wxplot
class PlotExample(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Example of wx.lib.plot")
wx.Frame.__init__(self, None, title="Example of wx.lib.plot", size=(640,480))
# Generate some Data
x_data = [1, 2, 3, 4, 5, 6, 7, 8, 9]

File diff suppressed because it is too large Load Diff

View File

@@ -13,9 +13,7 @@ This contains all of the PolyXXX objects used by :mod:`wx.lib.plot`.
__docformat__ = "restructuredtext en"
# Standard Library
import string as _string
import time as _time
import sys
import wx
import warnings
from collections import namedtuple
@@ -33,8 +31,9 @@ except:
raise ImportError("NumPy not found.\n" + msg)
# Package
from .utils import PendingDeprecation
from .utils import pendingDeprecation
from .utils import TempStyle
from .utils import pairwise
# XXX: Comment out this line to disable deprecation warnings
@@ -90,13 +89,18 @@ class PolyPoints(object):
raise ValueError("`logscale` must be a 2-tuple of bools")
self._logscale = logscale
@PendingDeprecation("self.logScale property")
def setLogScale(self, logscale):
"""
Set to change the axes to plot Log10(values)
Value must be a tuple of booleans (x_axis_bool, y_axis_bool)
.. deprecated:: Feb 27, 2016
Use the :attr:`~wx.lib.plot.polyobjects.PolyPoints.logScale`
property instead.
"""
pendingDeprecation("self.logScale property")
self._logscale = logscale
@property
@@ -574,8 +578,6 @@ class PolyMarker(PolyPoints):
'legend': ''}
def __init__(self, points, **attr):
PolyPoints.__init__(self, points, attr)
def draw(self, dc, printerScale, coord=None):
@@ -840,14 +842,6 @@ class PolyHistogram(PolyBarsBase):
self.hist = hist
self.binspec = binspec
# need to create a series of points to be used by PolyPoints
import itertools
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return zip(a, b)
# define the bins and center x locations
self.bins = list(pairwise(self.binspec))
bar_center_x = (pair[0] + (pair[1] - pair[0])/2 for pair in self.bins)
@@ -1013,13 +1007,13 @@ class PolyBoxPlot(PolyPoints):
outliers are outside of 1.5 * IQR
Parameters:
-----------
Parameters
----------
data : array-like
The data to plot
Returns:
--------
Returns
-------
bpdata : collections.namedtuple
Descriptive statistics for data:
(min_data, low_whisker, q25, median, q75, high_whisker, max_data)
@@ -1069,8 +1063,8 @@ class PolyBoxPlot(PolyPoints):
"""
Draws a box plot on the DC.
Notes:
------
Notes
-----
The following draw order is required:
1. First the whisker line
@@ -1235,11 +1229,6 @@ class PlotGraphics(object):
@property
def logScale(self):
# TODO: convert to try..except statement
# try:
# return [obj.logScale for obj in self.objects]
# except: # what error would be returned?
# return
if len(self.objects) == 0:
return
return [obj.logScale for obj in self.objects]
@@ -1254,16 +1243,16 @@ class PlotGraphics(object):
for obj in self.objects:
obj.logScale = logscale
@PendingDeprecation("self.logScale property")
def setLogScale(self, logscale):
"""
Set the log scale boolean value.
.. deprecated:: Feb 27, 2016
Use the :attr:`~wx.lib.plot.PlotGraphics.logScale` property
instead.
Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.logScale`
property instead.
"""
pendingDeprecation("self.logScale property")
self.logScale = logscale
@property
@@ -1294,88 +1283,88 @@ class PlotGraphics(object):
for o in self.objects:
o.scaleAndShift(scale, shift)
@PendingDeprecation("self.printerScale property")
def setPrinterScale(self, scale):
"""
Thickens up lines and markers only for printing
.. deprecated:: Feb 27, 2016
Use the :attr:`~wx.lib.plot.PlotGraphics.printerScale` property
instead.
Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.printerScale`
property instead.
"""
pendingDeprecation("self.printerScale property")
self.printerScale = scale
@PendingDeprecation("self.xLabel property")
def setXLabel(self, xLabel=''):
"""
Set the X axis label on the graph
.. deprecated:: Feb 27, 2016
Use the :attr:`~wx.lib.plot.PlotGraphics.xLabel` property
instead.
"""
Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.xLabel`
property instead.
"""
pendingDeprecation("self.xLabel property")
self.xLabel = xLabel
@PendingDeprecation("self.yLabel property")
def setYLabel(self, yLabel=''):
"""
Set the Y axis label on the graph
.. deprecated:: Feb 27, 2016
Use the :attr:`~wx.lib.plot.PlotGraphics.yLabel` property
instead.
"""
Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.yLabel`
property instead.
"""
pendingDeprecation("self.yLabel property")
self.yLabel = yLabel
@PendingDeprecation("self.title property")
def setTitle(self, title=''):
"""
Set the title at the top of graph
.. deprecated:: Feb 27, 2016
Use the :attr:`~wx.lib.plot.PlotGraphics.title` property
instead.
Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.title`
property instead.
"""
pendingDeprecation("self.title property")
self.title = title
@PendingDeprecation("self.xLabel property")
def getXLabel(self):
"""
Get X axis label string
.. deprecated:: Feb 27, 2016
Use the :attr:`~wx.lib.plot.PlotGraphics.xLabel` property
instead.
Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.xLabel`
property instead.
"""
pendingDeprecation("self.xLabel property")
return self.xLabel
@PendingDeprecation("self.yLabel property")
def getYLabel(self):
"""
Get Y axis label string
.. deprecated:: Feb 27, 2016
Use the :attr:`~wx.lib.plot.PlotGraphics.yLabel` property
instead.
Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.yLabel`
property instead.
"""
pendingDeprecation("self.yLabel property")
return self.yLabel
@PendingDeprecation("self.title property")
def getTitle(self, title=''):
"""
Get the title at the top of graph
.. deprecated:: Feb 27, 2016
Use the :attr:`~wx.lib.plot.PlotGraphics.title` property
instead.
Use the :attr:`~wx.lib.plot.polyobjects.PlotGraphics.title`
property instead.
"""
pendingDeprecation("self.title property")
return self.title
@property
@@ -1445,9 +1434,7 @@ class PlotGraphics(object):
return self.objects[item]
#-------------------------------------------------------------------------
# -------------------------------------------------------------------------
# Used to layout the printer page

View File

@@ -14,6 +14,8 @@ __docformat__ = "restructuredtext en"
# Standard Library
import functools
import inspect
import itertools
from warnings import warn as _warn
# Third Party
@@ -22,8 +24,9 @@ import numpy as np
class DisplaySide(object):
"""
Generic class for storing booleans describing which sides of a box are
displayed. Used for fine-tuning the axis, ticks, and values of a graph.
Generic class for describing which sides of a box are displayed.
Used for fine-tuning the axis, ticks, and values of a graph.
This class somewhat mimics a collections.namedtuple factory function in
that it is an iterable and can have indiviual elements accessible by name.
@@ -34,13 +37,13 @@ class DisplaySide(object):
- it contains type checking, only allowing boolean values
- it contains name checking, only allowing valid_names as attributes
:param bottom: Display the bottom side?
:param bottom: Display the bottom side
:type bottom: bool
:param left: Display the left side?
:param left: Display the left side
:type left: bool
:param top: Display the top side?
:param top: Display the top side
:type top: bool
:param right: Display the right side?
:param right: Display the right side
:type right: bool
"""
# TODO: Do I want to replace with __slots__?
@@ -108,11 +111,14 @@ class DisplaySide(object):
return iter([self.bottom, self.left, self.top, self.right])
# TODO: New name: RevertStyle? SavedStyle? Something else?
# TODO: replace with wx.DCPenChanger/wx.DCBrushChanger, etc.
# Alternatively, replace those with this function...
class TempStyle(object):
"""
Combination Decorator and Context Manager to revert pen or brush changes
after a method call or block finish.
Decorator / Context Manager to revert pen or brush changes.
Will revert pen, brush, or both to their previous values after a method
call or block finish.
:param which: The item to save and revert after execution. Can be
one of ``{'both', 'pen', 'brush'}``.
@@ -137,7 +143,6 @@ class TempStyle(object):
methods**, not standard functions. There is a plan to try and remove
this restriction, but I don't know when that will happen...
.. epigraph::
*Combination Decorator and Context Manager! Also makes Julienne fries!
@@ -235,51 +240,27 @@ class TempStyle(object):
dc.SetBrush(self.prevBrush)
class PendingDeprecation(object):
def pendingDeprecation(new_func):
"""
Decorator which warns the developer about methods that are
pending deprecation.
Raise `PendingDeprecationWarning` and display a message.
:param new_func: The new class, method, or function that should be used.
:type new_func: str
::
@PendingDeprecation("new_func")
def old_func():
pass
# prints the warning:
# `old_func` is pending deprecation. Please use `new_func` instead.
Uses inspect.stack() to determine the name of the item that this
is called from.
:param new_func: The name of the function that should be used instead.
:type new_func: string.
"""
_warn_txt = "`{}` is pending deprecation. Please use `{}` instead."
def __init__(self, new_func):
self.new_func = new_func
def __call__(self, func):
"""Support for functions"""
self.func = func
# self._update_docs()
@functools.wraps(self.func)
def wrapper(*args, **kwargs):
_warn(self._warn_txt.format(self.func.__name__, self.new_func),
PendingDeprecationWarning)
return self.func(*args, **kwargs)
return wrapper
def _update_docs(self):
""" Set the docs to that of the decorated function. """
self.__name__ = self.func.__name__
self.__doc__ = self.func.__doc__
warn_txt = "`{}` is pending deprecation. Please use `{}` instead."
_warn(warn_txt.format(inspect.stack()[1][3], new_func),
PendingDeprecationWarning)
def scale_and_shift_point(x, y, scale=1, shift=0):
"""
Creates a scaled and shifted 2x1 numpy array of [x, y] values.
The shift value must be in the scaled units.
:param float `x`: The x value of the unscaled, unshifted point
:param float `y`: The y valye of the unscaled, unshifted point
:param np.array `scale`: The scale factor to use ``[x_sacle, y_scale]``
@@ -290,6 +271,7 @@ def scale_and_shift_point(x, y, scale=1, shift=0):
:rtype: np.array
.. note::
:math:`new = (scale * old) + shift`
"""
point = scale * np.array([x, y]) + shift
@@ -298,8 +280,7 @@ def scale_and_shift_point(x, y, scale=1, shift=0):
def set_displayside(value):
"""
Wrapper around :class:`~wx.lib.plot._DisplaySide` that allowing for
"overloaded" calls.
Wrapper around :class:`~wx.lib.plot._DisplaySide` that allows for "overloaded" calls.
If ``value`` is a boolean: all 4 sides are set to ``value``
@@ -333,5 +314,11 @@ def set_displayside(value):
return DisplaySide(*_value)
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return zip(a, b)
if __name__ == "__main__":
raise RuntimeError("This module is not intended to be run by itself.")