Revision: 4053
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4053&view=rev
Author: mdboom
Date: 2007-10-29 08:21:49 -0700 (Mon, 29 Oct 2007)
Log Message:
-----------
Lots of minor bug fixes.
Modified Paths:
--------------
branches/transforms/PASSED_DEMOS
branches/transforms/lib/matplotlib/artist.py
branches/transforms/lib/matplotlib/axes.py
branches/transforms/lib/matplotlib/axis.py
branches/transforms/lib/matplotlib/backend_bases.py
branches/transforms/lib/matplotlib/backends/backend_svg.py
branches/transforms/lib/matplotlib/collections.py
branches/transforms/lib/matplotlib/colors.py
branches/transforms/lib/matplotlib/legend.py
branches/transforms/lib/matplotlib/lines.py
branches/transforms/lib/matplotlib/patches.py
branches/transforms/lib/matplotlib/widgets.py
Modified: branches/transforms/PASSED_DEMOS
===================================================================
--- branches/transforms/PASSED_DEMOS 2007-10-29 15:20:13 UTC (rev 4052)
+++ branches/transforms/PASSED_DEMOS 2007-10-29 15:21:49 UTC (rev 4053)
@@ -208,3 +208,5 @@
xcorr_demo.py O
zoom_window.py O
zorder_demo.py O
+
+MGDTODO: units directory
\ No newline at end of file
Modified: branches/transforms/lib/matplotlib/artist.py
===================================================================
--- branches/transforms/lib/matplotlib/artist.py 2007-10-29 15:20:13 UTC
(rev 4052)
+++ branches/transforms/lib/matplotlib/artist.py 2007-10-29 15:21:49 UTC
(rev 4053)
@@ -2,6 +2,7 @@
import re, warnings
from cbook import iterable, flatten
from transforms import Bbox, IdentityTransform, TransformedBbox,
TransformedPath
+from path import Path
## Note, matplotlib artists use the doc strings for set and get
# methods to enable the introspection methods of setp and getp. Every
@@ -285,25 +286,48 @@
def set_clip_path(self, path, transform=None):
"""
- Set the artist's clip path
+ Set the artist's clip path, which may be:
- ACCEPTS: a Path instance and a Transform instance, or a Patch instance
+ a) a Patch (or subclass) instance
+
+ b) a Path instance, in which cas aoptional transform may
+ be provided, which will be applied to the path before using it
+ for clipping.
+
+ c) None, to remove the clipping path
+
+ For efficiency, if the path happens to be an axis-aligned
+ rectangle, this method will set the clipping box to the
+ corresponding rectangle and set the clipping path to None.
+
+ ACCEPTS: a Path instance and a Transform instance, a Patch
+ instance, or None
"""
from patches import Patch, Rectangle
+
+ success = False
if transform is None:
if isinstance(path, Rectangle):
self.clipbox = TransformedBbox(Bbox.unit(),
path.get_transform())
+ success = True
elif isinstance(path, Patch):
self._clippath = TransformedPath(
path.get_path(),
path.get_transform())
- elif path is None:
- self._clippath = None
- else:
- raise TypeError("Invalid arguments to set_clip_path")
- else:
+ success = True
+
+ if path is None:
+ self._clippath = None
+ success = True
+ elif isinstance(path, Path):
self._clippath = TransformedPath(path, transform)
- self._clipon = self.clipbox is not None or path is not None
+ success = True
+
+ if not success:
+ print type(path), type(transform)
+ raise TypeError("Invalid arguments to set_clip_path")
+
+ self._clipon = self.clipbox is not None or self._clippath is not None
self.pchanged()
def get_alpha(self):
@@ -334,6 +358,10 @@
return self._clippath
def get_transformed_clip_path_and_affine(self):
+ '''
+ Return the clip path with the non-affine part of its transformation
applied,
+ and the remaining affine part of its transformation.
+ '''
if self._clippath is not None:
return self._clippath.get_transformed_path_and_affine()
return None, None
Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py 2007-10-29 15:20:13 UTC (rev
4052)
+++ branches/transforms/lib/matplotlib/axes.py 2007-10-29 15:21:49 UTC (rev
4053)
@@ -494,9 +494,6 @@
self.set_label(label)
self.set_figure(fig)
- self._invertedx = False
- self._invertedy = False
-
# this call may differ for non-sep axes, eg polar
self._init_axis()
@@ -553,7 +550,8 @@
def _set_lim_and_transforms(self):
"""
set the dataLim and viewLim BBox attributes and the
- transData and transAxes Transformation attributes
+ transScale, transData, transLimits and transAxes
+ transformations.
"""
self.dataLim = mtransforms.Bbox.unit()
self.viewLim = mtransforms.Bbox.unit()
@@ -579,27 +577,105 @@
self.axes.transAxes, self.axes.transData)
def get_xaxis_transform(self):
+ """
+ Get the transformation used for drawing x-axis labels, ticks
+ and gridlines. The x-direction is in data coordinates and the
+ y-direction is in axis coordinates.
+
+ This transformation is primarily used by the Axis class, and
+ is meant to be overridden by new kinds of projections that may
+ need to place axis elements in different locations.
+ """
return self._xaxis_transform
def get_xaxis_text1_transform(self, pad_pixels):
+ """
+ Get the transformation used for drawing x-axis labels, which
+ will add the given number of pad_pixels between the axes and
+ the label. The x-direction is in data coordinates and the
+ y-direction is in axis coordinates. Returns a 3-tuple of the
+ form:
+
+ (transform, valign, halign)
+
+ where valign and halign are requested alignments for the text.
+
+ This transformation is primarily used by the Axis class, and
+ is meant to be overridden by new kinds of projections that may
+ need to place axis elements in different locations.
+ """
return (self._xaxis_transform +
mtransforms.Affine2D().translate(0, -1 * pad_pixels),
"top", "center")
def get_xaxis_text2_transform(self, pad_pixels):
+ """
+ Get the transformation used for drawing the secondary x-axis
+ labels, which will add the given number of pad_pixels between
+ the axes and the label. The x-direction is in data
+ coordinates and the y-direction is in axis coordinates.
+ Returns a 3-tuple of the form:
+
+ (transform, valign, halign)
+
+ where valign and halign are requested alignments for the text.
+
+ This transformation is primarily used by the Axis class, and
+ is meant to be overridden by new kinds of projections that may
+ need to place axis elements in different locations.
+ """
return (self._xaxis_transform +
mtransforms.Affine2D().translate(0, pad_pixels),
"bottom", "center")
def get_yaxis_transform(self):
+ """
+ Get the transformation used for drawing y-axis labels, ticks
+ and gridlines. The x-direction is in axis coordinates and the
+ y-direction is in data coordinates.
+
+ This transformation is primarily used by the Axis class, and
+ is meant to be overridden by new kinds of projections that may
+ need to place axis elements in different locations.
+ """
return self._yaxis_transform
def get_yaxis_text1_transform(self, pad_pixels):
+ """
+ Get the transformation used for drawing y-axis labels, which
+ will add the given number of pad_pixels between the axes and
+ the label. The x-direction is in axis coordinates and the
+ y-direction is in data coordinates. Returns a 3-tuple of the
+ form:
+
+ (transform, valign, halign)
+
+ where valign and halign are requested alignments for the text.
+
+ This transformation is primarily used by the Axis class, and
+ is meant to be overridden by new kinds of projections that may
+ need to place axis elements in different locations.
+ """
return (self._yaxis_transform +
mtransforms.Affine2D().translate(-1 * pad_pixels, 0),
"center", "right")
def get_yaxis_text2_transform(self, pad_pixels):
+ """
+ Get the transformation used for drawing the secondary y-axis
+ labels, which will add the given number of pad_pixels between
+ the axes and the label. The x-direction is in axis
+ coordinates and the y-direction is in data coordinates.
+ Returns a 3-tuple of the form:
+
+ (transform, valign, halign)
+
+ where valign and halign are requested alignments for the text.
+
+ This transformation is primarily used by the Axis class, and
+ is meant to be overridden by new kinds of projections that may
+ need to place axis elements in different locations.
+ """
return (self._yaxis_transform +
mtransforms.Affine2D().translate(pad_pixels, 0),
"center", "left")
@@ -610,11 +686,11 @@
self.xaxis.get_transform(), self.yaxis.get_transform()))
def get_position(self, original=False):
- 'Return the axes rectangle left, bottom, width, height'
+ 'Return the a copy of the axes rectangle as a Bbox'
if original:
- return self._originalPosition
+ return self._originalPosition.frozen()
else:
- return self._position
+ return self._position.frozen()
def set_position(self, pos, which='both'):
@@ -639,7 +715,6 @@
if which in ('both', 'original'):
self._originalPosition.set(pos)
-
def _set_artist_props(self, a):
'set the boilerplate props for artists added to axes'
a.set_figure(self.figure)
@@ -648,6 +723,16 @@
a.axes = self
def get_axes_patch(self):
+ """
+ Returns the patch used to draw the background of the axes. It
+ is also used as the clipping path for any data elements on the
+ axes.
+
+ In the standard axes, this is a rectangle, but in other
+ projections it may not be.
+
+ Intended to be overridden by new projection types.
+ """
return mpatches.Rectangle((0.0, 0.0), 1.0, 1.0)
def cla(self):
@@ -806,6 +891,12 @@
', '.join(mtransforms.BBox.coefs.keys()))
def get_data_ratio(self):
+ """
+ Returns the aspect ratio of the raw data.
+
+ This method is intended to be overridden by new projection
+ types.
+ """
xmin,xmax = self.get_xbound()
xsize = max(math.fabs(xmax-xmin), 1e-30)
ymin,ymax = self.get_ybound()
@@ -1032,6 +1123,7 @@
a.set_axes(self)
self.artists.append(a)
self._set_artist_props(a)
+ # MGDTODO: We may not want to do this -- the old trunk didn't
a.set_clip_path(self.axesPatch)
a._remove_method = lambda h: self.artists.remove(h)
@@ -1074,19 +1166,20 @@
self._update_patch_limits(p)
self.patches.append(p)
p._remove_method = lambda h: self.patches.remove(h)
-
+
def _update_patch_limits(self, p):
'update the datalimits for patch p'
- xys = self._get_verts_in_data_coords(
- p.get_data_transform(),
- p.get_patch_transform().transform(p.get_path().vertices))
- self.update_datalim(xys)
+ vertices = p.get_patch_transform().transform(p.get_path().vertices)
+ if p.get_data_transform() != self.transData:
+ transform = p.get_data_transform() + self.transData.inverted()
+ xys = transform.transform(vertices)
+ self.update_datalim(vertices)
-
def add_table(self, tab):
'Add a table instance to the list of axes tables'
self._set_artist_props(tab)
self.tables.append(tab)
+ # MGDTODO: We may not want to do this (the old version in trunk didn't)
tab.set_clip_path(self.axesPatch)
tab._remove_method = lambda h: self.tables.remove(h)
@@ -1105,8 +1198,6 @@
# limits and set the bound to be the bounds of the xydata.
# Otherwise, it will compute the bounds of it's current data
# and the data in xydata
- # MGDTODO: This isn't always the most efficient way to do this... in
- # some cases things should use update_datalim_bounds
if not ma.isMaskedArray(xys):
xys = npy.asarray(xys)
self.update_datalim_numerix(xys[:, 0], xys[:, 1])
@@ -1117,7 +1208,6 @@
# limits and set the bound to be the bounds of the xydata.
# Otherwise, it will compute the bounds of it's current data
# and the data in xydata
- ## self.dataLim.update_numerix(x, y, -1)
self.dataLim.update_from_data(x, y, self.ignore_existing_data_limits)
self.ignore_existing_data_limits = False
@@ -1125,16 +1215,6 @@
'Update the datalim to include the given Bbox'
self.dataLim.set(Bbox.union([self.dataLim, bounds]))
- def _get_verts_in_data_coords(self, trans, xys):
- if trans == self.transData:
- return xys
- # data is not in axis data units. We must transform it to
- # display and then back to data to get it in data units
- #xys = trans.seq_xy_tups(xys)
- #return [ self.transData.inverse_xy_tup(xy) for xy in xys]
- xys = trans.transform(npy.asarray(xys))
- return self.transData.inverted().transform(xys)
-
def _process_unit_info(self, xdata=None, ydata=None, kwargs=None):
'look for unit kwargs and update the axis instances as necessary'
@@ -1162,7 +1242,7 @@
self.yaxis.set_units(yunits)
def in_axes(self, mouseevent):
- 'return True is the point xwin, ywin (display coords) are in the Axes'
+ 'return True if the given mouseevent (in display coords) is in the
Axes'
return self.axesPatch.contains(mouseevent)[0]
def get_autoscale_on(self):
@@ -1268,11 +1348,11 @@
if self.axison and self._frameon:
artists.append(self.axesFrame)
- dsu = [ (a.zorder, a) for a in artists
+ dsu = [ (a.zorder, i, a) for i, a in enumerate(artists)
if not a.get_animated() ]
dsu.sort()
- for zorder, a in dsu:
+ for zorder, i, a in dsu:
a.draw(renderer)
renderer.close_group('axes')
@@ -1474,16 +1554,10 @@
self.set_xlim(upper, lower)
def get_xlim(self):
- """Get the x-axis range [xmin, xmax]
-
- NOTE: The returned values are always [xmin, xmax] such that
- xmin < xmax; regardless of whether or not the axes are inverted.
"""
- bound1, bound2 = self.viewLim.intervalx
- if ( self._invertedx ):
- return bound2, bound1
- else:
- return bound1, bound2
+ Get the x-axis range [xmin, xmax]
+ """
+ return self.viewLim.intervalx
def set_xlim(self, xmin=None, xmax=None, emit=True, **kwargs):
"""
@@ -1637,16 +1711,10 @@
self.set_ylim(upper, lower)
def get_ylim(self):
- """Get the y-axis range [xmin, xmax]
-
- NOTE: The returned values are always [ymin, ymax] such that
- ymin < ymax; regardless of whether or not the axes are inverted.
"""
- bound1, bound2 = self.viewLim.intervaly
- if ( self._invertedy ):
- return bound2, bound1
- else:
- return bound1, bound2
+ Get the y-axis range [xmin, xmax]
+ """
+ return self.viewLim.intervaly
def set_ylim(self, ymin=None, ymax=None, emit=True, **kwargs):
"""
@@ -1812,8 +1880,10 @@
def format_coord(self, x, y):
'return a format string formatting the x, y coord'
- if x is None or y is None:
- return ''
+ if x is None:
+ x = '???'
+ if y is None:
+ y = '???'
xs = self.format_xdata(x)
ys = self.format_ydata(y)
return 'x=%s, y=%s'%(xs,ys)
@@ -1855,6 +1925,17 @@
self._navigate_mode = b
def start_pan(self, x, y, button):
+ """
+ Called when a pan operation has started.
+
+ x, y are the mouse coordinates in display coords.
+ button is the mouse button number:
+ 1: LEFT
+ 2: MIDDLE
+ 3: RIGHT
+
+ Intended to be overridden by new projection types.
+ """
self._pan_start = cbook.Bunch(
lim = self.viewLim.frozen(),
trans = self.transData.frozen(),
@@ -1864,9 +1945,29 @@
)
def end_pan(self):
+ """
+ Called when a pan operation completes (when the mouse button
+ is up.)
+
+ Intended to be overridden by new projection types.
+ """
del self._pan_start
def drag_pan(self, button, key, x, y):
+ """
+ Called when the mouse moves during a pan operation.
+
+ button is the mouse button number:
+ 1: LEFT
+ 2: MIDDLE
+ 3: RIGHT
+
+ key is a "shift" key
+
+ x, y are the mouse coordinates in display coords.
+
+ Intended to be overridden by new projection types.
+ """
def format_deltas(key, dx, dy):
if key=='control':
if(abs(dx)>abs(dy)):
@@ -2223,7 +2324,7 @@
%(Annotation)s
"""
a = mtext.Annotation(*args, **kwargs)
- a.set_transform(mtransforms.Affine2D())
+ a.set_transform(mtransforms.IdentityTransform())
self._set_artist_props(a)
if kwargs.has_key('clip_on'): a.set_clip_path(self.axesPatch)
self.texts.append(a)
@@ -4035,9 +4136,9 @@
if len(sh) == 1 and sh[0] == len(x):
colors = None # use cmap, norm after collection is created
else:
- colors = mcolors.colorConverter.to_rgba_list(c, alpha)
+ colors = mcolors.colorConverter.to_rgba_array(c, alpha)
else:
- colors = mcolors.colorConverter.to_rgba_list(c, alpha)
+ colors = mcolors.colorConverter.to_rgba_array(c, alpha)
if not iterable(s):
scales = (s,)
@@ -4137,7 +4238,7 @@
offsets = zip(x,y),
transOffset = self.transData,
)
- collection.set_transform(mtransforms.Affine2D())
+ collection.set_transform(mtransforms.IdentityTransform())
collection.set_alpha(alpha)
collection.update(kwargs)
@@ -4198,6 +4299,9 @@
quiverkey.__doc__ = mquiver.QuiverKey.quiverkey_doc
def quiver(self, *args, **kw):
+ """
+ MGDTODO: Document me
+ """
q = mquiver.Quiver(self, *args, **kw)
self.add_collection(q, False)
self.update_datalim_numerix(q.X, q.Y)
Modified: branches/transforms/lib/matplotlib/axis.py
===================================================================
--- branches/transforms/lib/matplotlib/axis.py 2007-10-29 15:20:13 UTC (rev
4052)
+++ branches/transforms/lib/matplotlib/axis.py 2007-10-29 15:21:49 UTC (rev
4053)
@@ -14,7 +14,7 @@
from font_manager import FontProperties
from text import Text, TextWithDash
from transforms import Affine2D, Bbox, blended_transform_factory, \
- interval_contains
+ IdentityTransform, interval_contains
from patches import bbox_artist
from scale import scale_factory
@@ -113,6 +113,7 @@
self.tick1line.set_clip_path(clippath, transform)
self.tick2line.set_clip_path(clippath, transform)
self.gridline.set_clip_path(clippath, transform)
+ set_clip_path.__doc__ = Artist.set_clip_path.__doc__
def contains(self, mouseevent):
"""Test whether the mouse event occured in the Tick marks.
@@ -1015,7 +1016,7 @@
horizontalalignment='center',
)
label.set_transform( blended_transform_factory(
- self.axes.transAxes, Affine2D() ))
+ self.axes.transAxes, IdentityTransform() ))
self._set_artist_props(label)
self.label_position='bottom'
@@ -1030,7 +1031,7 @@
horizontalalignment='right',
)
offsetText.set_transform( blended_transform_factory(
- self.axes.transAxes, Affine2D() ))
+ self.axes.transAxes, IdentityTransform() ))
self._set_artist_props(offsetText)
self.offset_text_position='bottom'
return offsetText
@@ -1092,11 +1093,11 @@
def set_ticks_position(self, position):
"""
- Set the ticks position (top, bottom, both or default)
- both sets the ticks to appear on both positions, but
- does not change the tick labels.
- default resets the tick positions to the default:
- ticks on both positions, labels at bottom.
+ Set the ticks position (top, bottom, both, default or none)
+ both sets the ticks to appear on both positions, but does not
+ change the tick labels. default resets the tick positions to
+ the default: ticks on both positions, labels at bottom. none
+ can be used if you don't want any ticks.
ACCEPTS: [ 'top' | 'bottom' | 'both' | 'default' | 'none' ]
"""
@@ -1225,7 +1226,7 @@
rotation='vertical',
)
label.set_transform( blended_transform_factory(
- Affine2D(), self.axes.transAxes) )
+ IdentityTransform(), self.axes.transAxes) )
self._set_artist_props(label)
self.label_position='left'
@@ -1240,7 +1241,7 @@
horizontalalignment = 'left',
)
offsetText.set_transform(blended_transform_factory(
- self.axes.transAxes, Affine2D()) )
+ self.axes.transAxes, IdentityTransform()) )
self._set_artist_props(offsetText)
self.offset_text_position='left'
return offsetText
Modified: branches/transforms/lib/matplotlib/backend_bases.py
===================================================================
--- branches/transforms/lib/matplotlib/backend_bases.py 2007-10-29 15:20:13 UTC
(rev 4052)
+++ branches/transforms/lib/matplotlib/backend_bases.py 2007-10-29 15:21:49 UTC
(rev 4053)
@@ -73,7 +73,7 @@
offsets, offsetTrans, facecolors, edgecolors,
linewidths, linestyles, antialiaseds):
path, transform = path_id
- transform = transform.frozen().translate(xo, yo)
+ transform =
transforms.Affine2D(transform.get_matrix()).translate(xo, yo)
self.draw_path(gc, path, transform, rgbFace)
def _iter_collection_raw_paths(self, master_transform, paths,
all_transforms):
@@ -200,6 +200,27 @@
"""
return False
+ def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!'):
+ raise NotImplementedError
+
+ def draw_text(self, gc, x, y, s, prop, angle, ismath=False):
+ """
+ Draw the text.Text instance s at x,y (display coords) with font
+ properties instance prop at angle in degrees, using GraphicsContext gc
+
+ **backend implementers note**
+
+ When you are trying to determine if you have gotten your bounding box
+ right (which is what enables the text layout/alignment to work
+ properly), it helps to change the line in text.py
+
+ if 0: bbox_artist(self, renderer)
+
+ to if 1, and then the actual bounding box will be blotted along with
+ your text.
+ """
+ raise NotImplementedError
+
def flipy(self):
"""return true if y small numbers are top for renderer
Is used for drawing text (text.py) and images (image.py) only
@@ -386,7 +407,8 @@
def set_clip_path(self, path):
"""
- Set the clip path and transformation
+ Set the clip path and transformation. Path should be a
+ transforms.TransformedPath instance.
"""
assert path is None or isinstance(path, transforms.TransformedPath)
self._clippath = path
Modified: branches/transforms/lib/matplotlib/backends/backend_svg.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_svg.py 2007-10-29
15:20:13 UTC (rev 4052)
+++ branches/transforms/lib/matplotlib/backends/backend_svg.py 2007-10-29
15:21:49 UTC (rev 4053)
@@ -205,7 +205,7 @@
for i, (path, transform) in enumerate(self._iter_collection_raw_paths(
master_transform, paths, all_transforms)):
name = 'coll%x_%x' % (self._path_collection_id, i)
- transform = transform.frozen().scale(1.0, -1.0)
+ transform = Affine2D(transform.get_matrix()).scale(1.0, -1.0)
d = self._convert_path(path, transform)
write('<path id="%s" d="%s"/>\n' % (name, d))
path_codes.append(name)
Modified: branches/transforms/lib/matplotlib/collections.py
===================================================================
--- branches/transforms/lib/matplotlib/collections.py 2007-10-29 15:20:13 UTC
(rev 4052)
+++ branches/transforms/lib/matplotlib/collections.py 2007-10-29 15:21:49 UTC
(rev 4053)
@@ -83,12 +83,12 @@
if antialiaseds is None: antialiaseds =
(mpl.rcParams['patch.antialiased'],)
self.set_linestyles(linestyles)
- self._facecolors = _colors.colorConverter.to_rgba_list(facecolors)
+ self._facecolors = _colors.colorConverter.to_rgba_array(facecolors)
if edgecolors == 'None':
self._edgecolors = self._facecolors
linewidths = (0,)
else:
- self._edgecolors = _colors.colorConverter.to_rgba_list(edgecolors)
+ self._edgecolors = _colors.colorConverter.to_rgba_array(edgecolors)
self._linewidths = self._get_value(linewidths)
self._antialiaseds = self._get_value(antialiaseds)
@@ -268,7 +268,7 @@
ACCEPTS: matplotlib color arg or sequence of rgba tuples
"""
- self._facecolors = _colors.colorConverter.to_rgba_list(c, self._alpha)
+ self._facecolors = _colors.colorConverter.to_rgba_array(c, self._alpha)
set_facecolors = set_facecolor
@@ -284,7 +284,7 @@
self._linewidths = (0.0,)
self._edgecolors = npy.array([])
else:
- self._edgecolors = _colors.colorConverter.to_rgba_list(c)
+ self._edgecolors = _colors.colorConverter.to_rgba_array(c)
set_edgecolors = set_edgecolor
def set_alpha(self, alpha):
@@ -581,7 +581,7 @@
if antialiaseds is None: antialiaseds =
(mpl.rcParams['lines.antialiased'],)
self.set_linestyles(linestyles)
- colors = _colors.colorConverter.to_rgba_list(colors)
+ colors = _colors.colorConverter.to_rgba_array(colors)
Collection.__init__(
self,
@@ -633,7 +633,7 @@
ACCEPTS: matplotlib color arg or sequence of rgba tuples
"""
- self._edgecolors = _colors.colorConverter.to_rgba_list(c)
+ self._edgecolors = _colors.colorConverter.to_rgba_array(c)
def color(self, c):
"""
Modified: branches/transforms/lib/matplotlib/colors.py
===================================================================
--- branches/transforms/lib/matplotlib/colors.py 2007-10-29 15:20:13 UTC
(rev 4052)
+++ branches/transforms/lib/matplotlib/colors.py 2007-10-29 15:21:49 UTC
(rev 4053)
@@ -307,12 +307,13 @@
except (TypeError, ValueError), exc:
raise ValueError('to_rgba: Invalid rgba arg "%s"\n%s' % (str(arg),
exc))
- def to_rgba_list(self, c, alpha=None):
+ def to_rgba_array(self, c, alpha=None):
"""
- Returns a list of rgba tuples.
+ Returns an Numpy array of rgba tuples.
Accepts a single mpl color spec or a sequence of specs.
- If the sequence is a list, the list items are changed in place.
+ If the sequence is a list or array, the items are changed in place,
+ but an array copy is still returned.
"""
try:
result = [self.to_rgba(c, alpha)]
@@ -320,7 +321,7 @@
# If c is a list it must be maintained as the same list
# with modified items so that items can be appended to
# it. This is needed for examples/dynamic_collections.py.
- if not isinstance(c, list): # specific; don't need duck-typing
+ if not isinstance(c, (list, npy.ndarray)): # specific; don't need
duck-typing
c = list(c)
for i, cc in enumerate(c):
c[i] = self.to_rgba(cc, alpha) # change in place
Modified: branches/transforms/lib/matplotlib/legend.py
===================================================================
--- branches/transforms/lib/matplotlib/legend.py 2007-10-29 15:20:13 UTC
(rev 4052)
+++ branches/transforms/lib/matplotlib/legend.py 2007-10-29 15:21:49 UTC
(rev 4053)
@@ -363,15 +363,6 @@
bbox.update_from_data_xy(averts, True)
bboxes.append(bbox)
- for handle in ax.collections:
- if isinstance(handle, LineCollection):
- hlines = handle.get_lines()
- trans = handle.get_transform()
- for line in hlines:
- tline = trans.seq_xy_tups(line)
- aline = [inv(v) for v in tline]
- lines.append(aline)
-
return [vertices, bboxes, lines]
def draw_frame(self, b):
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py 2007-10-29 15:20:13 UTC (rev
4052)
+++ branches/transforms/lib/matplotlib/lines.py 2007-10-29 15:21:49 UTC (rev
4053)
@@ -71,6 +71,45 @@
ic1 = breakpoints
return npy.concatenate((ic0[:, npy.newaxis], ic1[:, npy.newaxis]), axis=1)
+def segment_hits(cx,cy,x,y,radius):
+ """Determine if any line segments are within radius of a point. Returns
+ the list of line segments that are within that radius.
+ """
+ # Process single points specially
+ if len(x) < 2:
+ res, = npy.nonzero( (cx - x)**2 + (cy - y)**2 <= radius**2 )
+ return res
+
+ # We need to lop the last element off a lot.
+ xr,yr = x[:-1],y[:-1]
+
+ # Only look at line segments whose nearest point to C on the line
+ # lies within the segment.
+ dx,dy = x[1:]-xr, y[1:]-yr
+ Lnorm_sq = dx**2+dy**2 # Possibly want to eliminate Lnorm==0
+ u = ( (cx-xr)*dx + (cy-yr)*dy )/Lnorm_sq
+ candidates = (u>=0) & (u<=1)
+ #if any(candidates): print "candidates",xr[candidates]
+
+ # Note that there is a little area near one side of each point
+ # which will be near neither segment, and another which will
+ # be near both, depending on the angle of the lines. The
+ # following radius test eliminates these ambiguities.
+ point_hits = (cx - x)**2 + (cy - y)**2 <= radius**2
+ #if any(point_hits): print "points",xr[candidates]
+ candidates = candidates & ~point_hits[:-1] & ~point_hits[1:]
+
+ # For those candidates which remain, determine how far they lie away
+ # from the line.
+ px,py = xr+u*dx,yr+u*dy
+ line_hits = (cx-px)**2 + (cy-py)**2 <= radius**2
+ #if any(line_hits): print "lines",xr[candidates]
+ line_hits = line_hits & candidates
+ points, = point_hits.ravel().nonzero()
+ lines, = line_hits.ravel().nonzero()
+ #print points,lines
+ return npy.concatenate((points,lines))
+
class Line2D(Artist):
lineStyles = _lineStyles = { # hidden names deprecated
'-' : '_draw_solid',
@@ -276,7 +315,6 @@
else:
pixels = self.figure.dpi/72. * self.pickradius
- path, transform =
self._transformed_path.get_transformed_path_and_affine()
if self._linestyle == 'None':
# If no line, return the nearby point(s)
d = npy.sqrt((xt-mouseevent.x)**2 + (yt-mouseevent.y)**2)
@@ -320,7 +358,7 @@
# correct for marker size, if any
if self._marker is not None:
ms = (self._markersize / 72.0 * self.figure.dpi) * 0.5
- bbox = Bbox(bbox.get_points() + [[-ms, -ms], [ms, ms]])
+ bbox = bbox.padded(ms)
return bbox
def set_axes(self, ax):
@@ -399,7 +437,7 @@
"""
set the Transformation instance used by this artist
- ACCEPTS: a matplotlib.transform transformation instance
+ ACCEPTS: a matplotlib.transforms.Transform instance
"""
Artist.set_transform(self, t)
self._transformed_path = TransformedPath(self._path,
self.get_transform())
Modified: branches/transforms/lib/matplotlib/patches.py
===================================================================
--- branches/transforms/lib/matplotlib/patches.py 2007-10-29 15:20:13 UTC
(rev 4052)
+++ branches/transforms/lib/matplotlib/patches.py 2007-10-29 15:21:49 UTC
(rev 4053)
@@ -82,7 +82,7 @@
Returns T/F, {}
"""
- # This is a general version of contains should work on any
+ # This is a general version of contains that should work on any
# patch with a path. However, patches that have a faster
# algebraic solution to hit-testing should override this
# method.
@@ -290,8 +290,8 @@
Patch.__init__(self)
self.patch = patch
self.props = props
- self.ox, self.oy = ox, oy
- self._shadow_transform = transforms.Affine2D().translate(self.ox,
self.oy)
+ self._ox, self._oy = ox, oy
+ self._update_transform()
self._update()
__init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
@@ -308,7 +308,22 @@
self.set_facecolor((r,g,b,0.5))
self.set_edgecolor((r,g,b,0.5))
-
+
+ def _update_transform(self):
+ self._shadow_transform = transforms.Affine2D().translate(self._ox,
self._oy)
+
+ def _get_ox(self):
+ return self._ox
+ def _set_ox(self, ox):
+ self._ox = ox
+ self._update_transform()
+
+ def _get_oy(self):
+ return self._oy
+ def _set_oy(self, oy):
+ self._oy = oy
+ self._update_transform()
+
def get_path(self):
return self.patch.get_path()
Modified: branches/transforms/lib/matplotlib/widgets.py
===================================================================
--- branches/transforms/lib/matplotlib/widgets.py 2007-10-29 15:20:13 UTC
(rev 4052)
+++ branches/transforms/lib/matplotlib/widgets.py 2007-10-29 15:21:49 UTC
(rev 4053)
@@ -849,7 +849,7 @@
self.prev = (0, 0)
if self.direction == 'horizontal':
- trans = (self.ax.transData, self.ax.transAxes)
+ trans = blended_transform_factory(self.ax.transData,
self.ax.transAxes)
w,h = 0,1
else:
trans = blended_transform_factory(self.ax.transAxes,
self.ax.transData)
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins