From: <lee...@us...> - 2009-06-02 01:14:37
|
Revision: 7173 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7173&view=rev Author: leejjoon Date: 2009-06-02 00:31:45 +0000 (Tue, 02 Jun 2009) Log Message: ----------- axes_grid: fix broken spine support Modified Paths: -------------- trunk/matplotlib/examples/axes_grid/simple_axisline.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/ChangeLog trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_rgb.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py Modified: trunk/matplotlib/examples/axes_grid/simple_axisline.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axisline.py 2009-06-01 22:39:49 UTC (rev 7172) +++ trunk/matplotlib/examples/axes_grid/simple_axisline.py 2009-06-02 00:31:45 UTC (rev 7173) @@ -26,7 +26,8 @@ # make new (right-side) yaxis, but wth some offset offset = (20, 0) - new_axisline = ax.get_grid_helper().new_axisline + new_axisline = ax.get_grid_helper().new_fixed_axis + ax.axis["right2"] = new_axisline(loc="right", offset=offset) ax.axis["right2"].label.set_text("Label Y2") Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/ChangeLog =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/ChangeLog 2009-06-01 22:39:49 UTC (rev 7172) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/ChangeLog 2009-06-02 00:31:45 UTC (rev 7173) @@ -1,3 +1,7 @@ +2009-06-01 Jae-Joon Lee <lee...@gm...> + + * axislines.py (Axes.toggle_axisline): fix broken spine support. + 2009-05-04 Jae-Joon Lee <lee...@gm...> * inset_locator.py (inset_axes, zoomed_inset_axes): axes_class support Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_rgb.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_rgb.py 2009-06-01 22:39:49 UTC (rev 7172) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_rgb.py 2009-06-02 00:31:45 UTC (rev 7173) @@ -10,8 +10,8 @@ pad_size = Size.Fraction(pad, Size.AxesY(ax)) - xsize = Size.Fraction(Size.AxesX(ax), (1.-2.*pad)/3.) - ysize = Size.Fraction(Size.AxesY(ax), (1.-2.*pad)/3.) + xsize = Size.Fraction((1.-2.*pad)/3., Size.AxesX(ax)) + ysize = Size.Fraction((1.-2.*pad)/3., Size.AxesY(ax)) divider.set_horizontal([Size.AxesX(ax), pad_size, xsize]) divider.set_vertical([ysize, pad_size, ysize, pad_size, ysize]) @@ -51,6 +51,22 @@ #import matplotlib.axes as maxes import axislines +def imshow_rgb(ax, r, g, b, **kwargs): + ny, nx = r.shape + R = np.zeros([ny, nx, 3], dtype="d") + R[:,:,0] = r + G = np.zeros_like(R) + G[:,:,1] = g + B = np.zeros_like(R) + B[:,:,2] = b + + RGB = R + G + B + + im_rgb = ax.imshow(RGB, **kwargs) + + return im_rgb + + class RGBAxes(object): def __init__(self, *kl, **kwargs): pad = kwargs.pop("pad", 0.0) Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py 2009-06-01 22:39:49 UTC (rev 7172) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py 2009-06-02 00:31:45 UTC (rev 7173) @@ -1249,16 +1249,14 @@ b = not self._axisline_on if b: self._axisline_on = True - #self.frame.set_visible(False) for s in self.spines.values(): - s.artist.set_visible(False) + s.set_visible(False) self.xaxis.set_visible(False) self.yaxis.set_visible(False) else: self._axisline_on = False - #self.frame.set_visible(True) for s in self.spines.values(): - s.artist.set_visible(True) + s.set_visible(True) self.xaxis.set_visible(True) self.yaxis.set_visible(True) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2009-06-03 05:50:06
|
Revision: 7175 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7175&view=rev Author: leejjoon Date: 2009-06-03 05:49:59 +0000 (Wed, 03 Jun 2009) Log Message: ----------- axes_grid: initial checkin of curvelinear grid support Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/mpl_toolkits/axes_grid/ChangeLog trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py Added Paths: ----------- trunk/matplotlib/examples/axes_grid/demo_curvelinear_grid.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/angle_helper.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/clip_path.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_finder.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_helper_curvelinear.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-06-02 02:30:57 UTC (rev 7174) +++ trunk/matplotlib/CHANGELOG 2009-06-03 05:49:59 UTC (rev 7175) @@ -1,3 +1,6 @@ +2009-06-03 axes_grid : Initial check-in of curvelinear grid support. See + examples/axes_grid/demo_curvelinear_grid.py - JJL + 2009-06-01 Spine is now derived from Patch - ADS 2009-06-01 use cbook.is_string_like() instead of isinstance() for spines - ADS Added: trunk/matplotlib/examples/axes_grid/demo_curvelinear_grid.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_curvelinear_grid.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/demo_curvelinear_grid.py 2009-06-03 05:49:59 UTC (rev 7175) @@ -0,0 +1,131 @@ +import numpy as np +#from matplotlib.path import Path + +import matplotlib.pyplot as plt +import matplotlib.cbook as cbook + +from mpl_toolkits.axes_grid.grid_helper_curvelinear import GridHelperCurveLinear +from mpl_toolkits.axes_grid.axislines import Subplot + +from mpl_toolkits.axes_grid.parasite_axes import SubplotHost, \ + ParasiteAxesAuxTrans + + +def curvelinear_test1(fig): + """ + grid for custom transform. + """ + + def tr(x, y): + x, y = np.asarray(x), np.asarray(y) + return x, y-x + + def inv_tr(x,y): + x, y = np.asarray(x), np.asarray(y) + return x, y+x + + + grid_helper = GridHelperCurveLinear((tr, inv_tr)) + + ax1 = Subplot(fig, 1, 2, 1, grid_helper=grid_helper) + # ax1 will have a ticks and gridlines defined by the given + # transform (+ transData of the Axes). Note that the transform of + # the Axes itself (i.e., transData) is not affected by the given + # transform. + + fig.add_subplot(ax1) + + xx, yy = tr([3, 6], [5.0, 10.]) + ax1.plot(xx, yy) + + ax1.set_aspect(1.) + ax1.set_xlim(0, 10.) + ax1.set_ylim(0, 10.) + + ax1.grid(True) + + + +import mpl_toolkits.axes_grid.angle_helper as angle_helper +from matplotlib.projections import PolarAxes +from matplotlib.transforms import Affine2D + +def curvelinear_test2(fig): + """ + polar projection, but in a rectangular box. + """ + + # PolarAxes.PolarTransform takes radian. However, we want our coordinate + # system in degree + tr = Affine2D().scale(np.pi/180., 1.) + PolarAxes.PolarTransform() + + # polar projection, which involves cycle, and also has limits in + # its coordinates, needs a special method to find the extremes + # (min, max of the coordinate within the view). + + # 20, 20 : number of sampling points along x, y direction + extreme_finder = angle_helper.ExtremeFinderCycle(20, 20, + lon_cycle = 360, + lat_cycle = None, + lon_minmax = None, + lat_minmax = (0, np.inf), + ) + + grid_locator1 = angle_helper.LocatorDMS(12) + # Find a grid values appropriate for the coordinate (degree, + # minute, second). + + tick_formatter1 = angle_helper.FormatterDMS() + # And also uses an appropriate formatter. Note that,the + # acceptable Locator and Formatter class is a bit different than + # that of mpl's, and you cannot directly use mpl's Locator and + # Formatter here (but may be possible in the future). + + grid_helper = GridHelperCurveLinear(tr, + extreme_finder=extreme_finder, + grid_locator1=grid_locator1, + tick_formatter1=tick_formatter1 + ) + + + ax1 = SubplotHost(fig, 1, 2, 2, grid_helper=grid_helper) + + # make ticklabels of right and top axis visible. + ax1.axis["right"].major_ticklabels.set_visible(True) + ax1.axis["top"].major_ticklabels.set_visible(True) + + # let right axis shows ticklabels for 1st coordinate (angle) + ax1.axis["right"].get_helper().nth_coord_ticks=0 + # let bottom axis shows ticklabels for 2nd coordinate (radius) + ax1.axis["bottom"].get_helper().nth_coord_ticks=1 + + fig.add_subplot(ax1) + + + # A parasite axes with given transform + ax2 = ParasiteAxesAuxTrans(ax1, tr, "equal") + # note that ax2.transData == tr + ax1.transData + # Anthing you draw in ax2 will match the ticks and grids of ax1. + ax1.parasites.append(ax2) + intp = cbook.simple_linear_interpolation + ax2.plot(intp(np.array([0, 30]), 50), + intp(np.array([10., 10.]), 50)) + + ax1.set_aspect(1.) + ax1.set_xlim(-5, 12) + ax1.set_ylim(-5, 10) + + ax1.grid(True) + +if 1: + fig = plt.figure(1, figsize=(7, 4)) + fig.clf() + + curvelinear_test1(fig) + curvelinear_test2(fig) + + plt.draw() + plt.show() + + + Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/ChangeLog =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/ChangeLog 2009-06-02 02:30:57 UTC (rev 7174) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/ChangeLog 2009-06-03 05:49:59 UTC (rev 7175) @@ -1,6 +1,7 @@ 2009-06-01 Jae-Joon Lee <lee...@gm...> * axislines.py (Axes.toggle_axisline): fix broken spine support. + (AxisArtistHelper): Initial support for curvelinear grid and ticks. 2009-05-04 Jae-Joon Lee <lee...@gm...> Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid/angle_helper.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/angle_helper.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/angle_helper.py 2009-06-03 05:49:59 UTC (rev 7175) @@ -0,0 +1,345 @@ +from math import floor + +import numpy as np +import math + +A = np.array + +from mpl_toolkits.axes_grid.grid_finder import ExtremeFinderSimple + +def select_step_degree(dv): + + degree_limits_ = [1.5, 3, 7, 13, 20, 40, 70, 120, 270, 520] + degree_steps_ = [ 1, 2, 5, 10, 15, 30, 45, 90, 180, 360] + degree_factors = [1.] * len(degree_steps_) + + minsec_limits_ = [1.5, 2.5, 3.5, 8, 11, 18, 25, 45] + minsec_steps_ = [1, 2, 3, 5, 10, 15, 20, 30] + + minute_limits_ = A(minsec_limits_)*(1./60.) + minute_factors = [60.] * len(minute_limits_) + + second_limits_ = A(minsec_limits_)*(1./3600.) + second_factors = [3600.] * len(second_limits_) + + degree_limits = np.concatenate([second_limits_, + minute_limits_, + degree_limits_]) + + degree_steps = np.concatenate([minsec_steps_, + minsec_steps_, + degree_steps_]) + + degree_factors = np.concatenate([second_factors, + minute_factors, + degree_factors]) + + n = degree_limits.searchsorted(dv) + step = degree_steps[n] + factor = degree_factors[n] + + return step, factor + + + +def select_step_hour(dv): + + hour_limits_ = [1.5, 2.5, 3.5, 5, 7, 10, 15, 21, 36] + hour_steps_ = [1, 2 , 3, 4, 6, 8, 12, 18, 24] + hour_factors = [1.] * len(hour_steps_) + + minsec_limits_ = [1.5, 2.5, 3.5, 4.5, 5.5, 8, 11, 14, 18, 25, 45] + minsec_steps_ = [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30] + + minute_limits_ = A(minsec_limits_)*(1./60.) + minute_factors = [60.] * len(minute_limits_) + + second_limits_ = A(minsec_limits_)*(1./3600.) + second_factors = [3600.] * len(second_limits_) + + hour_limits = np.concatenate([second_limits_, + minute_limits_, + hour_limits_]) + + hour_steps = np.concatenate([minsec_steps_, + minsec_steps_, + hour_steps_]) + + hour_factors = np.concatenate([second_factors, + minute_factors, + hour_factors]) + + n = hour_limits.searchsorted(dv) + step = hour_steps[n] + factor = hour_factors[n] + + return step, factor + + +def select_step_sub(dv): + + # subarcsec or degree + tmp = 10.**(int(math.log10(dv))-1.) + dv2 = dv/tmp + substep_limits_ = [1.5, 3., 7.] + substep_steps_ = [1. , 2., 5.] + + factor = 1./tmp + + if 1.5*tmp >= dv: + step = 1 + elif 3.*tmp >= dv: + step = 2 + elif 7.*tmp >= dv: + step = 5 + else: + step = 1 + factor = 0.1*factor + + return step, factor + + +def select_step(v1, v2, nv, hour=False): + + if v1 > v2: + v1, v2 = v2, v1 + + A = np.array + + dv = float(v2 - v1) / nv + + if hour: + _select_step = select_step_hour + cycle = 24. + else: + _select_step = select_step_degree + cycle = 360. + + # for degree + if dv > 1./3600.: + #print "degree" + step, factor = _select_step(dv) + else: + step, factor = select_step_sub(dv*3600.) + #print "feac", step, factor + + factor = factor * 3600. + + + f1, f2, fstep = v1*factor, v2*factor, step/factor + levs = np.arange(math.floor(f1/step), math.ceil(f2/step)+0.5, + 1, dtype="i") * step + + # n : number valid levels. If there is a cycle, e.g., [0, 90, 180, + # 270, 360], the a grid line needs to be extend from 0 to 360, so + # we need to return the whole array. However, the last level (360) + # needs to be ignored often. In this case, so we return n=4. + + n = len(levs) + + + # we need to check the range of values + # for example, -90 to 90, 0 to 360, + + + if factor == 1. and (levs[-1] >= levs[0]+cycle): # check for cycle + nv = int(cycle / step) + levs = np.arange(0, nv, 1) * step + n = len(levs) + + return levs, n, factor + + +def select_step24(v1, v2, nv): + v1, v2 = v1/15., v2/15. + levs, n, factor = select_step(v1, v2, nv, hour=True) + return levs*15., n, factor + +def select_step360(v1, v2, nv): + return select_step(v1, v2, nv, hour=False) + + + + +class LocatorHMS(object): + def __init__(self, den): + self.den = den + def __call__(self, v1, v2): + return select_step24(v1, v2, self.den) + + +class LocatorDMS(object): + def __init__(self, den): + self.den = den + def __call__(self, v1, v2): + return select_step360(v1, v2, self.den) + + +class FormatterHMS(object): + def __call__(self, direction, factor, values): # hour + if len(values) == 0: + return [] + ss = [[-1, 1][v>0] for v in values] + values = np.abs(values)/15. + + if factor == 1: + return ["$%d^{\mathrm{h}}$" % (int(v),) for v in values] + elif factor == 60: + return ["$%d^{\mathrm{h}}\,%02d^{\mathrm{m}}$" % (s*floor(v/60.), v%60) \ + for s, v in zip(ss, values)] + elif factor == 3600: + if ss[-1] == -1: + inverse_order = True + values = values[::-1] + else: + inverse_order = False + degree = floor(values[0]/3600.) + hm_fmt = "$%d^{\mathrm{h}}\,%02d^{\mathrm{m}}\," + s_fmt = "%02d^{\mathrm{s}}$" + l_hm_old = "" + r = [] + for v in values-3600*degree: + l_hm = hm_fmt % (ss[0]*degree, floor(v/60.)) + l_s = s_fmt % (v%60,) + if l_hm != l_hm_old: + l_hm_old = l_hm + l = l_hm + l_s + else: + l = "$"+l_s + r.append(l) + if inverse_order: + return r[::-1] + else: + return r + #return [fmt % (ss[0]*degree, floor(v/60.), v%60) \ + # for s, v in zip(ss, values-3600*degree)] + else: # factor > 3600. + return ["$%s$" % (str(v),) for v in values] + + +class FormatterDMS(object): + def __call__(self, direction, factor, values): + if len(values) == 0: + return [] + ss = [[-1, 1][v>0] for v in values] + values = np.abs(values) + if factor == 1: + return ["$%d^{\circ}$" % (s*int(v),) for (s, v) in zip(ss, values)] + elif factor == 60: + return ["$%d^{\circ}\,%02d^{\prime}$" % (s*floor(v/60.), v%60) \ + for s, v in zip(ss, values)] + elif factor == 3600: + if ss[-1] == -1: + inverse_order = True + values = values[::-1] + else: + inverse_order = False + degree = floor(values[0]/3600.) + hm_fmt = "$%d^{\circ}\,%02d^{\prime}\," + s_fmt = "%02d^{\prime\prime}$" + l_hm_old = "" + r = [] + for v in values-3600*degree: + l_hm = hm_fmt % (ss[0]*degree, floor(v/60.)) + l_s = s_fmt % (v%60,) + if l_hm != l_hm_old: + l_hm_old = l_hm + l = l_hm + l_s + else: + l = "$"+l_s + r.append(l) + if inverse_order: + return r[::-1] + else: + return r + #return [fmt % (ss[0]*degree, floor(v/60.), v%60) \ + # for s, v in zip(ss, values-3600*degree)] + else: # factor > 3600. + return ["$%s$" % (str(v),) for v in ss*values] + + + + +class ExtremeFinderCycle(ExtremeFinderSimple): + """ + When there is a cycle, e.g., longitude goes from 0-360. + """ + def __init__(self, + nx, ny, + lon_cycle = 360., + lat_cycle = None, + lon_minmax = None, + lat_minmax = (-90, 90) + ): + #self.transfrom_xy = transform_xy + #self.inv_transfrom_xy = inv_transform_xy + self.nx, self.ny = nx, ny + self.lon_cycle, self.lat_cycle = lon_cycle, lat_cycle + self.lon_minmax = lon_minmax + self.lat_minmax = lat_minmax + + + def __call__(self, transform_xy, x1, y1, x2, y2): + """ + get extreme values. + + x1, y1, x2, y2 in image coordinates (0-based) + nx, ny : number of dvision in each axis + """ + x_, y_ = np.linspace(x1, x2, self.nx), np.linspace(y1, y2, self.ny) + x, y = np.meshgrid(x_, y_) + lon, lat = transform_xy(np.ravel(x), np.ravel(y)) + + # iron out jumps, but algorithm should be improved. + # Tis is just naive way of doing and my fail for some cases. + if self.lon_cycle is not None: + lon0 = lon.min() + lon -= 360. * ((lon - lon0) > 180.) + if self.lat_cycle is not None: + lat0 = lat.min() + lat -= 360. * ((lat - lat0) > 180.) + + lon_min, lon_max = lon.min(), lon.max() + lat_min, lat_max = lat.min(), lat.max() + + lon_min, lon_max, lat_min, lat_max = \ + self._adjust_extremes(lon_min, lon_max, lat_min, lat_max) + + return lon_min, lon_max, lat_min, lat_max + + + def _adjust_extremes(self, lon_min, lon_max, lat_min, lat_max): + + lon_min, lon_max, lat_min, lat_max = \ + self._add_pad(lon_min, lon_max, lat_min, lat_max) + + # check cycle + if self.lon_cycle: + lon_max = min(lon_max, lon_min + self.lon_cycle) + if self.lat_cycle: + lat_max = min(lat_max, lat_min + self.lat_cycle) + + if self.lon_minmax is not None: + min0 = self.lon_minmax[0] + lon_min = max(min0, lon_min) + max0 = self.lon_minmax[1] + lon_max = min(max0, lon_max) + + if self.lat_minmax is not None: + min0 = self.lat_minmax[0] + lat_min = max(min0, lat_min) + max0 = self.lat_minmax[1] + lat_max = min(max0, lat_max) + + return lon_min, lon_max, lat_min, lat_max + + + + + +if __name__ == "__main__": + #test2() + print select_step360(21.2, 33.3, 5) + print select_step360(20+21.2/60., 21+33.3/60., 5) + print select_step360(20.5+21.2/3600., 20.5+33.3/3600., 5) + print select_step360(20+21.2/60., 20+53.3/60., 5) Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py 2009-06-02 02:30:57 UTC (rev 7174) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py 2009-06-03 05:49:59 UTC (rev 7175) @@ -1,3 +1,48 @@ +""" +Axislines includes modified implementation of the Axes class. The +biggest difference is that the artists responsible to draw axis line, +ticks, ticklabel and axis labels are separated out from the mpl's Axis +class, which are much more than artists in the original +mpl. Originally, this change was motivated to support curvlinear +grid. Here are a few reasons that I came up with new axes class. + + + * "top" and "bottom" x-axis (or "left" and "right" y-axis) can have + different ticks (tick locations and labels). This is not possible + with the current mpl, although some twin axes trick can help. + + * Curvelinear grid. + + * angled ticks. + +In the new axes class, xaxis and yaxis is set to not visible by +default, and new set of artist (AxisArtist) are defined to draw axis +line, ticks, ticklabels and axis label. Axes.axis attribute serves as +a dictionary of these artists, i.e., ax.axis["left"] is a AxisArtist +instance responsible to draw left y-axis. The default Axes.axis contains +"bottom", "left", "top" and "right". + +AxisArtist can be considered as a container artist and +has following children artists which will draw ticks, labels, etc. + + * line + * major_ticks, major_ticklabels + * minor_ticks, minor_ticklabels + * offsetText + * label + +Note that these are separate artists from Axis class of the +original mpl, thus most of tick-related command in the original mpl +won't work, although some effort has made to work with. For example, +color and markerwidth of the ax.axis["bottom"].major_ticks will follow +those of Axes.xaxis unless explicitly specified. + +In addition to AxisArtist, the Axes will have *gridlines* attribute, +which obviously draws grid lines. The gridlines needs to be separated +from the axis as some gridlines can never pass any axis. + +""" + import matplotlib.axes as maxes import matplotlib.artist as martist import matplotlib.text as mtext @@ -73,25 +118,92 @@ class UnimplementedException(Exception): pass -class AxisLineHelper(object): + + +class AxisArtistHelper(object): + """ + AxisArtistHelper should define + following method with given APIs. Note that the first axes argument + will be axes attribute of the caller artist. + + + # LINE + + def get_line(self, axes): + # path : Path + return path + + def get_line_transform(self, axes): + # ... + # trans : transform + return trans + + # LABEL + + def get_label_pos(self, axes): + # x, y : position + return (x, y), trans + + + def get_label_offset_transform(self, \ + axes, + pad_points, fontprops, renderer, + bboxes, + ): + # va : vertical alignment + # ha : horizontal alignment + # a : angle + return trans, va, ha, a + + # TICK + + def get_tick_transform(self, axes): + return trans + + def get_tick_iterators(self, axes): + # iter : iteratoable object that yields (c, angle, l) where + # c, angle, l is position, tick angle, and label + + return iter_major, iter_minot + + + """ class _Base(object): + def __init__(self, label_direction): self.label_direction = label_direction - def get_label_pos(self): - raise UnimplementedException("") + #def update(self): + # raise UnimplementedException("update method not implemented") + def update_lim(self, axes): + pass + _label_angles = dict(left=90, right=90, bottom=0, top=0) _ticklabel_angles = dict(left=0, right=0, bottom=0, top=0) - def _get_label_transform(self, pad_points, fontprops, renderer, - bboxes=None, - trans=None): + def _get_label_offset_transform(self, pad_points, fontprops, renderer, + bboxes=None, + #trans=None + ): - if trans is None: - trans = self.axes.transAxes + """ + Returns (offset-transform, vertical-alignment, horiz-alignment) + of (tick or axis) labels appropriate for the label + direction. - #dpi_scale_trans = self.axes.figure.dpi_scale_trans + The offset-transform represents a required pixel offset + from the reference point. For example, x-axis center will + be the referece point for xlabel. + + pad_points : padding from axis line or tick labels (see bboxes) + fontprops : font properties for label + renderer : renderer + bboxes=None : list of bboxes (window extents) of the tick labels. + + all the above parameters are used to estimate the offset. + + """ if renderer: pad_pixels = renderer.points_to_pixels(pad_points) font_size_points = fontprops.get_size_in_points() @@ -111,74 +223,64 @@ tr = Affine2D() if self.label_direction == "left": tr.translate(-(pad_pixels+w), 0.) - trans = trans + tr + #trans = trans + tr - return trans, "center", "right" + return tr, "center", "right" elif self.label_direction == "right": tr.translate(+(pad_pixels+w), 0.) - #tr = ScaledTranslation(+((pad_points+w) / 72.), 0., - # dpi_scale_trans) - trans = trans + tr + #trans = trans + tr - return trans, "center", "left" + return tr, "center", "left" elif self.label_direction == "bottom": - #pad_points = font_size_points + pad_points tr.translate(0, -(pad_pixels+font_size_pixels+h)) - trans = trans + tr + #trans = trans + tr - return trans, "baseline", "center" + return tr, "baseline", "center" elif self.label_direction == "top": - #pad_points = font_size_points/8. + pad_points - #tr.translate(0, +(pad_pixels+font_size_pixels/6.+h)) - #tr.translate(0, +(pad_pixels+font_size_pixels/10.+h)) tr.translate(0, +(pad_pixels+h)) - #tr = ScaledTranslation(0, (pad_points+h) / 72., - # dpi_scale_trans) - trans = trans + tr + #trans = trans + tr - return trans, "baseline", "center" + return tr, "baseline", "center" else: raise ValueError("") - def get_label_transform(self, pad_points, fontprops, renderer, - bboxes, - trans=None): + def get_label_offset_transform(self, + axes, + pad_points, fontprops, renderer, + bboxes, + #trans=None + ): - tr, va, ha = self._get_label_transform(pad_points, fontprops, - renderer, - bboxes, trans) + tr, va, ha = self._get_label_offset_transform(pad_points, fontprops, + renderer, + bboxes, + #trans + ) a = self._label_angles[self.label_direction] return tr, va, ha, a - def get_ticklabel_transform(self, pad_points, fontprops, renderer, - trans=None): - tr, va, ha = self._get_label_transform(pad_points, fontprops, - renderer, - None, trans) + def get_ticklabel_offset_transform(self, axes, + pad_points, fontprops, + renderer, + ): + tr, va, ha = self._get_label_offset_transform(pad_points, fontprops, + renderer, + None, + ) + a = self._ticklabel_angles[self.label_direction] return tr, va, ha, a - def get_line_transform(self): - return self.axes.transAxes - def get_line(self): - raise UnimplementedException("") - def get_tick_transform(self): - raise UnimplementedException("") - - def get_tick_iterators(self): - raise UnimplementedException("") - - class Fixed(_Base): _default_passthru_pt = dict(left=(0, 0), @@ -186,13 +288,13 @@ bottom=(0, 0), top=(0, 1)) - def __init__(self, axes, loc, nth_coord=None, + def __init__(self, + loc, nth_coord=None, passingthrough_point=None, label_direction=None): """ nth_coord = along which coordinate value varies in 2d, nth_coord = 0 -> x axis, nth_coord = 1 -> y axis """ - self.axes = axes if loc not in ["left", "right", "bottom", "top"]: raise ValueError("%s" % loc) @@ -203,9 +305,8 @@ nth_coord = 0 self.nth_coord = nth_coord - self.axis = [self.axes.xaxis, self.axes.yaxis][self.nth_coord] - super(AxisLineHelper.Fixed, self).__init__(loc) + super(AxisArtistHelper.Fixed, self).__init__(loc) if passingthrough_point is None: passingthrough_point = self._default_passthru_pt[loc] @@ -220,113 +321,160 @@ fixed_coord = 1-nth_coord _verts[:,fixed_coord] = self.passthru_pt[fixed_coord] + # axis line in transAxes self._path = Path(_verts) def get_nth_coord(self): return self.nth_coord - def get_line(self): + # LINE + + def get_line(self, axes): return self._path - def get_label_pos(self): + def get_line_transform(self, axes): + return axes.transAxes + + # LABLE + + def get_label_pos(self, axes): + """ + label reference position in transAxes. + + get_label_transform() returns a transform of (transAxes+offset) + """ _verts = [0.5, 0.5] nth_coord = self.nth_coord fixed_coord = 1-nth_coord _verts[fixed_coord] = self.passthru_pt[fixed_coord] - return _verts, self.axes.transAxes + return _verts, axes.transAxes - def get_tick_transform(self): - trans_tick = [self.axes.get_xaxis_transform(), - self.axes.get_yaxis_transform()][self.nth_coord] - return trans_tick + def get_label_offset_transform(self, axes, + pad_points, fontprops, renderer, + bboxes, + ): - def get_tick_iterators(self): - """tick_loc, tick_angle, tick_label""" + tr, va, ha = self._get_label_offset_transform( \ + pad_points, fontprops, renderer, bboxes, + #trans + ) - angle = 0 - 90 * self.nth_coord - if self.passthru_pt[1 - self.nth_coord] > 0.5: - angle = 180+angle + a = self._label_angles[self.label_direction] + #tr = axes.transAxes + tr - major = self.axis.major - majorLocs = major.locator() - major.formatter.set_locs(majorLocs) - majorLabels = [major.formatter(val, i) for i, val in enumerate(majorLocs)] + return tr, va, ha, a - minor = self.axis.minor - minorLocs = minor.locator() - minor.formatter.set_locs(minorLocs) - minorLabels = [minor.formatter(val, i) for i, val in enumerate(minorLocs)] - trans_tick = self.get_tick_transform() - tr2ax = trans_tick + self.axes.transAxes.inverted() + # TICK - def _f(locs, labels): - for x, l in zip(locs, labels): + def get_tick_transform(self, axes): + trans_tick = [axes.get_xaxis_transform(), + axes.get_yaxis_transform()][self.nth_coord] - c = list(self.passthru_pt) # copy - c[self.nth_coord] = x + return trans_tick - c2 = tr2ax.transform_point(c) - delta=0.001 - if 0. -delta<= c2[self.nth_coord] <= 1.+delta: - yield c, angle, l - return _f(majorLocs, majorLabels), _f(minorLocs, minorLabels) - class Floating(_Base): - def __init__(self, axes, nth_coord, + def __init__(self, nth_coord, passingthrough_point, label_direction, transform): - self.axes = axes self.nth_coord = nth_coord - self.axis = [self.axes.xaxis, self.axes.yaxis][self.nth_coord] self.passingthrough_point = passingthrough_point self.transform = transform - super(AxisLineHelper.Floating, self).__init__(label_direction) + super(AxisArtistHelper.Floating, + self).__init__(label_direction) + def get_nth_coord(self): return self.nth_coord - def get_line(self): + def get_line(self, axes): _verts = np.array([[0., 0.], [1., 1.]]) fixed_coord = 1-self.nth_coord - trans_passingthrough_point = self.transform + self.axes.transAxes.inverted() + trans_passingthrough_point = self.transform + axes.transAxes.inverted() p = trans_passingthrough_point.transform_point(self.passingthrough_point) _verts[:,fixed_coord] = p[fixed_coord] return Path(_verts) + def get_line_transform(self, axes): + return axes.transAxes - def get_label_pos(self): + def get_label_pos(self, axes): _verts = [0.5, 0.5] fixed_coord = 1-self.nth_coord - trans_passingthrough_point = self.transform + self.axes.transAxes.inverted() + trans_passingthrough_point = self.transform + axes.transAxes.inverted() p = trans_passingthrough_point.transform_point(self.passingthrough_point) _verts[fixed_coord] = p[fixed_coord] if not (0. <= _verts[fixed_coord] <= 1.): return None, None else: - return _verts, self.axes.transAxes + return _verts, axes.transAxes + def get_label_transform(self, axes, + pad_points, fontprops, renderer, + bboxes, + ): + tr, va, ha = self._get_label_offset_transform(pad_points, fontprops, + renderer, + bboxes, + #trans + ) - def get_tick_transform(self): + a = self._label_angles[self.label_direction] + tr = axes.transAxes + tr + #tr = axes.transAxes + tr + + return tr, va, ha, a + + + + def get_tick_transform(self, axes): return self.transform - def get_tick_iterators(self): + + + + +class AxisArtistHelperRectlinear: + + class Fixed(AxisArtistHelper.Fixed): + + def __init__(self, + axes, loc, nth_coord=None, + passingthrough_point=None, label_direction=None): + """ + nth_coord = along which coordinate value varies + in 2d, nth_coord = 0 -> x axis, nth_coord = 1 -> y axis + """ + + super(AxisArtistHelperRectlinear.Fixed, self).__init__( \ + loc, nth_coord, + passingthrough_point, label_direction) + + self.axis = [axes.xaxis, axes.yaxis][self.nth_coord] + + + + # TICK + + def get_tick_iterators(self, axes): """tick_loc, tick_angle, tick_label""" angle = 0 - 90 * self.nth_coord + if self.passthru_pt[1 - self.nth_coord] > 0.5: + angle = 180+angle major = self.axis.major majorLocs = major.locator() @@ -338,11 +486,56 @@ minor.formatter.set_locs(minorLocs) minorLabels = [minor.formatter(val, i) for i, val in enumerate(minorLocs)] - tr2ax = self.transform + self.axes.transAxes.inverted() + trans_tick = self.get_tick_transform(axes) + tr2ax = trans_tick + axes.transAxes.inverted() + def _f(locs, labels): for x, l in zip(locs, labels): + c = list(self.passthru_pt) # copy + c[self.nth_coord] = x + + # check if the tick point is inside axes + c2 = tr2ax.transform_point(c) + delta=0.001 + if 0. -delta<= c2[self.nth_coord] <= 1.+delta: + yield c, angle, l + + return _f(majorLocs, majorLabels), _f(minorLocs, minorLabels) + + + + class Floating(AxisArtistHelper.Floating): + def __init__(self, axes, nth_coord, + passingthrough_point, label_direction, transform): + + super(AxisArtistHelperRectlinear.Floating, self).__init__( \ + nth_coord, passingthrough_point, label_direction, transform) + + self.axis = [axes.xaxis, axes.yaxis][self.nth_coord] + + + def get_tick_iterators(self, axes): + """tick_loc, tick_angle, tick_label""" + + angle = 0 - 90 * self.nth_coord + + major = self.axis.major + majorLocs = major.locator() + major.formatter.set_locs(majorLocs) + majorLabels = [major.formatter(val, i) for i, val in enumerate(majorLocs)] + + minor = self.axis.minor + minorLocs = minor.locator() + minor.formatter.set_locs(minorLocs) + minorLabels = [minor.formatter(val, i) for i, val in enumerate(minorLocs)] + + tr2ax = self.transform + axes.transAxes.inverted() + + def _f(locs, labels): + for x, l in zip(locs, labels): + c = list(self.passingthrough_point) # copy c[self.nth_coord] = x c1, c2 = tr2ax.transform_point(c) @@ -352,34 +545,60 @@ return _f(majorLocs, majorLabels), _f(minorLocs, minorLabels) -class GridHelperRectlinear(object): + +class GridHelperBase(object): + def __init__(self): - self.axes = None self._force_update = True + self._old_limits = None + super(GridHelperBase, self).__init__() - def set_axes(self, axes): - self.axes = axes + def update_lim(self, axes): + x1, x2 = axes.get_xlim() + y1, y2 = axes.get_ylim() + + if self._force_update or self._old_limits != (x1, x2, y1, y2): + self._update(x1, x2, y1, y2) + self._force_update = False + self._old_limits = (x1, x2, y1, y2) + + def _update(self, x1, x2, y1, y2): - self._force_update = False + pass + def invalidate(self): self._force_update = True + def get_gridlines(self): return [] - def _get_axisline_helper(self, nth_coord, loc, + + +class GridHelperRectlinear(GridHelperBase): + + + def __init__(self, axes): + + super(GridHelperRectlinear, self).__init__() + self.axes = axes + + #def set_axes(self, axes): + # self.axes = axes + + def _get_axisline_helper_deprecated(self, nth_coord, loc, passingthrough_point, transform=None): if transform is None or transform is self.axes.transAxes: - return AxisLineHelper.Fixed(self.axes, loc, + return AxisArtistHelper.Fixed(self.axes, loc, nth_coord, passingthrough_point) else: label_direction = loc - return AxisLineHelper.Floating(self.axes, + return AxisArtistHelper.Floating(self.axes, nth_coord, passingthrough_point, label_direction, transform) @@ -390,16 +609,23 @@ #transform=None, tick_direction="in", label_direction=None, - offset=None): + offset=None, + axes=None, + ): - _helper = AxisLineHelper.Fixed(self.axes, loc, - nth_coord, passthrough_point) + if axes is None: + warnings.warn("'new_fixed_axis' explicitly requires the axes keyword.") + axes = self.axes - axisline = AxisLine(self.axes, _helper, - #tick_direction="in", - offset=offset, - ) + _helper = AxisArtistHelperRectlinear.Fixed(axes, loc, + nth_coord, + passthrough_point) + axisline = AxisArtist(axes, _helper, + #tick_direction="in", + offset=offset, + ) + return axisline @@ -407,21 +633,27 @@ transform=None, tick_direction="in", label_direction=None, - ): + axes=None, + ): - _helper = AxisLineHelper.Floating(self.axes, - nth_coord, passthrough_point, - label_direction, - transform) + if axes is None: + warnings.warn("'new_floating_axis' explicitly requires the axes keyword.") + axes = self.axes - axisline = AxisLine(self.axes, _helper, - #tick_direction="in", - ) + _helper = AxisArtistHelperRectlinear.Floating( \ + axes, + nth_coord, passthrough_point, + label_direction, + transform) + axisline = AxisArtist(axes, _helper, + #tick_direction="in", + ) + return axisline - def new_axisline(self, loc, + def new_axisline_deprecated(self, loc, nth_coord=None, passthrough_point=None, transform=None, tick_direction="in", @@ -435,7 +667,7 @@ passthrough_point, transform) - axisline = AxisLine(self.axes, _helper, + axisline = AxisArtist(self.axes, _helper, #tick_direction="in", offset=offset, ) @@ -444,18 +676,9 @@ - - - -class XYEvent: - def __init__(self, xy): - self.x, self.y = xy - - from matplotlib.lines import Line2D class Ticks(Line2D): -#LineCollection def __init__(self, ticksize, **kwargs): self.ticksize = ticksize self.locs_angles = [] @@ -608,6 +831,9 @@ # return Bbox.from_bounds(0, 0, 0, 0) + + + class AxisLabel(mtext.Text): def __init__(self, *kl, **kwargs): self._axis = kwargs.pop("axis", None) @@ -635,279 +861,40 @@ return self._text -class AxisGridLineBase(martist.Artist): - def __init__(self, *kl, **kw): - super(AxisGridLineBase, self).__init__(*kl, **kw) +class GridlinesCollection(LineCollection): + def __init__(self, *kl, **kwargs): + super(GridlinesCollection, self).__init__(*kl, **kwargs) + self.set_grid_helper(None) + def set_grid_helper(self, grid_helper): + self._grid_helper = grid_helper - -class GridLine(AxisGridLineBase): - """ a line along which the n-th axes coord is constant.""" - - LABELPAD = 5 - ZORDER=2.5 - - def __init__(self, axes, - helper, - #offset_transform=None, - offset=None, - major_tick_size=None, - major_tick_pad=None, - minor_tick_size=None, - minor_tick_pad=None, - **kw): - - AxisGridLineBase.__init__(self, **kw) - - self.axes = axes - - self._helper = helper - - #if offset_transform is None: - # self.offset_transform = IdentityTransform() - #else: - # self.offset_transform = offset_transform - - if offset is None: - offset = (0, 0) - self.dpi_transform = Affine2D() - self.offset_transform = ScaledTranslation(offset[0], offset[1], - self.dpi_transform) - - self.set_transform(axes.transAxes + \ - self.offset_transform) - - self._label_visible = True - self._majortick_visible = True - self._majorticklabel_visible = True - self._minortick_visible = True - self._minorticklabel_visible = True - - - if self._helper.label_direction in ["left", "right"]: - axis_name = "ytick" - else: - axis_name = "xtick" - - - if major_tick_size is None: - self.major_tick_size = rcParams['%s.major.size'%axis_name] - if major_tick_pad is None: - self.major_tick_pad = rcParams['%s.major.pad'%axis_name] - if minor_tick_size is None: - self.minor_tick_size = rcParams['%s.minor.size'%axis_name] - if minor_tick_pad is None: - self.minor_tick_pad = rcParams['%s.minor.pad'%axis_name] - - self._init_line() - self._init_ticks() - self._init_label() - - self.set_zorder(self.ZORDER) - - def _init_line(self): - tran = self._helper.get_line_transform() + self.offset_transform - self.line = BezierPath(self._helper.get_line(), - color=rcParams['axes.edgecolor'], - linewidth=rcParams['axes.linewidth'], - transform=tran) - - def get_helper(self): - return self._helper - - def _draw_line(self, renderer): - self.line.set_path(self._helper.get_line()) - self.line.draw(renderer) - - - def _init_ticks(self): - - transform=self._helper.get_tick_transform()+self.offset_transform - - self.major_ticks = Ticks(self.major_tick_size, - transform=transform) - self.minor_ticks = Ticks(self.minor_tick_size, - transform=transform) - - - size = rcParams['xtick.labelsize'] - - fontprops = font_manager.FontProperties(size=size) - tvhl = self._helper.get_ticklabel_transform(self.major_tick_pad, - fontprops=fontprops, - renderer=None, - trans=transform) - trans, vert, horiz, label_a = tvhl - - color = rcParams['xtick.color'] - self.major_ticklabels = TickLabels(size, color=color) - self.minor_ticklabels = TickLabels(size, color=color) - - #self.major_ticklabels = TickLabels(size, axis=self.axis) - #self.minor_ticklabels = TickLabels(size, axis=self.axis) - - - self.major_ticklabels.set(figure = self.axes.figure, - rotation = label_a, - transform=trans, - va=vert, - ha=horiz, - fontproperties=fontprops) - - self.minor_ticklabels.set(figure = self.axes.figure, - rotation = label_a, - transform=trans, - va=vert, - ha=horiz, - fontproperties=fontprops) - - - def _draw_ticks(self, renderer): - #majortick_iter, minortick_iter): - #major_locs, major_angles, - #minor_locs, minor_angles): - - majortick_iter, minortick_iter = self._helper.get_tick_iterators() - - tick_loc_angles = [] - tick_loc_labels = [] - for tick_loc, tick_angle, tick_label in majortick_iter: - tick_loc_angles.append((tick_loc, tick_angle)) - tick_loc_labels.append((tick_loc, tick_label)) - - - transform=self._helper.get_tick_transform()+self.offset_transform - fontprops = font_manager.FontProperties(size=12) - tvhl = self._helper.get_ticklabel_transform(self.major_tick_pad, - fontprops=fontprops, - renderer=renderer, - trans=transform) - trans, va, ha, a = tvhl - self.major_ticklabels.set(transform=trans, - va=va, ha=ha, rotation=a) - - - self.major_ticks.update_locs_angles(tick_loc_angles, renderer) - self.major_ticklabels.update_locs_labels(tick_loc_labels, renderer) - - self.major_ticks.draw(renderer) - self.major_ticklabels.draw(renderer) - - tick_loc_angles = [] - tick_loc_labels = [] - for tick_loc, tick_angle, tick_label in minortick_iter: - tick_loc_angles.append((tick_loc, tick_angle)) - tick_loc_labels.append((tick_loc, tick_label)) - - self.minor_ticks.update_locs_angles(tick_loc_angles, renderer) - self.minor_ticklabels.update_locs_labels(tick_loc_labels, renderer) - - self.minor_ticks.draw(renderer) - self.minor_ticklabels.draw(renderer) - - return self.major_ticklabels.get_window_extents(renderer) - - def _init_label(self): - # x in axes coords, y in display coords (to be updated at draw - # time by _update_label_positions) - fontprops = font_manager.FontProperties(size=rcParams['axes.labelsize']) - textprops = dict(fontproperties = fontprops, - color = rcParams['axes.labelcolor'], - ) - - self.label = AxisLabel(0, 0, "", - fontproperties=fontprops, - color = rcParams['axes.labelcolor'], - ) - self.label.set_figure(self.axes.figure) - - #self._set_artist_props(label) - - def _draw_label(self, renderer, bboxes): - - if not self.label.get_visible(): - return - - fontprops = font_manager.FontProperties(size=rcParams['axes.labelsize']) - pad_points = self.LABELPAD + self.major_tick_pad - xy, tr = self._helper.get_label_pos() - if xy is None: return - - x, y = xy - tr2, va, ha, a = self._helper.get_label_transform(pad_points, fontprops, - renderer, - bboxes=bboxes, - trans=tr+self.offset_transform) - - self.label.set(x=x, y=y, - transform=tr2, - va=va, ha=ha, rotation=a) - -# if self.label.get_text() == "__from_axes__": -# label_text = self.axis.get_label().get_text() -# self.label.set_text(label_text) -# self.label.draw(renderer) -# self.label.set_text("__from_axes__") -# else: - - self.label.draw(renderer) - - - def set_label(self, s): - self.label.set_text(s) - - def draw(self, renderer): - 'Draw the axis lines, tick lines and labels' + if self._grid_helper is not None: + self._grid_helper.update_lim(self.axes) + #self.set_transform(self._grid_helper.get_gridlines_transform()) + gl = self._grid_helper.get_gridlines() + if gl: + self.set_segments([np.transpose(l) for l in gl]) + else: + self.set_segments([]) + super(GridlinesCollection, self).draw(renderer) - if not self.get_visible(): return - renderer.open_group(__name__) +class AxisGridLineBase(martist.Artist): + def __init__(self, *kl, **kw): + super(AxisGridLineBase, self).__init__(*kl, **kw) - dpi_cor = renderer.points_to_pixels(1.) - self.dpi_transform.clear().scale(dpi_cor, dpi_cor) +class AxisArtist(AxisGridLineBase): + """ + an artist which draws axis (a line along which the n-th axes coord + is constant) line, ticks, ticklabels, and axis label. - self._draw_line(renderer) - bboxes = self._draw_ticks(renderer) + It requires an AxisArtistHelper instance. + """ - #self._draw_offsetText(renderer) - self._draw_label(renderer, bboxes) - - renderer.close_group(__name__) - - def get_ticklabel_extents(self, renderer): - pass - - def toggle(self, all=None, ticks=None, ticklabels=None, label=None): - if all: - _ticks, _ticklabels, _label = True, True, True - elif all is not None: - _ticks, _ticklabels, _label = False, False, False - else: - _ticks, _ticklabels, _label = None, None, None - - if ticks is not None: - _ticks = ticks - if ticklabels is not None: - _ticklabels = ticklabels - if label is not None: - _label = label - - if _ticks is not None: - self.major_ticks.set_visible(_ticks) - self.minor_ticks.set_visible(_ticks) - if _ticklabels is not None: - self.major_ticklabels.set_visible(_ticklabels) - self.minor_ticklabels.set_visible(_ticklabels) - if _label is not None: - self.label.set_visible(_label) - - -class AxisLine(AxisGridLineBase): - """ a line along which the n-th axes coord is constant.""" - LABELPAD = 5 ZORDER=2.5 @@ -920,26 +907,23 @@ minor_tick_size=None, minor_tick_pad=None, **kw): - + """ + axes is also used to follow the axis attribute (tick color, etc). + """ AxisGridLineBase.__init__(self, **kw) self.axes = axes - self._helper = helper + self._axis_artist_helper = helper - #if offset_transform is None: - # self.offset_transform = IdentityTransform() - #else: - # self.offset_transform = offset_transform - if offset is None: offset = (0, 0) self.dpi_transform = Affine2D() self.offset_transform = ScaledTranslation(offset[0], offset[1], self.dpi_transform) - self.set_transform(axes.transAxes + \ - self.offset_transform) + #self.set_transform(axes.transAxes + \ + # self.offset_transform) self._label_visible = True self._majortick_visible = True @@ -948,7 +932,7 @@ self._minorticklabel_visible = True - if self._helper.label_direction in ["left", "right"]: + if self._axis_artist_helper.label_direction in ["left", "right"]: axis_name = "ytick" self.axis = axes.yaxis else: @@ -967,29 +951,35 @@ self._init_line() self._init_ticks() - self._init_offsetText(self._helper.label_direction) + self._init_offsetText(self._axis_artist_helper.label_direction) self._init_label() self.set_zorder(self.ZORDER) + def get_transform(self): + return self.axes.transAxes + self.offset_transform + + def get_helper(self): + return self._axis_artist_helper + + def _init_line(self): - tran = self._helper.get_line_transform() + self.offset_transform - self.line = BezierPath(self._helper.get_line(), + tran = self._axis_artist_helper.get_line_transform(self.axes) \ + + self.offset_transform + self.line = BezierPath(self._axis_artist_helper.get_line(self.axes), color=rcParams['axes.edgecolor'], linewidth=rcParams['axes.linewidth'], transform=tran) - def get_helper(self): - return self._helper - def _draw_line(self, renderer): - self.line.set_path(self._helper.get_line()) + self.line.set_path(self._axis_artist_helper.get_line(self.axes)) self.line.draw(renderer) def _init_ticks(self): - transform=self._helper.get_tick_transform()+self.offset_transform + transform=self._axis_artist_helper.get_tick_transform(self.axes) \ + + self.offset_transform self.major_ticks = Ticks(self.major_tick_size, axis=self.axis, @@ -1002,16 +992,17 @@ size = rcParams['xtick.labelsize'] fontprops = font_manager.FontProperties(size=size) - tvhl = self._helper.get_ticklabel_transform(self.major_tick_pad, - fontprops=fontprops, - renderer=None, - trans=transform) + #tvhl = self._axis_artist_helper.get_ticklabel_transform( + tvhl = self._axis_artist_helper.get_ticklabel_offset_transform( \ + self.axes, + self.major_tick_pad, + fontprops=fontprops, + renderer=None, + ) + #trans=transform) trans, vert, horiz, label_a = tvhl + trans = transform + trans - #color = rcParams['xtick.color'] - #self.major_ticklabels = TickLabels(size, color=color) - #self.minor_ticklabels = TickLabels(size, color=color) - self.major_ticklabels = TickLabels(size, axis=self.axis) self.minor_ticklabels = TickLabels(size, axis=self.axis) @@ -1040,7 +1031,7 @@ x,y,va,ha = self._offsetText_pos[direction] - #d = self._helper.label_direction + #d = self._axis_artist_helper.label_direction #fp = font_manager.FontProperties(size=rcParams['xtick.labelsize']) #fp = font_manager.FontProperties(size=self.major_ticklabels.get_size()) self.offsetText = mtext.Annotation("", @@ -1056,7 +1047,7 @@ def _update_offsetText(self): - self.offsetText.set_text( self._helper.axis.major.formatter.get_offset() ) + self.offsetText.set_text( self.axis.major.formatter.get_offset() ) self.offsetText.set_size(self.major_ticklabels.get_size()) offset = self.major_tick_pad + self.major_ticklabels.get_size() + 2. self.offsetText.xytext= (0, offset) @@ -1072,7 +1063,8 @@ #major_locs, major_angles, #minor_locs, minor_angles): - majortick_iter, minortick_iter = self._helper.get_tick_iterators() + majortick_iter, minortick_iter = \ + self._axis_artist_helper.get_tick_iterators(self.axes) tick_loc_angles = [] tick_loc_labels = [] @@ -1081,13 +1073,19 @@ tick_loc_labels.append((tick_loc, tick_label)) - transform=self._helper.get_tick_transform()+self.offset_transform + transform=self._axis_artist_helper.get_tick_transform(self.axes) \ + + self.offset_transform fontprops = font_manager.FontProperties(size=12) - tvhl = self._helper.get_ticklabel_transform(self.major_tick_pad, - fontprops=fontprops, - renderer=renderer, - trans=transform) + tvhl = self._axis_artist_helper.get_ticklabel_offset_transform( \ + self.axes, + self.major_tick_pad, + fontprops=fontprops, + renderer=renderer, + ) + #trans=transform) trans, va, ha, a = tvhl + trans = transform + trans + self.major_ticklabels.set(transform=trans, va=va, ha=ha, rotation=a) @@ -1140,14 +1138,18 @@ fontprops = font_manager.FontProperties(size=rcParams['axes.labelsize']) pad_points = self.LABELPAD + self.major_tick_pad - xy, tr = self._helper.get_label_pos() + xy, tr = self._axis_artist_helper.get_label_pos(self.axes) if xy is None: return x, y = xy - tr2, va, ha, a = self._helper.get_label_transform(pad_points, fontprops, - renderer, - bboxes=bboxes, - trans=tr+self.offset_transform) + tr2, va, ha, a = self._axis_artist_helper.get_label_offset_transform(\ + self.axes, + pad_points, fontprops, + renderer, + bboxes=bboxes, + ) + #trans=tr+self.offset_transform) + tr2 = (tr+self.offset_transform) + tr2 self.label.set(x=x, y=y, transform=tr2, @@ -1174,6 +1... [truncated message content] |
From: <md...@us...> - 2009-06-03 12:50:19
|
Revision: 7177 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7177&view=rev Author: mdboom Date: 2009-06-03 12:16:21 +0000 (Wed, 03 Jun 2009) Log Message: ----------- Merged revisions 7176 via svnmerge from https://matplotlib.svn.sf.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r7176 | mdboom | 2009-06-03 08:15:06 -0400 (Wed, 03 Jun 2009) | 1 line Bugfix in FltkAgg backend, thanks to Daniel ........ Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7115 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7176 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176 Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176 Modified: trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py 2009-06-03 12:15:06 UTC (rev 7176) +++ trunk/matplotlib/lib/matplotlib/backends/backend_fltkagg.py 2009-06-03 12:16:21 UTC (rev 7177) @@ -115,6 +115,7 @@ window = Fltk.Fl_Double_Window(10,10,30,30) canvas = FigureCanvasFltkAgg(figure) window.end() + #Fltk.Fl.visual(Fltk.FL_DOUBLE) window.show() window.make_current() figManager = FigureManagerFltkAgg(canvas, num, window) @@ -157,7 +158,7 @@ def handle(self, event): x=Fltk.Fl.event_x() y=Fltk.Fl.event_y() - yf=self._source.figure.bbox.height() - y + yf=self._source.figure.bbox.height - y if event == Fltk.FL_FOCUS or event == Fltk.FL_UNFOCUS: return 1 elif event == Fltk.FL_KEYDOWN: @@ -230,7 +231,7 @@ def resize(self,size): w, h = size # compute desired figure size in inches - dpival = self.figure.dpi.get() + dpival = self.figure.dpi winch = w/dpival hinch = h/dpival self.figure.set_size_inches(winch,hinch) @@ -405,7 +406,7 @@ """ def __init__(self, canvas, figman): - #xmin, xmax = canvas.figure.bbox.intervalx().get_bounds() + #xmin, xmax = canvas.figure.bbox.intervalx #height, width = 50, xmax-xmin self.canvas = canvas self.figman = figman Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 + /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 + /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 + /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2009-06-06 11:36:12
|
Revision: 7184 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7184&view=rev Author: jdh2358 Date: 2009-06-06 11:36:10 +0000 (Sat, 06 Jun 2009) Log Message: ----------- do not apply alpha to rgba color conversion if input is already rgba Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/collections.py trunk/matplotlib/lib/matplotlib/colors.py trunk/matplotlib/src/_backend_agg.cpp Modified: trunk/matplotlib/lib/matplotlib/collections.py =================================================================== --- trunk/matplotlib/lib/matplotlib/collections.py 2009-06-05 23:45:53 UTC (rev 7183) +++ trunk/matplotlib/lib/matplotlib/collections.py 2009-06-06 11:36:10 UTC (rev 7184) @@ -91,6 +91,7 @@ self.set_antialiased(antialiaseds) self.set_urls(urls) + self._uniform_offsets = None self._offsets = np.array([], np.float_) if offsets is not None: @@ -106,6 +107,7 @@ self._pickradius = pickradius self.update(kwargs) + def _get_value(self, val): try: return (float(val), ) except TypeError: Modified: trunk/matplotlib/lib/matplotlib/colors.py =================================================================== --- trunk/matplotlib/lib/matplotlib/colors.py 2009-06-05 23:45:53 UTC (rev 7183) +++ trunk/matplotlib/lib/matplotlib/colors.py 2009-06-06 11:36:10 UTC (rev 7184) @@ -373,7 +373,11 @@ if isinstance(c, np.ndarray): if c.ndim != 2 and c.dtype.kind not in 'SU': raise ValueError("Color array must be two-dimensional") - + if len(c.shape)==2 and c.shape[-1]==4: + # looks like rgba already, nothing to be done; do + # we want to apply alpha here if + # (c[:,3]==1).all() ? + return c result = np.zeros((len(c), 4)) for i, cc in enumerate(c): result[i] = self.to_rgba(cc, alpha) # change in place @@ -976,7 +980,7 @@ def __init__(self,azdeg=315,altdeg=45,\ hsv_min_val=0,hsv_max_val=1,hsv_min_sat=1,hsv_max_sat=0): """ - Specify the azimuth (measured clockwise from south) and altitude + Specify the azimuth (measured clockwise from south) and altitude (measured up from the plane of the surface) of the light source in degrees. @@ -987,7 +991,7 @@ (hsv_max_sat hsv_max_val) in regions that are illuminated. The default extremes are chose so that completely shaded points are nearly black (s = 1, v = 0) and completely illuminated points - are nearly white (s = 0, v = 1). + are nearly white (s = 0, v = 1). """ self.azdeg = azdeg self.altdeg = altdeg @@ -999,10 +1003,10 @@ def shade(self,data,cmap): """ Take the input data array, convert to HSV values in the - given colormap, then adjust those color values + given colormap, then adjust those color values to given the impression of a shaded relief map with a specified light source. - RGBA values are returned, which can then be used to + RGBA values are returned, which can then be used to plot the shaded image with imshow. """ # imagine an artificial sun placed at infinity in Modified: trunk/matplotlib/src/_backend_agg.cpp =================================================================== --- trunk/matplotlib/src/_backend_agg.cpp 2009-06-05 23:45:53 UTC (rev 7183) +++ trunk/matplotlib/src/_backend_agg.cpp 2009-06-06 11:36:10 UTC (rev 7184) @@ -465,7 +465,7 @@ if (region->data==NULL) throw Py::ValueError("Cannot restore_region from NULL data"); - agg::rect_i rect(xx1-region->rect.x1, (yy1-region->rect.y1), + agg::rect_i rect(xx1-region->rect.x1, (yy1-region->rect.y1), xx2-region->rect.x1, (yy2-region->rect.y1)); @@ -1187,6 +1187,7 @@ *(double*)PyArray_GETPTR2(edgecolors, ei, 1), *(double*)PyArray_GETPTR2(edgecolors, ei, 2), *(double*)PyArray_GETPTR2(edgecolors, ei, 3)); + if (Nlinewidths) { gc.linewidth = double(Py::Float(linewidths[i % Nlinewidths])) * dpi/72.0; } else { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2009-06-07 15:48:37
|
Revision: 7196 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7196&view=rev Author: jdh2358 Date: 2009-06-07 15:48:05 +0000 (Sun, 07 Jun 2009) Log Message: ----------- modifications to examples/docs to get them to build for the website Modified Paths: -------------- trunk/matplotlib/doc/pyplots/matplotlibrc trunk/matplotlib/doc/pyplots/tex_demo.png trunk/matplotlib/examples/pylab_examples/finance_work2.py trunk/matplotlib/lib/matplotlib/axes.py Modified: trunk/matplotlib/doc/pyplots/matplotlibrc =================================================================== --- trunk/matplotlib/doc/pyplots/matplotlibrc 2009-06-07 14:15:28 UTC (rev 7195) +++ trunk/matplotlib/doc/pyplots/matplotlibrc 2009-06-07 15:48:05 UTC (rev 7196) @@ -27,7 +27,6 @@ # the default backend; one of GTK GTKAgg GTKCairo FltkAgg QtAgg TkAgg # WX WXAgg Agg Cairo GD GDK Paint PS PDF SVG Template backend : Agg -numerix : numpy # numpy, Numeric or numarray #maskedarray : False # True to use external maskedarray module # instead of numpy.ma; this is a temporary # setting for testing maskedarray. Modified: trunk/matplotlib/doc/pyplots/tex_demo.png =================================================================== (Binary files differ) Modified: trunk/matplotlib/examples/pylab_examples/finance_work2.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/finance_work2.py 2009-06-07 14:15:28 UTC (rev 7195) +++ trunk/matplotlib/examples/pylab_examples/finance_work2.py 2009-06-07 15:48:05 UTC (rev 7196) @@ -1,10 +1,5 @@ -## Plot the stock price with some technical indicators -## Example usage:: -## python stocks2.py --ticker=GE --startdate=2003 -## -import datetime, os, urllib, optparse +import datetime import numpy as np -import dateutil.parser import matplotlib.colors as colors import matplotlib.finance as finance import matplotlib.dates as mdates @@ -13,34 +8,12 @@ import matplotlib.pyplot as plt import matplotlib.font_manager as font_manager -today = datetime.date.today() -optionparser = optparse.OptionParser() +startdate = datetime.date(2006,1,1) +today = enddate = datetime.date.today() +ticker = 'SPY' -optionparser.add_option('-t', '--ticker', - dest='ticker', - help='a stock market ticker', - default='SPY') -optionparser.add_option('-s', '--startdate', - dest='startdate', - help='the start date', - default=(today-datetime.timedelta(days=365*2)).strftime('%Y-%m-%d')) - -optionparser.add_option('-e', '--enddate', - dest='enddate', - help='the end date', - default=today.strftime('%Y-%m-%d')) - - -(commandoptions, commandargs) = optionparser.parse_args() - - -startdate = dateutil.parser.parse(commandoptions.startdate) -enddate = dateutil.parser.parse(commandoptions.enddate) -ticker = commandoptions.ticker - - fh = finance.fetch_historical_yahoo(ticker, startdate, enddate) # a numpy record array with fields: date, open, high, low, close, volume, adj_close) Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2009-06-07 14:15:28 UTC (rev 7195) +++ trunk/matplotlib/lib/matplotlib/axes.py 2009-06-07 15:48:05 UTC (rev 7196) @@ -6019,7 +6019,7 @@ %(PolyCollection)s - .. plot:: mpl_examples/pylab_examples/fill_between_demo.py.py + .. plot:: mpl_examples/pylab_examples/fill_between_demo.py .. seealso:: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <he...@us...> - 2009-06-07 23:23:51
|
Revision: 7198 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7198&view=rev Author: heeres Date: 2009-06-07 23:23:41 +0000 (Sun, 07 Jun 2009) Log Message: ----------- mplot3d: update axes code, add support for '3D' text. Split and add examples and begin documentation. Modified Paths: -------------- trunk/matplotlib/doc/devel/documenting_mpl.rst trunk/matplotlib/doc/users/toolkits.rst trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/axis3d.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/proj3d.py Added Paths: ----------- trunk/matplotlib/examples/mplot3d/2dcollections3d_demo.py trunk/matplotlib/examples/mplot3d/bars3d_demo.py trunk/matplotlib/examples/mplot3d/contour3d_demo.py trunk/matplotlib/examples/mplot3d/contourf3d_demo.py trunk/matplotlib/examples/mplot3d/lines3d_demo.py trunk/matplotlib/examples/mplot3d/polys3d_demo.py trunk/matplotlib/examples/mplot3d/scatter3d_demo.py trunk/matplotlib/examples/mplot3d/surface3d_demo.py trunk/matplotlib/examples/mplot3d/text3d_demo.py trunk/matplotlib/examples/mplot3d/wire3d_demo.py Removed Paths: ------------- trunk/matplotlib/examples/mplot3d/contour.py trunk/matplotlib/examples/mplot3d/contourf.py trunk/matplotlib/examples/mplot3d/demo.py trunk/matplotlib/examples/mplot3d/polys.py trunk/matplotlib/examples/mplot3d/scatter.py trunk/matplotlib/examples/mplot3d/surface.py trunk/matplotlib/examples/mplot3d/wire.py Modified: trunk/matplotlib/doc/devel/documenting_mpl.rst =================================================================== --- trunk/matplotlib/doc/devel/documenting_mpl.rst 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/doc/devel/documenting_mpl.rst 2009-06-07 23:23:41 UTC (rev 7198) @@ -9,9 +9,11 @@ The documentation for matplotlib is generated from ReStructured Text using the Sphinx_ documentation generation tool. Sphinx-0.5 or later -is required. Most developers work from the sphinx subversion repository because it is a rapidly evolving project:: +is required. You might still run into problems, so most developers +work from the sphinx source repository (Mercurial based) because it +is a rapidly evolving project:: - svn co http://svn.python.org/projects/doctools/trunk sphinx + hg clone http://bitbucket.org/birkenfeld/sphinx/ cd sphinx python setup.py install Modified: trunk/matplotlib/doc/users/toolkits.rst =================================================================== --- trunk/matplotlib/doc/users/toolkits.rst 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/doc/users/toolkits.rst 2009-06-07 23:23:41 UTC (rev 7198) @@ -54,6 +54,7 @@ there, but ships with matplotlib and thus may be a lighter weight solution for some use cases. +See :ref:`toolkit_mplot3d-index` for more documentation and examples. .. _toolkit_axes_grid: Added: trunk/matplotlib/examples/mplot3d/2dcollections3d_demo.py =================================================================== --- trunk/matplotlib/examples/mplot3d/2dcollections3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/2dcollections3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,24 @@ +from mpl_toolkits.mplot3d import Axes3D +import numpy as np +import pylab + +fig = pylab.figure() +ax = Axes3D(fig) + +x = np.linspace(0, 1, 100) +y = np.sin(x * 2 * np.pi) / 2 + 0.5 +ax.plot(x, y, zs=0, zdir='z', label='zs=0, zdir=z') + +colors = ('r', 'g', 'b', 'k') +for c in colors: + x = np.random.sample(20) + y = np.random.sample(20) + ax.scatter(x, y, 0, zdir='y', c=c) + +ax.legend() +ax.set_xlim3d(0, 1) +ax.set_ylim3d(0, 1) +ax.set_zlim3d(0, 1) + +pylab.show() + Added: trunk/matplotlib/examples/mplot3d/bars3d_demo.py =================================================================== --- trunk/matplotlib/examples/mplot3d/bars3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/bars3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,20 @@ +from mpl_toolkits.mplot3d import Axes3D +from matplotlib.collections import PolyCollection +from matplotlib.colors import colorConverter +import pylab +import random +import numpy as np + +fig = pylab.figure() +ax = Axes3D(fig) +for c, z in zip(['r', 'g', 'b', 'y'], [30, 20, 10, 0]): + xs = np.arange(20) + ys = [random.random() for x in xs] + ax.bar(xs, ys, zs=z, zdir='y', color=c, alpha=0.8) + +ax.set_xlabel('X') +ax.set_ylabel('Y') +ax.set_zlabel('Z') + +pylab.show() + Deleted: trunk/matplotlib/examples/mplot3d/contour.py =================================================================== --- trunk/matplotlib/examples/mplot3d/contour.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/examples/mplot3d/contour.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -1,12 +0,0 @@ -from mpl_toolkits.mplot3d import axes3d -import pylab -import random - -fig = pylab.figure() -ax = axes3d.Axes3D(fig) -X, Y, Z = axes3d.get_test_data(0.05) -cset = ax.contour3D(X, Y, Z) -ax.clabel(cset, fontsize=9, inline=1) - -pylab.show() - Copied: trunk/matplotlib/examples/mplot3d/contour3d_demo.py (from rev 7162, trunk/matplotlib/examples/mplot3d/contour.py) =================================================================== --- trunk/matplotlib/examples/mplot3d/contour3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/contour3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,12 @@ +from mpl_toolkits.mplot3d import axes3d +import pylab +import random + +fig = pylab.figure() +ax = axes3d.Axes3D(fig) +X, Y, Z = axes3d.get_test_data(0.05) +cset = ax.contour(X, Y, Z) +ax.clabel(cset, fontsize=9, inline=1) + +pylab.show() + Property changes on: trunk/matplotlib/examples/mplot3d/contour3d_demo.py ___________________________________________________________________ Added: svn:mergeinfo + /branches/v0_91_maint/examples/mplot3d/contour.py:5753-5771 /branches/v0_98_5_maint/examples/mplot3d/contour.py:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 Deleted: trunk/matplotlib/examples/mplot3d/contourf.py =================================================================== --- trunk/matplotlib/examples/mplot3d/contourf.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/examples/mplot3d/contourf.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -1,12 +0,0 @@ -from mpl_toolkits.mplot3d import axes3d -import pylab -import random - -fig = pylab.figure() -ax = axes3d.Axes3D(fig) -X, Y, Z = axes3d.get_test_data(0.05) -cset = ax.contourf3D(X, Y, Z) -ax.clabel(cset, fontsize=9, inline=1) - -pylab.show() - Copied: trunk/matplotlib/examples/mplot3d/contourf3d_demo.py (from rev 7162, trunk/matplotlib/examples/mplot3d/contourf.py) =================================================================== --- trunk/matplotlib/examples/mplot3d/contourf3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/contourf3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,12 @@ +from mpl_toolkits.mplot3d import axes3d +import pylab +import random + +fig = pylab.figure() +ax = axes3d.Axes3D(fig) +X, Y, Z = axes3d.get_test_data(0.05) +cset = ax.contourf(X, Y, Z) +ax.clabel(cset, fontsize=9, inline=1) + +pylab.show() + Property changes on: trunk/matplotlib/examples/mplot3d/contourf3d_demo.py ___________________________________________________________________ Added: svn:mergeinfo + /branches/v0_91_maint/examples/mplot3d/contourf.py:5753-5771 /branches/v0_98_5_maint/examples/mplot3d/contourf.py:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 Deleted: trunk/matplotlib/examples/mplot3d/demo.py =================================================================== --- trunk/matplotlib/examples/mplot3d/demo.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/examples/mplot3d/demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -1,138 +0,0 @@ -import random -import numpy as np -import matplotlib.pyplot as plt -import mpl_toolkits.mplot3d.axes3d as axes3d -from matplotlib.colors import Normalize, colorConverter - -def test_scatter(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - n = 100 - for c,zl,zh in [('r',-50,-25),('b',-30,-5)]: - xs,ys,zs = zip(* - [(random.randrange(23,32), - random.randrange(100), - random.randrange(zl,zh) - ) for i in range(n)]) - ax.scatter3D(xs,ys,zs, c=c) - - ax.set_xlabel('------------ X Label --------------------') - ax.set_ylabel('------------ Y Label --------------------') - ax.set_zlabel('------------ Z Label --------------------') - -def test_wire(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - X,Y,Z = axes3d.get_test_data(0.05) - ax.plot_wireframe(X,Y,Z, rstride=10,cstride=10) - ax.set_xlabel('X') - ax.set_ylabel('Y') - ax.set_zlabel('Z') - -def test_surface(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - X,Y,Z = axes3d.get_test_data(0.05) - ax.plot_surface(X,Y,Z, rstride=10,cstride=10) - ax.set_xlabel('X') - ax.set_ylabel('Y') - ax.set_zlabel('Z') - -def test_contour(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - X,Y,Z = axes3d.get_test_data(0.05) - cset = ax.contour3D(X,Y,Z) - ax.clabel(cset, fontsize=9, inline=1) - ax.set_xlabel('X') - ax.set_ylabel('Y') - ax.set_zlabel('Z') - -def test_contourf(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - X,Y,Z = axes3d.get_test_data(0.05) - cset = ax.contourf3D(X,Y,Z) - ax.clabel(cset, fontsize=9, inline=1) - ax.set_xlabel('X') - ax.set_ylabel('Y') - ax.set_zlabel('Z') - -def test_plot(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - xs = np.arange(0,4*np.pi+0.1,0.1) - ys = np.sin(xs) - ax.plot(xs,ys, label='zl') - ax.plot(xs,ys+max(xs),label='zh') - ax.plot(xs,ys,dir='x', label='xl') - ax.plot(xs,ys,dir='x', z=max(xs),label='xh') - ax.plot(xs,ys,dir='y', label='yl') - ax.plot(xs,ys,dir='y', z=max(xs), label='yh') - ax.set_xlabel('X') - ax.set_ylabel('Y') - ax.set_zlabel('Z') - ax.legend() - -def test_polys(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - cc = lambda arg: colorConverter.to_rgba(arg, alpha=0.6) - - xs = np.arange(0,10,0.4) - verts = [] - zs = [0.0,1.0,2.0,3.0] - for z in zs: - ys = [random.random() for x in xs] - ys[0],ys[-1] = 0,0 - verts.append(zip(xs,ys)) - - from matplotlib.collections import PolyCollection - poly = PolyCollection(verts, facecolors = [cc('r'),cc('g'),cc('b'), - cc('y')]) - poly.set_alpha(0.7) - ax.add_collection(poly,zs=zs,dir='y') - - ax.set_xlim(0,10) - ax.set_ylim(-1,4) - ax.set_zlim(0,1) - -def test_scatter2D(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - xs = [random.random() for i in range(20)] - ys = [random.random() for x in xs] - ax.scatter(xs, ys) - ax.scatter(xs, ys, dir='y', c='r') - ax.scatter(xs, ys, dir='x', c='g') - -def test_bar2D(): - f = plt.figure() - ax = axes3d.Axes3D(f) - - for c,z in zip(['r','g','b', 'y'],[30,20,10,0]): - xs = np.arange(20) - ys = [random.random() for x in xs] - ax.bar(xs, ys, z=z, dir='y', color=c, alpha=0.8) - -if __name__ == "__main__": - - test_scatter() - test_wire() - test_surface() - test_contour() - test_contourf() - test_plot() - test_polys() - test_scatter2D() - test_bar2D() - - plt.show() Added: trunk/matplotlib/examples/mplot3d/lines3d_demo.py =================================================================== --- trunk/matplotlib/examples/mplot3d/lines3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/lines3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,19 @@ +import matplotlib as mpl +from mpl_toolkits.mplot3d import Axes3D +import numpy as np +import pylab + +mpl.rcParams['legend.fontsize'] = 10 + +fig = pylab.figure() +ax = Axes3D(fig) +theta = np.linspace(-4 * np.pi, 4 * np.pi, 100) +z = np.linspace(-2, 2, 100) +r = z**2 + 1 +x = r * np.sin(theta) +y = r * np.cos(theta) +ax.plot(x, y, z, label='parametric curve') +ax.legend() + +pylab.show() + Deleted: trunk/matplotlib/examples/mplot3d/polys.py =================================================================== --- trunk/matplotlib/examples/mplot3d/polys.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/examples/mplot3d/polys.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -1,31 +0,0 @@ -from mpl_toolkits.mplot3d import Axes3D -from matplotlib.collections import PolyCollection -from matplotlib.colors import colorConverter -import pylab -import random -import numpy as np - -fig = pylab.figure() -ax = Axes3D(fig) - -cc = lambda arg: colorConverter.to_rgba(arg, alpha=0.6) - -xs = np.arange(0, 10, 0.4) -verts = [] -zs = [0.0, 1.0, 2.0, 3.0] -for z in zs: - ys = [random.random() for x in xs] - ys[0], ys[-1] = 0, 0 - verts.append(zip(xs, ys)) - -poly = PolyCollection(verts, facecolors = [cc('r'), cc('g'), cc('b'), - cc('y')]) -poly.set_alpha(0.7) -ax.add_collection(poly, zs=zs, dir='y') - -ax.set_xlim(0, 10) -ax.set_ylim(-1, 4) -ax.set_zlim(0, 1) - -pylab.show() - Copied: trunk/matplotlib/examples/mplot3d/polys3d_demo.py (from rev 7162, trunk/matplotlib/examples/mplot3d/polys.py) =================================================================== --- trunk/matplotlib/examples/mplot3d/polys3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/polys3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,31 @@ +from mpl_toolkits.mplot3d import Axes3D +from matplotlib.collections import PolyCollection +from matplotlib.colors import colorConverter +import pylab +import random +import numpy as np + +fig = pylab.figure() +ax = Axes3D(fig) + +cc = lambda arg: colorConverter.to_rgba(arg, alpha=0.6) + +xs = np.arange(0, 10, 0.4) +verts = [] +zs = [0.0, 1.0, 2.0, 3.0] +for z in zs: + ys = [random.random() for x in xs] + ys[0], ys[-1] = 0, 0 + verts.append(zip(xs, ys)) + +poly = PolyCollection(verts, facecolors = [cc('r'), cc('g'), cc('b'), + cc('y')]) +poly.set_alpha(0.7) +ax.add_collection3d(poly, zs=zs, zdir='y') + +ax.set_xlim3d(0, 10) +ax.set_ylim3d(-1, 4) +ax.set_zlim3d(0, 1) + +pylab.show() + Property changes on: trunk/matplotlib/examples/mplot3d/polys3d_demo.py ___________________________________________________________________ Added: svn:mergeinfo + /branches/v0_91_maint/examples/mplot3d/polys.py:5753-5771 /branches/v0_98_5_maint/examples/mplot3d/polys.py:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 Deleted: trunk/matplotlib/examples/mplot3d/scatter.py =================================================================== --- trunk/matplotlib/examples/mplot3d/scatter.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/examples/mplot3d/scatter.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -1,21 +0,0 @@ -from mpl_toolkits.mplot3d import Axes3D -import pylab -import random - -fig = pylab.figure() -ax = Axes3D(fig) -n = 100 -for c, zl, zh in [('r', -50, -25), ('b', -30, -5)]: - xs, ys, zs = zip(* - [(random.randrange(23, 32), - random.randrange(100), - random.randrange(zl, zh) - ) for i in range(n)]) - ax.scatter3D(xs, ys, zs, c=c) - -ax.set_xlabel('X Label') -ax.set_ylabel('Y Label') -ax.set_zlabel('Z Label') - -pylab.show() - Copied: trunk/matplotlib/examples/mplot3d/scatter3d_demo.py (from rev 7162, trunk/matplotlib/examples/mplot3d/scatter.py) =================================================================== --- trunk/matplotlib/examples/mplot3d/scatter3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/scatter3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,21 @@ +from mpl_toolkits.mplot3d import Axes3D +import pylab +import random + +fig = pylab.figure() +ax = Axes3D(fig) +n = 100 +for c, zl, zh in [('r', -50, -25), ('b', -30, -5)]: + xs, ys, zs = zip(* + [(random.randrange(23, 32), + random.randrange(100), + random.randrange(zl, zh) + ) for i in range(n)]) + ax.scatter(xs, ys, zs, c=c) + +ax.set_xlabel('X Label') +ax.set_ylabel('Y Label') +ax.set_zlabel('Z Label') + +pylab.show() + Property changes on: trunk/matplotlib/examples/mplot3d/scatter3d_demo.py ___________________________________________________________________ Added: svn:mergeinfo + /branches/v0_91_maint/examples/mplot3d/scatter.py:5753-5771 /branches/v0_98_5_maint/examples/mplot3d/scatter.py:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 Deleted: trunk/matplotlib/examples/mplot3d/surface.py =================================================================== --- trunk/matplotlib/examples/mplot3d/surface.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/examples/mplot3d/surface.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -1,16 +0,0 @@ -from mpl_toolkits.mplot3d import Axes3D -import pylab -import random -import numpy as np - -fig = pylab.figure() -ax = Axes3D(fig) -X = np.arange(-5, 5, 0.5) -Y = np.arange(-5, 5, 0.5) -X, Y = np.meshgrid(X, Y) -R = np.sqrt(X**2 + Y**2) -Z = np.sin(R) -ax.plot_surface(X, Y, Z, rstride=1, cstride=1, color='forestgreen') - -pylab.show() - Copied: trunk/matplotlib/examples/mplot3d/surface3d_demo.py (from rev 7162, trunk/matplotlib/examples/mplot3d/surface.py) =================================================================== --- trunk/matplotlib/examples/mplot3d/surface3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/surface3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,16 @@ +from mpl_toolkits.mplot3d import Axes3D +import pylab +import random +import numpy as np + +fig = pylab.figure() +ax = Axes3D(fig) +X = np.arange(-5, 5, 0.5) +Y = np.arange(-5, 5, 0.5) +X, Y = np.meshgrid(X, Y) +R = np.sqrt(X**2 + Y**2) +Z = np.sin(R) +ax.plot_surface(X, Y, Z, rstride=1, cstride=1, color='forestgreen') + +pylab.show() + Property changes on: trunk/matplotlib/examples/mplot3d/surface3d_demo.py ___________________________________________________________________ Added: svn:mergeinfo + /branches/v0_91_maint/examples/mplot3d/surface.py:5753-5771 /branches/v0_98_5_maint/examples/mplot3d/surface.py:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 Added: trunk/matplotlib/examples/mplot3d/text3d_demo.py =================================================================== --- trunk/matplotlib/examples/mplot3d/text3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/text3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,26 @@ +from mpl_toolkits.mplot3d import Axes3D +import pylab +import random + +fig = pylab.figure() +ax = Axes3D(fig) + +zdirs = (None, 'x', 'y', 'z', (1, 1, 0), (1, 1, 1)) +xs = (2, 6, 4, 9, 7, 2) +ys = (6, 4, 8, 7, 2, 2) +zs = (4, 2, 5, 6, 1, 7) + +for zdir, x, y, z in zip(zdirs, xs, ys, zs): + label = '(%d, %d, %d), dir=%s' % (x, y, z, zdir) + ax.text(x, y, z, label, zdir) + +ax.set_xlim3d(0, 10) +ax.set_ylim3d(0, 10) +ax.set_zlim3d(0, 10) + +ax.set_xlabel('X axis') +ax.set_ylabel('Y axis') +ax.set_zlabel('Z axis') + +pylab.show() + Deleted: trunk/matplotlib/examples/mplot3d/wire.py =================================================================== --- trunk/matplotlib/examples/mplot3d/wire.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/examples/mplot3d/wire.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -1,12 +0,0 @@ -from mpl_toolkits.mplot3d import axes3d -import pylab -import random -import numpy as np - -fig = pylab.figure() -ax = axes3d.Axes3D(fig) -X, Y, Z = axes3d.get_test_data(0.05) -ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10) - -pylab.show() - Copied: trunk/matplotlib/examples/mplot3d/wire3d_demo.py (from rev 7162, trunk/matplotlib/examples/mplot3d/wire.py) =================================================================== --- trunk/matplotlib/examples/mplot3d/wire3d_demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/wire3d_demo.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -0,0 +1,12 @@ +from mpl_toolkits.mplot3d import axes3d +import pylab +import random +import numpy as np + +fig = pylab.figure() +ax = axes3d.Axes3D(fig) +X, Y, Z = axes3d.get_test_data(0.05) +ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10) + +pylab.show() + Property changes on: trunk/matplotlib/examples/mplot3d/wire3d_demo.py ___________________________________________________________________ Added: svn:mergeinfo + /branches/v0_91_maint/examples/mplot3d/wire.py:5753-5771 /branches/v0_98_5_maint/examples/mplot3d/wire.py:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080 Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -2,45 +2,89 @@ # art3d.py, original mplot3d version by John Porter # Parts rewritten by Reinier Heeres <re...@he...> -from matplotlib import lines, text, path as mpath +''' +Module containing 3D artist code and functions to convert 2D +artists into 3D versions which can be added to an Axes3D. +''' + +from matplotlib import lines, text as mtext, path as mpath, colors as mcolors from matplotlib.collections import Collection, LineCollection, \ PolyCollection, PatchCollection -from matplotlib.patches import Patch, Rectangle +from matplotlib.patches import Patch from matplotlib.colors import Normalize -from matplotlib import transforms +from matplotlib.cbook import iterable -import types import numpy as np +import math import proj3d -class Text3D(text.Text): +def norm_angle(a): + """Return angle between -180 and +180""" + a = (a + 360) % 360 + if a > 180: + a = a - 360 + return a - def __init__(self, x=0, y=0, z=0, text='', dir='z'): - text.Text.__init__(self, x, y, text) - self.set_3d_properties(z, dir) +def norm_text_angle(a): + """Return angle between -90 and +90""" + a = (a + 180) % 180 + if a > 90: + a = a - 180 + return a - def set_3d_properties(self, z=0, dir='z'): +def get_dir_vector(zdir): + if zdir == 'x': + return np.array((1, 0, 0)) + elif zdir == 'y': + return np.array((0, 1, 0)) + elif zdir == 'z': + return np.array((0, 0, 1)) + elif zdir == None: + return np.array((0, 0, 0)) + elif iterable(zdir) and len(zdir) == 3: + return zdir + else: + raise ValueError("'x', 'y', 'z', None or vector of length 3 expected") + +class Text3D(mtext.Text): + ''' + Text object with 3D position and (in the future) direction. + ''' + + def __init__(self, x=0, y=0, z=0, text='', zdir='z'): + mtext.Text.__init__(self, x, y, text) + self.set_3d_properties(z, zdir) + + def set_3d_properties(self, z=0, zdir='z'): x, y = self.get_position() - self._position3d = juggle_axes(x, y, z, dir) + self._position3d = np.array((x, y, z)) + self._dir_vec = get_dir_vector(zdir) def draw(self, renderer): - x, y, z = self._position3d - x, y, z = proj3d.proj_transform(x, y, z, renderer.M) - self.set_position(x, y) - text.Text.draw(self, renderer) + proj = proj3d.proj_trans_points([self._position3d, \ + self._position3d + self._dir_vec], renderer.M) + dx = proj[0][1] - proj[0][0] + dy = proj[1][1] - proj[1][0] + angle = math.degrees(math.atan2(dy, dx)) + self.set_position((proj[0][0], proj[1][0])) + self.set_rotation(norm_text_angle(angle)) + mtext.Text.draw(self, renderer) -def text_2d_to_3d(obj, z=0, dir='z'): +def text_2d_to_3d(obj, z=0, zdir='z'): """Convert a Text to a Text3D object.""" obj.__class__ = Text3D - obj.set_3d_properties(z, dir) + obj.set_3d_properties(z, zdir) class Line3D(lines.Line2D): + ''' + 3D line object. + ''' def __init__(self, xs, ys, zs, *args, **kwargs): lines.Line2D.__init__(self, [], [], *args, **kwargs) self._verts3d = xs, ys, zs - def set_3d_properties(self, zs=0, dir='z'): + def set_3d_properties(self, zs=0, zdir='z'): xs = self.get_xdata() ys = self.get_ydata() try: @@ -48,7 +92,7 @@ zs = [zs for x in xs] except: pass - self._verts3d = juggle_axes(xs, ys, zs, dir) + self._verts3d = juggle_axes(xs, ys, zs, zdir) def draw(self, renderer): xs3d, ys3d, zs3d = self._verts3d @@ -56,46 +100,58 @@ self.set_data(xs, ys) lines.Line2D.draw(self, renderer) -def line_2d_to_3d(line, z=0, dir='z'): +def line_2d_to_3d(line, zs=0, zdir='z'): + ''' + Convert a 2D line to 3D. + ''' line.__class__ = Line3D - line.set_3d_properties(z, dir) + line.set_3d_properties(zs, zdir) -def path_to_3d_segment(path, z=0, dir='z'): - '''Convert a path to a 3d segment.''' +def path_to_3d_segment(path, z=0, zdir='z'): + '''Convert a path to a 3D segment.''' seg = [] for (pathseg, code) in path.iter_segments(): seg.append(pathseg) - seg3d = [juggle_axes(x, y, z, dir) for (x, y) in seg] + seg3d = [juggle_axes(x, y, z, zdir) for (x, y) in seg] return seg3d -def paths_to_3d_segments(paths, zs=0, dir='z'): - '''Convert paths from a collection object to 3d segments.''' +def paths_to_3d_segments(paths, zs=0, zdir='z'): + '''Convert paths from a collection object to 3D segments.''' try: zs = float(zs) - zs = [zs for i in range(len(paths))] + zs = [zs] * len(paths) except: pass segments = [] for path, z in zip(paths, zs): - segments.append(path_to_3d_segment(path, z, dir)) + segments.append(path_to_3d_segment(path, z, zdir)) return segments class Line3DCollection(LineCollection): + ''' + A collection of 3D lines. + ''' def __init__(self, segments, *args, **kwargs): LineCollection.__init__(self, segments, *args, **kwargs) def set_segments(self, segments): + ''' + Set 3D segments + ''' self._segments3d = segments LineCollection.set_segments(self, []) def do_3d_projection(self, renderer): + ''' + Project the points according to renderer matrix. + ''' xyslist = [ proj3d.proj_trans_points(points, renderer.M) for points in self._segments3d] - segments_2d = [zip(xs,ys) for (xs,ys,zs) in xyslist] + segments_2d = [zip(xs, ys) for (xs, ys, zs) in xyslist] LineCollection.set_segments(self, segments_2d) minz = 1e9 @@ -108,22 +164,28 @@ self.do_3d_projection(renderer) LineCollection.draw(self, renderer) -def line_collection_2d_to_3d(col, z=0, dir='z'): +def line_collection_2d_to_3d(col, zs=0, zdir='z'): """Convert a LineCollection to a Line3DCollection object.""" - segments3d = paths_to_3d_segments(col.get_paths(), z, dir) + segments3d = paths_to_3d_segments(col.get_paths(), zs, zdir) col.__class__ = Line3DCollection col.set_segments(segments3d) class Patch3D(Patch): + ''' + 3D patch object. + ''' def __init__(self, *args, **kwargs): zs = kwargs.pop('zs', []) - dir = kwargs.pop('dir', 'z') + zdir = kwargs.pop('zdir', 'z') Patch.__init__(self, *args, **kwargs) - self.set_3d_properties(zs, dir) + self.set_3d_properties(zs, zdir) - def set_3d_properties(self, verts, z=0, dir='z'): - self._segment3d = [juggle_axes(x, y, z, dir) for (x, y) in verts] + def set_3d_properties(self, verts, zs=0, zdir='z'): + if not iterable(zs): + zs = [zs] * len(verts) + self._segment3d = [juggle_axes(x, y, z, zdir) \ + for ((x, y), z) in zip(verts, zs)] self._facecolor3d = Patch.get_facecolor(self) def get_path(self): @@ -135,7 +197,7 @@ def do_3d_projection(self, renderer): s = self._segment3d xs, ys, zs = zip(*s) - vxs,vys,vzs,vis = proj3d.proj_transform_clip(xs,ys,zs, renderer.M) + vxs, vys,vzs, vis = proj3d.proj_transform_clip(xs, ys, zs, renderer.M) self._path2d = mpath.Path(zip(vxs, vys)) # FIXME: coloring self._facecolor2d = self._facecolor3d @@ -144,26 +206,29 @@ def draw(self, renderer): Patch.draw(self, renderer) -def patch_2d_to_3d(patch, z=0, dir='z'): +def patch_2d_to_3d(patch, z=0, zdir='z'): """Convert a Patch to a Patch3D object.""" verts = patch.get_verts() patch.__class__ = Patch3D - patch.set_3d_properties(verts, z, dir) + patch.set_3d_properties(verts, z, zdir) class Patch3DCollection(PatchCollection): + ''' + A collection of 3D patches. + ''' def __init__(self, *args, **kwargs): PatchCollection.__init__(self, *args, **kwargs) - def set_3d_properties(self, zs, dir): + def set_3d_properties(self, zs, zdir): xs, ys = zip(*self.get_offsets()) - self._offsets3d = juggle_axes(xs, ys, zs, dir) + self._offsets3d = juggle_axes(xs, ys, zs, zdir) self._facecolor3d = self.get_facecolor() self._edgecolor3d = self.get_edgecolor() def do_3d_projection(self, renderer): - xs,ys,zs = self._offsets3d - vxs,vys,vzs,vis = proj3d.proj_transform_clip(xs,ys,zs, renderer.M) + xs, ys, zs = self._offsets3d + vxs, vys, vzs, vis = proj3d.proj_transform_clip(xs, ys, zs, renderer.M) #FIXME: mpl allows us no way to unset the collection alpha value self._alpha = None self.set_facecolors(zalpha(self._facecolor3d, vzs)) @@ -175,19 +240,22 @@ def draw(self, renderer): PatchCollection.draw(self, renderer) -def patch_collection_2d_to_3d(col, zs=0, dir='z'): +def patch_collection_2d_to_3d(col, zs=0, zdir='z'): """Convert a PatchCollection to a Patch3DCollection object.""" col.__class__ = Patch3DCollection - col.set_3d_properties(zs, dir) + col.set_3d_properties(zs, zdir) class Poly3DCollection(PolyCollection): + ''' + A collection of 3D polygons. + ''' def __init__(self, verts, *args, **kwargs): PolyCollection.__init__(self, verts, *args, **kwargs) self.set_3d_properties() def get_vector(self, segments3d): - """optimise points for projection""" + """Optimize points for projection""" si = 0 ei = 0 segis = [] @@ -195,11 +263,11 @@ for p in segments3d: points.extend(p) ei = si+len(p) - segis.append((si,ei)) + segis.append((si, ei)) si = ei - xs,ys,zs = zip(*points) + xs, ys, zs = zip(*points) ones = np.ones(len(xs)) - self._vec = np.array([xs,ys,zs,ones]) + self._vec = np.array([xs, ys, zs, ones]) self._segis = segis self._sort_zpos = min(zs) @@ -221,14 +289,14 @@ # if required sort by depth (furthest drawn first) if self._zsort: - z_segments_2d = [(min(zs),zip(xs,ys),c) for - (xs,ys,zs),c in zip(xyzlist,colors)] + z_segments_2d = [(min(zs), zip(xs, ys), c) for + (xs, ys, zs), c in zip(xyzlist, colors)] z_segments_2d.sort() z_segments_2d.reverse() else: raise ValueError, "whoops" - segments_2d = [s for z,s,c in z_segments_2d] - colors = [c for z,s,c in z_segments_2d] + segments_2d = [s for z, s, c in z_segments_2d] + colors = [c for z, s, c in z_segments_2d] PolyCollection.set_verts(self, segments_2d) self._facecolors2d = colors @@ -244,21 +312,23 @@ def draw(self, renderer): return Collection.draw(self, renderer) -def poly_collection_2d_to_3d(col, zs=None, dir='z'): +def poly_collection_2d_to_3d(col, zs=None, zdir='z'): """Convert a PolyCollection to a Poly3DCollection object.""" - segments_3d = paths_to_3d_segments(col.get_paths(), zs, dir) + segments_3d = paths_to_3d_segments(col.get_paths(), zs, zdir) col.__class__ = Poly3DCollection col.set_verts(segments_3d) col.set_3d_properties() -def juggle_axes(xs,ys,zs, dir): +def juggle_axes(xs, ys, zs, zdir): """ - Depending on the direction of the plot re-order the axis. - This is so that 2d plots can be plotted along any direction. + Reorder coordinates so that zdir """ - if dir == 'x': return zs,xs,ys - elif dir == 'y': return xs,zs,ys - else: return xs,ys,zs + if zdir == 'x': + return zs, xs, ys + elif zdir == 'y': + return xs, zs, ys + else: + return xs, ys, zs def iscolor(c): try: @@ -269,8 +339,8 @@ def get_colors(c, num): """Stretch the color argument to provide the required number num""" - if type(c)==type("string"): - c = colors.colorConverter.to_rgba(colors) + if type(c) == type("string"): + c = mcolors.colorConverter.to_rgba(c) if iscolor(c): return [c] * num @@ -285,9 +355,9 @@ def zalpha(colors, zs): """Modify the alphas of the color list according to depth""" - colors = get_colors(colors,len(zs)) - norm = Normalize(min(zs),max(zs)) - sats = 1 - norm(zs)*0.7 - colors = [(c[0],c[1],c[2],c[3]*s) for c,s in zip(colors,sats)] + colors = get_colors(colors, len(zs)) + norm = Normalize(min(zs), max(zs)) + sats = 1 - norm(zs) * 0.7 + colors = [(c[0], c[1], c[2], c[3] * s) for c, s in zip(colors, sats)] return colors Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2009-06-07 17:36:51 UTC (rev 7197) +++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2009-06-07 23:23:41 UTC (rev 7198) @@ -4,17 +4,14 @@ # Parts fixed by Reinier Heeres <re...@he...> """ -3D projection glued onto 2D Axes. - -Axes3D +Module containing Axes3D, an object which can plot 3D objects on a +2D matplotlib figure. """ -from matplotlib import pyplot as plt -import random - from matplotlib.axes import Axes from matplotlib import cbook from matplotlib.transforms import Bbox +from matplotlib import collections import numpy as np from matplotlib.colors import Normalize, colorConverter @@ -25,32 +22,23 @@ def sensible_format_data(self, value): """Used to generate more comprehensible numbers in status bar""" if abs(value) > 1e4 or abs(value)<1e-3: - s = '%1.4e'% value + s = '%1.4e' % value return self._formatSciNotation(s) else: return '%4.3f' % value def unit_bbox(): - box = Bbox(np.array([[0,0],[1,1]])) + box = Bbox(np.array([[0, 0], [1, 1]])) return box -class Axes3DI(Axes): - """Wrap an Axes object - - The x,y data coordinates, which are manipulated by set_xlim and - set_ylim are used as the target view coordinates by the 3D - transformations. These coordinates are mostly invisible to the - outside world. - - set_w_xlim, set_w_ylim and set_w_zlim manipulate the 3D world - coordinates which are scaled to represent the data and are stored - in the xy_dataLim, zz_datalim bboxes. - - The axes representing the x,y,z world dimensions are self.w_xaxis, - self.w_yaxis and self.w_zaxis. They can probably be controlled in - more or less the normal ways. +class Axes3D(Axes): """ - def __init__(self, fig, rect=[0.0, 0.0, 1.0, 1.0], *args, **kwargs): + 3D axes object. + """ + + def __init__(self, fig, rect=None, *args, **kwargs): + if rect is None: + rect = [0.0, 0.0, 1.0, 1.0] self.fig = fig self.cids = [] @@ -87,71 +75,47 @@ ydwl = (0.95/self.dist) ydw = (0.9/self.dist) - self.set_xlim(-xdwl,xdw) - self.set_ylim(-ydwl,ydw) + Axes.set_xlim(self, -xdwl, xdw) + Axes.set_ylim(self, -ydwl, ydw) - def really_set_xlim(self, vmin, vmax): - self.viewLim.intervalx().set_bounds(vmin, vmax) - - def really_set_ylim(self, vmin, vmax): - self.viewLim.intervaly().set_bounds(vmin, vmax) - - def vlim_argument(self, get_lim, *args): - if not args: - vmin,vmax = get_lim() - elif len(args)==2: - vmin,vmax = args - elif len(args)==1: - vmin,vmax = args[0] - return vmin,vmax - - def nset_xlim(self, *args): - raise - vmin,vmax = self.vlim_argument(self.get_xlim) - print 'xlim', vmin,vmax - - def nset_ylim(self, *args): - vmin,vmax = self.vlim_argument(self.get_ylim) - print 'ylim', vmin,vmax - def create_axes(self): - self.w_xaxis = axis3d.XAxis('x',self.xy_viewLim.intervalx, + self.w_xaxis = axis3d.XAxis('x', self.xy_viewLim.intervalx, self.xy_dataLim.intervalx, self) - self.w_yaxis = axis3d.YAxis('y',self.xy_viewLim.intervaly, + self.w_yaxis = axis3d.YAxis('y', self.xy_viewLim.intervaly, self.xy_dataLim.intervaly, self) - self.w_zaxis = axis3d.ZAxis('z',self.zz_viewLim.intervalx, + self.w_zaxis = axis3d.ZAxis('z', self.zz_viewLim.intervalx, self.zz_dataLim.intervalx, self) - def unit_cube(self,vals=None): - minx,maxx,miny,maxy,minz,maxz = vals or self.get_w_lims() - xs,ys,zs = ([minx,maxx,maxx,minx,minx,maxx,maxx,minx], - [miny,miny,maxy,maxy,miny,miny,maxy,maxy], - [minz,minz,minz,minz,maxz,maxz,maxz,maxz]) - return zip(xs,ys,zs) + def unit_cube(self, vals=None): + minx, maxx, miny, maxy, minz, maxz = vals or self.get_w_lims() + xs, ys, zs = ([minx, maxx, maxx, minx, minx, maxx, maxx, minx], + [miny, miny, maxy, maxy, miny, miny, maxy, maxy], + [minz, minz, minz, minz, maxz, maxz, maxz, maxz]) + return zip(xs, ys, zs) - def tunit_cube(self,vals=None,M=None): + def tunit_cube(self, vals=None, M=None): if M is None: M = self.M xyzs = self.unit_cube(vals) - tcube = proj3d.proj_points(xyzs,M) + tcube = proj3d.proj_points(xyzs, M) return tcube - def tunit_edges(self, vals=None,M=None): - tc = self.tunit_cube(vals,M) - edges = [(tc[0],tc[1]), - (tc[1],tc[2]), - (tc[2],tc[3]), - (tc[3],tc[0]), + def tunit_edges(self, vals=None, M=None): + tc = self.tunit_cube(vals, M) + edges = [(tc[0], tc[1]), + (tc[1], tc[2]), + (tc[2], tc[3]), + (tc[3], tc[0]), - (tc[0],tc[4]), - (tc[1],tc[5]), - (tc[2],tc[6]), - (tc[3],tc[7]), + (tc[0], tc[4]), + (tc[1], tc[5]), + (tc[2], tc[6]), + (tc[3], tc[7]), - (tc[4],tc[5]), - (tc[5],tc[6]), - (tc[6],tc[7]), - (tc[7],tc[4])] + (tc[4], tc[5]), + (tc[5], tc[6]), + (tc[6], tc[7]), + (tc[7], tc[4])] return edges def draw(self, renderer): @@ -189,22 +153,19 @@ def get_axis_position(self): vals = self.get_w_lims() - tc = self.tunit_cube(vals,self.M) - xhigh = tc[1][2]>tc[2][2] - yhigh = tc[3][2]>tc[2][2] - zhigh = tc[0][2]>tc[2][2] - return xhigh,yhigh,zhigh + tc = self.tunit_cube(vals, self.M) + xhigh = tc[1][2] > tc[2][2] + yhigh = tc[3][2] > tc[2][2] + zhigh = tc[0][2] > tc[2][2] + return xhigh, yhigh, zhigh def update_datalim(self, xys, **kwargs): pass - def update_datalim_numerix(self, x, y): - pass - - def auto_scale_xyz(self, X,Y,Z=None,had_data=None): - x,y,z = map(np.asarray, (X,Y,Z)) + def auto_scale_xyz(self, X, Y, Z=None, had_data=None): + x, y, z = map(np.asarray, (X, Y, Z)) try: - x,y = x.flatten(),y.flatten() + x, y = x.flatten(), y.flatten() if Z is not None: z = z.flatten() except AttributeError: @@ -225,55 +186,63 @@ # of data and decides how to scale the view portal to fit it. self.set_top_view() - if not self._ready: return + if not self._ready: + return - if not self.get_autoscale_on(): return + if not self.get_autoscale_on(): + return if scalex: - self.set_w_xlim(self.xy_dataLim.intervalx) + self.set_xlim3d(self.xy_dataLim.intervalx) if scaley: - self.set_w_ylim(self.xy_dataLim.intervaly) + self.set_ylim3d(self.xy_dataLim.intervaly) if scalez: - self.set_w_zlim(self.zz_dataLim.intervalx) + self.set_zlim3d(self.zz_dataLim.intervalx) def get_w_lims(self): '''Get 3d world limits.''' - minpy,maxx = self.get_w_xlim() - miny,maxy = self.get_w_ylim() - minz,maxz = self.get_w_zlim() - return minpy,maxx,miny,maxy,minz,maxz + minpy, maxx = self.get_xlim3d() + miny, maxy = self.get_ylim3d() + minz, maxz = self.get_zlim3d() + return minpy, maxx, miny, maxy, minz, maxz def _determine_lims(self, xmin=None, xmax=None, *args, **kwargs): if xmax is None and cbook.iterable(xmin): xmin, xmax = xmin return (xmin, xmax) - def set_w_zlim(self, *args, **kwargs): - '''Set 3d z limits.''' + def set_xlim3d(self, *args, **kwargs): + '''Set 3D x limits.''' lims = self._determine_lims(*args, **kwargs) - self.zz_viewLim.intervalx = lims + self.xy_viewLim.intervalx = lims return lims - def set_w_xlim(self, *args, **kwargs): - '''Set 3d x limits.''' + def set_ylim3d(self, *args, **kwargs): + '''Set 3D y limits.''' lims = self._determine_lims(*args, **kwargs) - self.xy_viewLim.intervalx = lims + self.xy_viewLim.intervaly = lims return lims - def set_w_ylim(self, *args, **kwargs): - '''Set 3d y limits.''' + def set_zlim3d(self, *args, **kwargs): + '''Set 3D z limits.''' lims = self._determine_lims(*args, **kwargs) - self.xy_viewLim.intervaly = lims + self.zz_viewLim.intervalx = lims return lims - def get_w_zlim(self): - return self.zz_viewLim.intervalx - - def get_w_xlim(self): + def get_xlim3d(self): + '''Get 3D x limits.''' return self.xy_viewLim.intervalx - def get_w_ylim(self): + def get_ylim3d(self): + '''Get 3D y limits.''' return self.xy_viewLim.intervaly + def get_zlim3d(self): + '''Get 3D z limits.''' + return self.zz_viewLim.intervalx + + def clabel(self, *args, **kwargs): + return None + def pany(self, numsteps): print 'numsteps', numsteps @@ -296,23 +265,23 @@ point. """ - relev,razim = np.pi * self.elev/180, np.pi * self.azim/180 + relev, razim = np.pi * self.elev/180, np.pi * self.azim/180 - xmin,xmax = self.get_w_xlim() - ymin,ymax = self.get_w_ylim() - zmin,zmax = self.get_w_zlim() + xmin, xmax = self.get_xlim3d() + ymin, ymax = self.get_ylim3d() + zmin, zmax = self.get_zlim3d() # transform to uniform world coordinates 0-1.0,0-1.0,0-1.0 - worldM = proj3d.world_transformation(xmin,xmax, - ymin,ymax, - zmin,zmax) + worldM = proj3d.world_transformation(xmin, xmax, + ymin, ymax, + zmin, zmax) # look into the middle of the new coordinates - R = np.array([0.5,0.5,0.5]) + R = np.array([0.5, 0.5, 0.5]) - xp = R[0] + np.cos(razim)*np.cos(relev)*self.dist - yp = R[1] + np.sin(razim)*np.cos(relev)*self.dist - zp = R[2] + np.sin(relev)*self.dist + xp = R[0] + np.cos(razim) * np.cos(relev) * self.dist + yp = R[1] + np.sin(razim) * np.cos(relev) * self.dist + zp = R[2] + np.sin(relev) * self.dist E = np.array((xp, yp, zp)) self.eye = E @@ -321,24 +290,24 @@ if abs(relev) > np.pi/2: # upside down - V = np.array((0,0,-1)) + V = np.array((0, 0, -1)) else: - V = np.array((0,0,1)) - zfront,zback = -self.dist,self.dist + V = np.array((0, 0, 1)) + zfront, zback = -self.dist, self.dist - viewM = proj3d.view_transformation(E,R,V) - perspM = proj3d.persp_transformation(zfront,zback) - M0 = np.dot(viewM,worldM) - M = np.dot(perspM,M0) + viewM = proj3d.view_transformation(E, R, V) + perspM = proj3d.persp_transformation(zfront, zback) + M0 = np.dot(viewM, worldM) + M = np.dot(perspM, M0) return M def mouse_init(self): self.button_pressed = None canv = self.figure.canvas if canv != None: - c1 = canv.mpl_connect('motion_notify_event', self.on_move) - c2 = canv.mpl_connect('button_press_event', self.button_press) - c3 = canv.mpl_connect('button_release_event', self.button_release) + c1 = canv.mpl_connect('motion_notify_event', self._on_move) + c2 = canv.mpl_connect('button_press_event', self._button_press) + c3 = canv.mpl_connect('button_release_event', self._button_release) self.cids = [c1, c2, c3] def cla(self): @@ -348,11 +317,11 @@ self.cids = [] Axes.cla(self) - def button_press(self, event): + def _button_press(self, event): self.button_pressed = event.button - self.sx,self.sy = event.xdata,event.ydata + self.sx, self.sy = event.xdata, event.ydata - def button_release(self, event): + def _button_release(self, event): self.button_pressed = None def format_xdata(self, x): @@ -361,10 +330,11 @@ self.fmt_xdata if it is callable, else will fall back on the xaxis major formatter """ - try: return self.fmt_xdata(x) + try: + return self.fmt_xdata(x) except TypeError: fmt = self.w_xaxis.get_major_formatter() - return sensible_format_data(fmt,x) + return sensible_format_data(fmt, x) def format_ydata(self, y): """ @@ -372,28 +342,30 @@ self.fmt_ydata if it is callable, else will fall back on the yaxis major formatter """ - try: return self.fmt_ydata(y) + try: + return self.fmt_ydata(y) except TypeError: fmt = self.w_yaxis.get_major_formatter() - return sensible_format_data(fmt,y) + return sensible_format_data(fmt, y) def format_zdata(self, z): """ - Return y string formatted. This function will use the attribute - self.fmt_ydata if it is callable, else will fall back on the yaxis + Return z string formatted. This function will use the attribute + self.fmt_zdata if it is callable, else will fall back on the yaxis major formatter """ - try: return self.fmt_zdata(z) - except (AttributeError,TypeError): + try: + return self.fmt_zdata(z) + except (AttributeError, TypeError): fmt = self.w_zaxis.get_major_formatter() - return sensible_format_data(fmt,z) + return sensible_format_data(fmt, z) def format_coord(self, xd, yd): - """Given the 2D view coordinates attempt to guess a 3D coordinate - - Looks for the nearest edge to the point and then assumes that the point is - at the same z location as the nearest point on the edge. """ + Given the 2D view coordinates attempt to guess a 3D coordinate. + Looks for the nearest edge to the point and then assumes that + the point is at the same z location as the nearest point on the edge. + """ if self.M is None: return '' @@ -402,32 +374,33 @@ return 'azimuth=%d deg, elevation=%d deg ' % (self.azim, self.elev) # ignore xd and yd and display angles instead - p = (xd,yd) + p = (xd, yd) edges = self.tunit_edges() #lines = [proj3d.line2d(p0,p1) for (p0,p1) in edges] - ldists = [(proj3d.line2d_seg_dist(p0,p1,p),i) for i,(p0,p1) in enumerate(edges)] + ldists = [(proj3d.line2d_seg_dist(p0, p1, p), i) for \ + i, (p0, p1) in enumerate(edges)] ldists.sort() # nearest edge edgei = ldists[0][1] - p0,p1 = edges[edgei] + p0, p1 = edges[edgei] # scale the z value to match - x0,y0,z0 = p0 - x1,y1,z1 = p1 - d0 = np.hypot(x0-xd,y0-yd) - d1 = np.hypot(x1-xd,y1-yd) + x0, y0, z0 = p0 + x1, y1, z1 = p1 + d0 = np.hypot(x0-xd, y0-yd) + d1 = np.hypot(x1-xd, y1-yd) dt = d0+d1 z = d1/dt * z0 + d0/dt * z1 - x,y,z = proj3d.inv_transform(xd,yd,z,self.M) + x, y, z = proj3d.inv_transform(xd, yd, z, self.M) xs = self.format_xdata(x) ys = self.format_ydata(y) zs = self.format_ydata(z) - return 'x=%s, y=%s, z=%s'%(xs,ys,zs) + return 'x=%s, y=%s, z=%s' % (xs, ys, zs) - def on_move(self, event): + def _on_move(self, event): """Mouse moving button-1 rotates @@ -438,27 +411,26 @@ if self.M is None: return - # this shouldn't be called before the graph has been drawn for the first time! + x, y = event.xdata, event.ydata - # In case the mouse is out of bounds. if x == None: - return - dx,dy = x-self.sx,y-self.sy - x0,x1 = self.get_xlim() - y0,y1 = self.get_ylim() + + dx, dy = x - self.sx, y - self.sy + x0, x1 = self.get_xlim() + y0, y1 = self.get_ylim() w = (x1-x0) h = (y1-y0) - self.sx,self.sy = x,y + self.sx, self.sy = x, y if self.button_pressed == 1: # rotate viewing point # get the x and y pixel coords if dx == 0 and dy == 0: return - self.elev = axis3d.norm_angle(self.elev - (dy/h)*180) - self.azim = axis3d.norm_angle(self.azim - (dx/w)*180) + self.elev = art3d.norm_angle(self.elev - (dy/h)*180) + self.azim = art3d.norm_angle(self.azim - (dx/w)*180) self.get_proj() self.figure.canvas.draw() elif self.button_pressed == 2: @@ -469,73 +441,122 @@ elif self.button_pressed == 3: # zoom view # hmmm..this needs some help from clipping.... - minpy,maxx,miny,maxy,minz,maxz = self.get_w_lims() + minpy, maxx, miny, maxy, minz, maxz = self.get_w_lims() df = 1-((h - dy)/h) dx = (maxx-minpy)*df dy = (maxy-miny)*df dz = (maxz-minz)*df - self.set_w_xlim(minpy-dx,maxx+dx) - self.set_w_ylim(miny-dy,maxy+dy) - self.set_w_zlim(minz-dz,maxz+dz) + self.set_xlim3d(minpy - dx, maxx + dx) + self.set_ylim3d(miny - dy, maxy + dy) + self.set_zlim3d(minz - dz, maxz + dz) self.get_proj() self.figure.canvas.draw() def set_xlabel(self, xlabel, fontdict=None, **kwargs): - #par = cbook.popd(kwargs, 'par',None) - #label.set_par(par) + '''Set xlabel. ''' label = self.w_xaxis.get_label() label.set_text(xlabel) - if fontdict is not None: label.update(fontdict) + if fontdict is not None: + label.update(fontdict) label.update(kwargs) return label def set_ylabel(self, ylabel, fontdict=None, **kwargs): + '''Set ylabel.''' + label = self.w_yaxis.get_label() label.set_text(ylabel) - if fontdict is not None: label.update(fontdict) + if fontdict is not None: + label.update(fontdict) label.update(kwargs) return label def set_zlabel(self, zlabel, fontdict=None, **kwargs): + '''Set zlabel.''' + label = self.w_zaxis.get_label() label.set_text(zlabel) - if fontdict is not None: label.update(fontdict) + if fontdict is not None: + label.update(fontdict) label.update(kwargs) return label - def plot(self, *args, **kwargs): + def text(self, x, y, z, s, zdir=None): + '''Add text to the plot.''' + text = Axes.text(self, x, y, s) + art3d.text_2d_to_3d(text, z, zdir) + return text + + text3D = text + + def plot(self, xs, ys, *args, **kwargs): + ''' + Plot 2D or 3D data. + + ========== ================================================ + Argument Description + ========== ================================================ + *xs*, *ys* X, y coordinates of vertices + + *zs* z value(s), either one for all points or one for + each point. + *zdir* Which direction to use as z ('x', 'y' or 'z') + when plotting a 2d set. + ========== ================================================ + + Other arguments are passed on to + :func:`~matplotlib.axes.Axes.plot` + ''' + had_data = self.has_data() + zs = kwargs.pop('zs', 0) + zdir = kwargs.pop('zdir', 'z') - zval = kwargs.pop( 'z', 0) - zdir = kwargs.pop('dir', 'z') - lines = Axes.plot(self, *args, **kwargs) + argsi = 0 + # First argument is array of zs + if len(args) > 0 and cbook.iterable(args[0]) and \ + len(xs) == len(args[0]) and cbook.is_scalar(args[0][0]): + zs = args[argsi] + argsi += 1 + + # First argument is z value + elif len(args) > 0 and cbook.is_scalar(args[0]): + zs = args[argsi] + argsi += 1 + + # Match length + if not cbook.iterable(zs): + zs = [zs] * len(xs) + + lines = Axes.plot(self, xs, ys, *args[argsi:], **kwargs) for line in lines: - art3d.line_2d_to_3d(line, z=zval, dir=zdir) + art3d.line_2d_to_3d(line, zs=zs, zdir=zdir) - xs = lines[0].get_xdata() - ys = lines[0].get_ydata() - zs = [zval for x in xs] - xs,ys,zs = art3d.juggle_axes(xs,ys,zs,zdir) - self.auto_scale_xyz(xs,ys,zs, had_data) + self.auto_scale_xyz(xs, ys, zs, had_data) return lines - def plot3D(self, xs, ys, zs, *args, **kwargs): - had_data = self.has_data() - lines = Axes.plot(self, xs,ys, *args, **kwargs) - if len(lines)==1: - line = lines[0] - art3d.line_2d_to_3d(line, zs) - self.auto_scale_xyz(xs,ys,zs, had_data) - return lines + plot3D = plot - plot3d=plot3D - def plot_surface(self, X, Y, Z, *args, **kwargs): + ''' + Create a surface plot. + + ========== ================================================ + Argument Description + ========== ================================================ + *X*, *Y*, Data values as numpy.arrays + *Z* + *rstride* Array row stride (step size) + *cstride* Array column stride (step size) + *color* Color of the surface patches + ========== ================================================ + ''' + had_data = self.has_data() rows, cols = Z.shape - tX,tY,tZ = np.transpose(X), np.transpose(Y), np.transpose(Z) + tX, tY, tZ = np.transpose(X), np.transpose(Y), np.transpose(Z) rstride = kwargs.pop('rstride', 10) cstride = kwargs.pop('cstride', 10) @@ -544,21 +565,21 @@ polys = [] boxes = [] - for rs in np.arange(0,rows-1,rstride): - for cs in np.arange(0,cols-1,cstride): + for rs in np.arange(0, rows-1, rstride): + for cs in np.arange(0, cols-1, cstride): ps = [] corners = [] - for a,ta in [(X,tX),(Y,tY),(Z,tZ)]: - ztop = a[rs][cs:min(cols,cs+cstride+1)] - zleft = ta[min(cols-1,cs+cstride)][rs:min(rows,rs+rstride+1)] - zbase = a[min(rows-1,rs+rstride)][cs:min(cols,cs+cstride+1):] + for a, ta in [(X, tX), (Y, tY), (Z, tZ)]: + ztop = a[rs][cs:min(cols, cs+cstride+1)] + zleft = ta[min(cols-1, cs+cstride)][rs:min(rows, rs+rstride+1)] + zbase = a[min(rows-1, rs+rstride)][cs:min(cols, cs+cstride+1):] zbase = zbase[::-1] - zright = ta[cs][rs:min(rows,rs+rstride+1):] + zright = ta[cs][rs:min(rows, rs+rstride+1):] zright = zright[::-1] - corners.append([ztop[0],ztop[-1],zbase[0],zbase[-1]]) - z = np.concatenate((ztop,zleft,zbase,zright)) + corners.append([ztop[0], ztop[-1], zbase[0], zbase[-1]]) + z = np.concatenate((ztop, zleft, zbase, zright)) ps.append(z) - boxes.append(map(np.array,zip(*corners))) + boxes.append(map(np.array, zip(*corners))) polys.append(zip(*ps)) lines = [] @@ -567,8 +588,8 @@ n = proj3d.cross(box[0]-box[1], box[0]-box[2]) n = n/proj3d.mod(n)*5 - shade.append(np.dot(n,[-1,-1,0.5])) - lines.append((box[0],n+box[0])) + shade.append(np.d... [truncated message content] |
From: <jd...@us...> - 2009-06-08 20:49:38
|
Revision: 7204 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7204&view=rev Author: jdh2358 Date: 2009-06-08 20:49:29 +0000 (Mon, 08 Jun 2009) Log Message: ----------- applied Goekhan's installation FAQ patch Modified Paths: -------------- trunk/matplotlib/doc/faq/installing_faq.rst trunk/matplotlib/lib/matplotlib/cbook.py Modified: trunk/matplotlib/doc/faq/installing_faq.rst =================================================================== --- trunk/matplotlib/doc/faq/installing_faq.rst 2009-06-08 16:28:21 UTC (rev 7203) +++ trunk/matplotlib/doc/faq/installing_faq.rst 2009-06-08 20:49:29 UTC (rev 7204) @@ -106,6 +106,19 @@ > cd matplotlib > python setup.py install +If you want to be able to follow the development branch as it changes just replace +the last step with (Make sure you have **setuptools** installed):: + + > python setupegg.py develop + +This creates links in the right places and installs the command line script to the appropriate places. +Then, if you want to update your **matplotlib** at any time, just do:: + + > svn update + +When you run `svn update`, if the output shows that only Python files have been updated, you are all set. +If C files have changed, you need to run the `python setupegg develop` command again to compile them. + There is more information on :ref:`using Subversion <using-svn>` in the developer docs. Modified: trunk/matplotlib/lib/matplotlib/cbook.py =================================================================== --- trunk/matplotlib/lib/matplotlib/cbook.py 2009-06-08 16:28:21 UTC (rev 7203) +++ trunk/matplotlib/lib/matplotlib/cbook.py 2009-06-08 20:49:29 UTC (rev 7204) @@ -254,6 +254,10 @@ self.__dict__.update(kwds) + def __repr__(self): + keys = self.__dict__.keys() + return 'Bunch(%s)'%', '.join(['%s=%s'%(k,self.__dict__[k]) for k in keys]) + def unique(x): 'Return a list of unique elements of *x*' return dict([ (val, 1) for val in x]).keys() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <he...@us...> - 2009-06-09 22:41:32
|
Revision: 7206 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7206&view=rev Author: heeres Date: 2009-06-09 22:40:35 +0000 (Tue, 09 Jun 2009) Log Message: ----------- mplot3d: make Poly3DCollection ScalarMappable, support in Axes3D.plot_surface. Fix-up and extend contours. Add examples. Modified Paths: -------------- trunk/matplotlib/doc/mpl_toolkits/mplot3d/tutorial.rst trunk/matplotlib/examples/mplot3d/surface3d_demo.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py Added Paths: ----------- trunk/matplotlib/examples/mplot3d/contour3d_demo2.py trunk/matplotlib/examples/mplot3d/surface3d_demo2.py Modified: trunk/matplotlib/doc/mpl_toolkits/mplot3d/tutorial.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/mplot3d/tutorial.rst 2009-06-09 16:47:46 UTC (rev 7205) +++ trunk/matplotlib/doc/mpl_toolkits/mplot3d/tutorial.rst 2009-06-09 22:40:35 UTC (rev 7206) @@ -38,12 +38,14 @@ .. automethod:: Axes3D.plot_surface .. plot:: mpl_examples/mplot3d/surface3d_demo.py +.. plot:: mpl_examples/mplot3d/surface3d_demo2.py Contour plots ============= .. automethod:: Axes3D.contour .. plot:: mpl_examples/mplot3d/contour3d_demo.py +.. plot:: mpl_examples/mplot3d/contour3d_demo2.py Filled contour plots ==================== Added: trunk/matplotlib/examples/mplot3d/contour3d_demo2.py =================================================================== --- trunk/matplotlib/examples/mplot3d/contour3d_demo2.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/contour3d_demo2.py 2009-06-09 22:40:35 UTC (rev 7206) @@ -0,0 +1,12 @@ +from mpl_toolkits.mplot3d import axes3d +import pylab +import random + +fig = pylab.figure() +ax = axes3d.Axes3D(fig) +X, Y, Z = axes3d.get_test_data(0.05) +cset = ax.contour(X, Y, Z, 16, extend3d=True) +ax.clabel(cset, fontsize=9, inline=1) + +pylab.show() + Modified: trunk/matplotlib/examples/mplot3d/surface3d_demo.py =================================================================== --- trunk/matplotlib/examples/mplot3d/surface3d_demo.py 2009-06-09 16:47:46 UTC (rev 7205) +++ trunk/matplotlib/examples/mplot3d/surface3d_demo.py 2009-06-09 22:40:35 UTC (rev 7206) @@ -1,16 +1,17 @@ from mpl_toolkits.mplot3d import Axes3D +from matplotlib import cm import pylab import random import numpy as np fig = pylab.figure() ax = Axes3D(fig) -X = np.arange(-5, 5, 0.5) -Y = np.arange(-5, 5, 0.5) +X = np.arange(-5, 5, 0.25) +Y = np.arange(-5, 5, 0.25) X, Y = np.meshgrid(X, Y) R = np.sqrt(X**2 + Y**2) Z = np.sin(R) -ax.plot_surface(X, Y, Z, rstride=1, cstride=1, color='forestgreen') +ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet) pylab.show() Added: trunk/matplotlib/examples/mplot3d/surface3d_demo2.py =================================================================== --- trunk/matplotlib/examples/mplot3d/surface3d_demo2.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/surface3d_demo2.py 2009-06-09 22:40:35 UTC (rev 7206) @@ -0,0 +1,18 @@ +from mpl_toolkits.mplot3d import Axes3D +import pylab +import random +import numpy as np + +fig = pylab.figure() +ax = Axes3D(fig) + +u = np.linspace(0, 2 * np.pi, 100) +v = np.linspace(0, np.pi, 100) + +x = 10 * np.outer(np.cos(u), np.sin(v)) +y = 10 * np.outer(np.sin(u), np.sin(v)) +z = 10 * np.outer(np.ones(np.size(u)), np.cos(v)) +ax.plot_surface(x, y, z, rstride=4, cstride=4, color='b') + +pylab.show() + Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py 2009-06-09 16:47:46 UTC (rev 7205) +++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py 2009-06-09 22:40:35 UTC (rev 7206) @@ -10,6 +10,7 @@ from matplotlib import lines, text as mtext, path as mpath, colors as mcolors from matplotlib.collections import Collection, LineCollection, \ PolyCollection, PatchCollection +from matplotlib.cm import ScalarMappable from matplotlib.patches import Patch from matplotlib.colors import Normalize from matplotlib.cbook import iterable @@ -111,26 +112,30 @@ line.__class__ = Line3D line.set_3d_properties(zs, zdir) -def path_to_3d_segment(path, z=0, zdir='z'): +def path_to_3d_segment(path, zs=0, zdir='z'): '''Convert a path to a 3D segment.''' + + if not iterable(zs): + zs = [zs] * len(path) + seg = [] - for (pathseg, code) in path.iter_segments(): - seg.append(pathseg) - seg3d = [juggle_axes(x, y, z, zdir) for (x, y) in seg] + pathsegs = path.iter_segments(simplify=False, curves=False) + for (((x, y), code), z) in zip(pathsegs, zs): + seg.append((x, y, z)) + seg3d = [juggle_axes(x, y, z, zdir) for (x, y, z) in seg] return seg3d def paths_to_3d_segments(paths, zs=0, zdir='z'): - '''Convert paths from a collection object to 3D segments.''' + ''' + Convert paths from a collection object to 3D segments. + ''' - try: - zs = float(zs) + if not iterable(zs): zs = [zs] * len(paths) - except: - pass segments = [] - for path, z in zip(paths, zs): - segments.append(path_to_3d_segment(path, z, zdir)) + for path, pathz in zip(paths, zs): + segments.append(path_to_3d_segment(path, pathz, zdir)) return segments class Line3DCollection(LineCollection): @@ -255,8 +260,17 @@ ''' def __init__(self, verts, *args, **kwargs): + ''' + Create a Poly3DCollection. + + *verts* should contain 3D coordinates. + + Note that this class does a bit of magic with the _facecolors + and _edgecolors properties. + ''' + PolyCollection.__init__(self, verts, *args, **kwargs) - self.set_3d_properties() + self._zsort = 1 def get_vector(self, segments3d): """Optimize points for projection""" @@ -276,6 +290,7 @@ self._sort_zpos = min(zs) def set_verts(self, verts, closed=True): + '''Set 3D vertices.''' self.get_vector(verts) # 2D verts will be updated at draw time PolyCollection.set_verts(self, [], closed) @@ -283,40 +298,73 @@ def set_3d_properties(self): self._zsort = 1 self._facecolors3d = PolyCollection.get_facecolors(self) - self._edgecolors3d = self.get_edgecolors() + self._edgecolors3d = PolyCollection.get_edgecolors(self) def do_3d_projection(self, renderer): + ''' + Perform the 3D projection for this object. + ''' + + if self._A is not None: + self.update_scalarmappable() + self._facecolors3d = self._facecolors + txs, tys, tzs = proj3d.proj_transform_vec(self._vec, renderer.M) xyzlist = [(txs[si:ei], tys[si:ei], tzs[si:ei]) \ for si, ei in self._segis] - colors = self._facecolors3d + # This extra fuss is to re-order face / edge colors + cface = self._facecolors3d + if len(self._edgecolors3d) != len(cface): + cedge = cface + else: + cedge = self._edgecolors3d + # if required sort by depth (furthest drawn first) if self._zsort: - z_segments_2d = [(min(zs), zip(xs, ys), c) for - (xs, ys, zs), c in zip(xyzlist, colors)] + z_segments_2d = [(min(zs), zip(xs, ys), fc, ec) for + (xs, ys, zs), fc, ec in zip(xyzlist, cface, cedge)] z_segments_2d.sort() z_segments_2d.reverse() else: raise ValueError, "whoops" - segments_2d = [s for z, s, c in z_segments_2d] - colors = [c for z, s, c in z_segments_2d] + + segments_2d = [s for z, s, fc, ec in z_segments_2d] PolyCollection.set_verts(self, segments_2d) - self._facecolors2d = colors + self._facecolors2d = [fc for z, s, fc, ec in z_segments_2d] + if len(self._edgecolors3d) == len(cface): + self._edgecolors2d = [ec for z, s, fc, ec in z_segments_2d] + else: + self._edgecolors2d = self._edgecolors3d + # Return zorder value zvec = np.array([[0], [0], [self._sort_zpos], [1]]) ztrans = proj3d.proj_transform_vec(zvec, renderer.M) return ztrans[2][0] + def set_facecolor(self, colors): + PolyCollection.set_facecolor(self, colors) + self._facecolors3d = PolyCollection.get_facecolor(self) + set_facecolors = set_facecolor + + def set_edgecolor(self, colors): + PolyCollection.set_edgecolor(self, colors) + self._edgecolors3d = PolyCollection.get_edgecolor(self) + set_edgecolors = set_edgecolor + def get_facecolors(self): return self._facecolors2d get_facecolor = get_facecolors + def get_edgecolors(self): + return self._edgecolors2d + get_edgecolor = get_edgecolors + def draw(self, renderer): return Collection.draw(self, renderer) -def poly_collection_2d_to_3d(col, zs=None, zdir='z'): +def poly_collection_2d_to_3d(col, zs=0, zdir='z'): """Convert a PolyCollection to a Poly3DCollection object.""" segments_3d = paths_to_3d_segments(col.get_paths(), zs, zdir) col.__class__ = Poly3DCollection Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2009-06-09 16:47:46 UTC (rev 7205) +++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2009-06-09 22:40:35 UTC (rev 7206) @@ -541,6 +541,10 @@ def plot_surface(self, X, Y, Z, *args, **kwargs): ''' Create a surface plot. + + By default it will be colored in shades of a solid color, + but it also supports color mapping by supplying the *cmap* + argument. ========== ================================================ Argument Description @@ -550,6 +554,7 @@ *rstride* Array row stride (step size) *cstride* Array column stride (step size) *color* Color of the surface patches + *cmap* A colormap for the surface patches. ========== ================================================ ''' @@ -562,9 +567,11 @@ color = kwargs.pop('color', 'b') color = np.array(colorConverter.to_rgba(color)) + cmap = kwargs.get('cmap', None) polys = [] - boxes = [] + normals = [] + avgz = [] for rs in np.arange(0, rows-1, rstride): for cs in np.arange(0, cols-1, cstride): ps = [] @@ -579,31 +586,53 @@ corners.append([ztop[0], ztop[-1], zbase[0], zbase[-1]]) z = np.concatenate((ztop, zleft, zbase, zright)) ps.append(z) - boxes.append(map(np.array, zip(*corners))) - polys.append(zip(*ps)) - lines = [] + # The construction leaves the array with duplicate points, which + # are removed here. + ps = zip(*ps) + lastp = np.array([]) + ps2 = [] + avgzsum = 0.0 + for p in ps: + if p != lastp: + ps2.append(p) + lastp = p + avgzsum += p[2] + polys.append(ps2) + avgz.append(avgzsum / len(ps2)) + + v1 = np.array(ps2[0]) - np.array(ps2[1]) + v2 = np.array(ps2[2]) - np.array(ps2[0]) + normals.append(np.cross(v1, v2)) + + polyc = art3d.Poly3DCollection(polys, *args, **kwargs) + if cmap is not None: + polyc.set_array(np.array(avgz)) + polyc.set_linewidth(0) + else: + colors = self._shade_colors(color, normals) + polyc.set_facecolors(colors) + + self.add_collection(polyc) + self.auto_scale_xyz(X, Y, Z, had_data) + + return polyc + + def _shade_colors(self, color, normals): shade = [] - for box in boxes: - n = proj3d.cross(box[0]-box[1], - box[0]-box[2]) - n = n/proj3d.mod(n)*5 + for n in normals: + n = n / proj3d.mod(n) * 5 shade.append(np.dot(n, [-1, -1, 0.5])) - lines.append((box[0], n+box[0])) shade = np.array(shade) mask = ~np.isnan(shade) norm = Normalize(min(shade[mask]), max(shade[mask])) - colors = [color * (0.5+norm(v)*0.5) for v in shade] - for c in colors: c[3] = 1 - polyc = art3d.Poly3DCollection(polys, facecolors=colors, \ - *args, **kwargs) - polyc._zsort = 1 - self.add_collection(polyc) + color = color.copy() + color[3] = 1 + colors = [color * (0.5 + norm(v) * 0.5) for v in shade] - self.auto_scale_xyz(X, Y, Z, had_data) - return polyc + return colors def plot_wireframe(self, X, Y, Z, *args, **kwargs): ''' @@ -653,21 +682,78 @@ return linec - def contour(self, X, Y, Z, *args, **kwargs): + def _3d_extend_contour(self, cset, stride=5): ''' + Extend a contour in 3D by creating + ''' + + levels = cset.levels + colls = cset.collections + dz = (levels[1] - levels[0]) / 2 + + for z, linec in zip(levels, colls): + topverts = art3d.paths_to_3d_segments(linec.get_paths(), z - dz) + botverts = art3d.paths_to_3d_segments(linec.get_paths(), z + dz) + + color = linec.get_color()[0] + + polyverts = [] + normals = [] + nsteps = round(len(topverts[0]) / stride) + stepsize = (len(topverts[0]) - 1) / (nsteps - 1) + for i in range(int(round(nsteps)) - 1): + i1 = int(round(i * stepsize)) + i2 = int(round((i + 1) * stepsize)) + polyverts.append([topverts[0][i1], + topverts[0][i2], + botverts[0][i2], + botverts[0][i1]]) + + v1 = np.array(topverts[0][i1]) - np.array(topverts[0][i2]) + v2 = np.array(topverts[0][i1]) - np.array(botverts[0][i1]) + normals.append(np.cross(v1, v2)) + + colors = self._shade_colors(color, normals) + colors2 = self._shade_colors(color, normals) + polycol = art3d.Poly3DCollection(polyverts, facecolors=colors, + edgecolors=colors2) + self.add_collection3d(polycol) + + for col in colls: + self.collections.remove(col) + + def contour(self, X, Y, Z, levels=10, **kwargs): + ''' Create a 3D contour plot. - *X*, *Y*, *Z*: data + ========== ================================================ + Argument Description + ========== ================================================ + *X*, *Y*, Data values as numpy.arrays + *Z* + *levels* Number of levels to use, defaults to 10. Can + also be a tuple of specific levels. + *extend3d* Whether to extend contour in 3D (default: False) + *stride* Stride (step size) for extending contour + ========== ================================================ - Keyword arguments are passed on to + Other keyword arguments are passed on to :func:`~matplotlib.axes.Axes.contour` ''' + extend3d = kwargs.pop('extend3d', False) + stride = kwargs.pop('stride', 5) + nlevels = kwargs.pop('nlevels', 15) + had_data = self.has_data() - cset = Axes.contour(self, X, Y, Z, *args, **kwargs) - for z, linec in zip(cset.levels, cset.collections): - art3d.line_collection_2d_to_3d(linec, z) + cset = Axes.contour(self, X, Y, Z, levels, **kwargs) + if extend3d: + self._3d_extend_contour(cset, stride) + else: + for z, linec in zip(cset.levels, cset.collections): + art3d.line_collection_2d_to_3d(linec, z) + self.auto_scale_xyz(X, Y, Z, had_data) return cset @@ -688,11 +774,8 @@ cset = Axes.contourf(self, X, Y, Z, *args, **kwargs) levels = cset.levels colls = cset.collections - for z1, z2, linec in zip(levels, levels[1:], colls): - zs = [z1] * (len(linec.get_paths()[0]) / 2) - zs += [z2] * (len(linec.get_paths()[0]) / 2) - art3d.poly_collection_2d_to_3d(linec, zs) + art3d.poly_collection_2d_to_3d(linec, z1) self.auto_scale_xyz(X, Y, Z, had_data) return cset This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-06-12 14:03:31
|
Revision: 7212 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7212&view=rev Author: mdboom Date: 2009-06-12 13:46:48 +0000 (Fri, 12 Jun 2009) Log Message: ----------- Merged revisions 7209,7211 via svnmerge from https://matplotlib.svn.sf.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r7209 | jdh2358 | 2009-06-10 13:39:22 -0400 (Wed, 10 Jun 2009) | 1 line remove gw32c from setupext ........ r7211 | mdboom | 2009-06-12 09:39:59 -0400 (Fri, 12 Jun 2009) | 2 lines Fix PDFs for use with ReportLab's pedantic parser ........ Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7176 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7211 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211 Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211 Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009-06-12 13:39:59 UTC (rev 7211) +++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009-06-12 13:46:48 UTC (rev 7212) @@ -1215,7 +1215,10 @@ 'No offset for object %d (%s)' % (i, name) borken = True else: - self.write("%010d %05d n \n" % (offset, generation)) + if name == 'the zero object': + self.write("%010d %05d f \n" % (offset, generation)) + else: + self.write("%010d %05d n \n" % (offset, generation)) i += 1 if borken: raise AssertionError, 'Indirect object does not exist' Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176 + /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176 + /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176 + /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2009-06-12 19:43:02
|
Revision: 7213 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7213&view=rev Author: jdh2358 Date: 2009-06-12 19:41:58 +0000 (Fri, 12 Jun 2009) Log Message: ----------- readded the long lost IndexFormatter Modified Paths: -------------- trunk/matplotlib/examples/pylab_examples/manual_axis.py trunk/matplotlib/lib/matplotlib/ticker.py Modified: trunk/matplotlib/examples/pylab_examples/manual_axis.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/manual_axis.py 2009-06-12 13:46:48 UTC (rev 7212) +++ trunk/matplotlib/examples/pylab_examples/manual_axis.py 2009-06-12 19:41:58 UTC (rev 7213) @@ -1,10 +1,11 @@ """ -matplotlib is fairly rigid about how and where it draws it xaxis and -yaxis, and it is a frequent request to be able to place these in other -locations. While it is not possible to customize matplotlib's -internal axis objects in this way, it is not too hard to simply turn -them off and draw your own axis lines, tick lines, and tick labels -where and how you want them +The techniques here are no longer required with the new support for +spines in matplotlib -- see +http://matplotlib.sourceforge.net/examples/pylab_examples/spine_placement_demo.html. + +This example should be considered deprecated and is left just for demo +purposes for folks wanting to make a pseudo-axis + """ import numpy as np Modified: trunk/matplotlib/lib/matplotlib/ticker.py =================================================================== --- trunk/matplotlib/lib/matplotlib/ticker.py 2009-06-12 13:46:48 UTC (rev 7212) +++ trunk/matplotlib/lib/matplotlib/ticker.py 2009-06-12 19:41:58 UTC (rev 7213) @@ -80,6 +80,9 @@ :class:`NullFormatter` no labels on the ticks +:class:`IndexFormatter` + set the strings from a list of labels + :class:`FixedFormatter` set the strings manually for the labels @@ -203,6 +206,24 @@ """ return s +class IndexFormatter: + """ + format the position x to the nearest i-th label where i=int(x+0.5) + """ + def __init__(self, labels): + self.labels = labels + self.n = len(labels) + def __call__(self, x, pos=None): + 'Return the format for tick val x at position pos; pos=None indicated unspecified' + i = int(x+0.5) + if i<0: + return '' + elif i>=self.n: + return '' + else: + return self.labels[i] + + class NullFormatter(Formatter): 'Always return the empty string' def __call__(self, x, pos=None): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2009-06-13 16:54:38
|
Revision: 7215 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7215&view=rev Author: leejjoon Date: 2009-06-13 16:54:31 +0000 (Sat, 13 Jun 2009) Log Message: ----------- Introduce a rotation_mode property for the Text artist Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/text.py Added Paths: ----------- trunk/matplotlib/examples/pylab_examples/demo_text_rotation_mode.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-06-13 12:09:29 UTC (rev 7214) +++ trunk/matplotlib/CHANGELOG 2009-06-13 16:54:31 UTC (rev 7215) @@ -1,3 +1,6 @@ +2009-06-13 Introduce a rotation_mode property for the Text artist. See + examples/pylab_examples/demo_text_rotation_mode.py -JJL + 2009-06-07 add support for bz2 files per sf support request 2794556 - JDH Added: trunk/matplotlib/examples/pylab_examples/demo_text_rotation_mode.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/demo_text_rotation_mode.py (rev 0) +++ trunk/matplotlib/examples/pylab_examples/demo_text_rotation_mode.py 2009-06-13 16:54:31 UTC (rev 7215) @@ -0,0 +1,45 @@ + +#clf() +from mpl_toolkits.axes_grid.axes_grid import AxesGrid + +def test_rotation_mode(fig, mode, subplot_location): + ha_list = "left center right".split() + va_list = "top center baseline bottom".split() + grid = AxesGrid(fig, subplot_location, + nrows_ncols=(len(va_list), len(ha_list)), + share_all=True, aspect=True, #label_mode='1', + cbar_mode=None) + + for ha, ax in zip(ha_list, grid.axes_row[-1]): + ax.axis["bottom"].label.set_text(ha) + + grid.axes_row[0][1].set_title(mode, size="large") + + for va, ax in zip(va_list, grid.axes_column[0]): + ax.axis["left"].label.set_text(va) + + i = 0 + for va in va_list: + for ha in ha_list: + ax = grid[i] + for axis in ax.axis.values(): + axis.toggle(ticks=False, ticklabels=False) + + ax.text(0.5, 0.5, "Tpg", + size="large", rotation=40, + bbox=dict(boxstyle="square,pad=0.", + ec="none", fc="0.5", alpha=0.5), + ha=ha, va=va, + rotation_mode=mode) + ax.axvline(0.5) + ax.axhline(0.5) + i += 1 + +if 1: + import matplotlib.pyplot as plt + fig = plt.figure(1, figsize=(5.5,4 )) + fig.clf() + + test_rotation_mode(fig, "default", 121) + test_rotation_mode(fig, "anchor", 122) + plt.show() Modified: trunk/matplotlib/lib/matplotlib/text.py =================================================================== --- trunk/matplotlib/lib/matplotlib/text.py 2009-06-13 12:09:29 UTC (rev 7214) +++ trunk/matplotlib/lib/matplotlib/text.py 2009-06-13 16:54:31 UTC (rev 7215) @@ -69,6 +69,7 @@ name or fontname string eg, ['Sans' | 'Courier' | 'Helvetica' ...] position (x,y) rotation [ angle in degrees 'vertical' | 'horizontal' + rotation_mode [ None | 'anchor'] size or fontsize [ size in points | relative size eg 'smaller', 'x-large' ] style or fontstyle [ 'normal' | 'italic' | 'oblique'] text string @@ -144,6 +145,7 @@ fontproperties=None, # defaults to FontProperties() rotation=None, linespacing=None, + rotation_mode=None, **kwargs ): """ @@ -175,6 +177,7 @@ if linespacing is None: linespacing = 1.2 # Maybe use rcParam later. self._linespacing = linespacing + self.set_rotation_mode(rotation_mode) self.update(kwargs) #self.set_bbox(dict(pad=0)) @@ -214,6 +217,24 @@ 'return the text angle as float in degrees' return get_rotation(self._rotation) # string_or_number -> number + def set_rotation_mode(self, m): + """ + set text rotation mode. If "anchor", the un-rotated text + will first aligned according to their *ha* and + *va*, and then will be rotated with the alignement + reference point as a origin. If None (default), the text will be + rotated first then will be aligned. + """ + if m is None or m in ["anchor", "default"]: + self._rotation_mode = m + else: + raise ValueError("Unknown rotation_mode : %s" % repr(m)) + + def get_rotation_mode(self): + "get text rotation mode" + return self._rotation_mode + + def update_from(self, other): 'Copy properties from other to self' Artist.update_from(self, other) @@ -268,7 +289,7 @@ # For multiline text, increase the line spacing when the # text net-height(excluding baseline) is larger than that # of a "l" (e.g., use of superscripts), which seems - # what TeX does. + # what TeX does. d_yoffset = max(0, (h-d)-(lp_h-lp_bl)) @@ -315,17 +336,34 @@ halign = self._horizontalalignment valign = self._verticalalignment - # compute the text location in display coords and the offsets - # necessary to align the bbox with that location - if halign=='center': offsetx = (xmin + width/2.0) - elif halign=='right': offsetx = (xmin + width) - else: offsetx = xmin + rotation_mode = self.get_rotation_mode() + if rotation_mode != "anchor": + # compute the text location in display coords and the offsets + # necessary to align the bbox with that location + if halign=='center': offsetx = (xmin + width/2.0) + elif halign=='right': offsetx = (xmin + width) + else: offsetx = xmin - if valign=='center': offsety = (ymin + height/2.0) - elif valign=='top': offsety = (ymin + height) - elif valign=='baseline': offsety = (ymin + height) - baseline - else: offsety = ymin + if valign=='center': offsety = (ymin + height/2.0) + elif valign=='top': offsety = (ymin + height) + elif valign=='baseline': offsety = (ymin + height) - baseline + else: offsety = ymin + else: + xmin1, ymin1 = cornersHoriz[0] + xmax1, ymax1 = cornersHoriz[2] + if halign=='center': offsetx = (xmin1 + xmax1)/2.0 + elif halign=='right': offsetx = xmax1 + else: offsetx = xmin1 + + if valign=='center': offsety = (ymin1 + ymax1)/2.0 + elif valign=='top': offsety = ymax1 + elif valign=='baseline': offsety = ymax1 - baseline + else: offsety = ymin1 + + offsetx, offsety = M.transform_point((offsetx, offsety)) + + xmin -= offsetx ymin -= offsety @@ -1562,8 +1600,8 @@ See :meth:`set_annotation_clip` for the meaning of return values. """ return self._annotation_clip - + def update_positions(self, renderer): "Update the pixel positions of the annotated point and the text." xy_pixel = self._get_position_xy(renderer) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <he...@us...> - 2009-06-13 21:13:17
|
Revision: 7216 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7216&view=rev Author: heeres Date: 2009-06-13 21:13:14 +0000 (Sat, 13 Jun 2009) Log Message: ----------- mplot3d: fix Axes3D.grid(), add axes3d.grid to matplotlibrc Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/rcsetup.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/axis3d.py trunk/matplotlib/matplotlibrc.template Modified: trunk/matplotlib/lib/matplotlib/rcsetup.py =================================================================== --- trunk/matplotlib/lib/matplotlib/rcsetup.py 2009-06-13 16:54:31 UTC (rev 7215) +++ trunk/matplotlib/lib/matplotlib/rcsetup.py 2009-06-13 21:13:14 UTC (rev 7216) @@ -441,6 +441,7 @@ 'axes.unicode_minus' : [True, validate_bool], 'polaraxes.grid' : [True, validate_bool], # display polar grid or not + 'axes3d.grid' : [True, validate_bool], # display 3d grid #legend properties 'legend.fancybox' : [False,validate_bool], Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2009-06-13 16:54:31 UTC (rev 7215) +++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2009-06-13 21:13:14 UTC (rev 7216) @@ -8,7 +8,7 @@ 2D matplotlib figure. """ -from matplotlib.axes import Axes +from matplotlib.axes import Axes, rcParams from matplotlib import cbook from matplotlib.transforms import Bbox from matplotlib import collections @@ -316,6 +316,7 @@ self.figure.canvas.mpl_disconnect(cid) self.cids = [] Axes.cla(self) + self.grid(rcParams['axes3d.grid']) def _button_press(self, event): self.button_pressed = event.button @@ -482,6 +483,12 @@ label.update(kwargs) return label + def grid(self, on=True, **kwargs): + ''' + Set / unset 3D grid. + ''' + self._draw_grid = on + def text(self, x, y, z, s, zdir=None): '''Add text to the plot.''' text = Axes.text(self, x, y, s) Modified: trunk/matplotlib/lib/mpl_toolkits/mplot3d/axis3d.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/mplot3d/axis3d.py 2009-06-13 16:54:31 UTC (rev 7215) +++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/axis3d.py 2009-06-13 21:13:14 UTC (rev 7216) @@ -43,6 +43,7 @@ tick.tick1line.set_linestyle('-') tick.tick1line.set_marker('') tick.tick1line.set_data(tickxs, tickys) + tick.gridline.set_data(0, 0) class Axis(maxis.XAxis): @@ -143,7 +144,8 @@ # filter locations here so that no extra grid lines are drawn interval = self.get_view_interval() - majorLocs = [loc for loc in majorLocs if interval[0] < loc < interval[1]] + majorLocs = [loc for loc in majorLocs if \ + interval[0] < loc < interval[1]] self.major.formatter.set_locs(majorLocs) majorLabels = [self.major.formatter(val, i) for i, val in enumerate(majorLocs)] @@ -230,9 +232,10 @@ xyz2[i][newindex] = newval lines = zip(xyz1, xyz0, xyz2) - self.gridlines.set_segments(lines) - self.gridlines.set_color([(0.9,0.9,0.9,1)] * len(lines)) - self.gridlines.draw(renderer, project=True) + if self.axes._draw_grid: + self.gridlines.set_segments(lines) + self.gridlines.set_color([(0.9,0.9,0.9,1)] * len(lines)) + self.gridlines.draw(renderer, project=True) # Draw ticks tickdir = info['tickdir'] Modified: trunk/matplotlib/matplotlibrc.template =================================================================== --- trunk/matplotlib/matplotlibrc.template 2009-06-13 16:54:31 UTC (rev 7215) +++ trunk/matplotlib/matplotlibrc.template 2009-06-13 21:13:14 UTC (rev 7216) @@ -210,6 +210,7 @@ # rather than hypen. See http://en.wikipedia.org/wiki/Plus_sign#Plus_sign #polaraxes.grid : True # display grid on polar axes +#axes3d.grid : True # display grid on 3d axes ### TICKS # see http://matplotlib.sourceforge.net/api/axis_api.html#matplotlib.axis.Tick This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2009-06-14 02:14:34
|
Revision: 7217 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7217&view=rev Author: efiring Date: 2009-06-14 01:32:20 +0000 (Sun, 14 Jun 2009) Log Message: ----------- partial cleanup of mlab and of the pylab imports from mlab Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/cbook.py trunk/matplotlib/lib/matplotlib/mlab.py trunk/matplotlib/lib/matplotlib/pylab.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-06-13 21:13:14 UTC (rev 7216) +++ trunk/matplotlib/CHANGELOG 2009-06-14 01:32:20 UTC (rev 7217) @@ -1,3 +1,5 @@ +2009-06-13 partial cleanup of mlab and its importation in pylab - EF + 2009-06-13 Introduce a rotation_mode property for the Text artist. See examples/pylab_examples/demo_text_rotation_mode.py -JJL Modified: trunk/matplotlib/lib/matplotlib/cbook.py =================================================================== --- trunk/matplotlib/lib/matplotlib/cbook.py 2009-06-13 21:13:14 UTC (rev 7216) +++ trunk/matplotlib/lib/matplotlib/cbook.py 2009-06-14 01:32:20 UTC (rev 7217) @@ -761,36 +761,6 @@ - -# python 2.2 dicts don't have pop--but we don't support 2.2 any more -def popd(d, *args): - """ - Should behave like python2.3 :meth:`dict.pop` method; *d* is a - :class:`dict`:: - - # returns value for key and deletes item; raises a KeyError if key - # is not in dict - val = popd(d, key) - - # returns value for key if key exists, else default. Delete key, - # val item if it exists. Will not raise a KeyError - val = popd(d, key, default) - - """ - warnings.warn("Use native python dict.pop method", DeprecationWarning) - # warning added 2008/07/22 - if len(args)==1: - key = args[0] - val = d[key] - del d[key] - elif len(args)==2: - key, default = args - val = d.get(key, default) - try: del d[key] - except KeyError: pass - return val - - class maxdict(dict): """ A dictionary with a maximum size; this doesn't override all the Modified: trunk/matplotlib/lib/matplotlib/mlab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mlab.py 2009-06-13 21:13:14 UTC (rev 7216) +++ trunk/matplotlib/lib/matplotlib/mlab.py 2009-06-14 01:32:20 UTC (rev 7217) @@ -130,39 +130,12 @@ care--function signatures may differ): -:meth:`conv` - convolution (numpy.convolve) - -:meth:`corrcoef` - The matrix of correlation coefficients - -:meth:`hist` - Histogram (numpy.histogram) - -:meth:`linspace` - Linear spaced array from min to max - :meth:`load` load ASCII file - use numpy.loadtxt -:meth:`meshgrid` - Make a 2D grid from 2 1 arrays (numpy.meshgrid) - -:meth:`polyfit` - least squares best polynomial fit of x to y (numpy.polyfit) - -:meth:`polyval` - evaluate a vector for a vector of polynomial coeffs (numpy.polyval) - :meth:`save` save ASCII file - use numpy.savetxt -:meth:`trapz` - trapeziodal integration (trapz(x,y) -> numpy.trapz(y,x)) - -:meth:`vander` - the Vandermonde matrix (numpy.vander) - """ from __future__ import division @@ -176,20 +149,6 @@ import matplotlib.cbook as cbook -def linspace(*args, **kw): - warnings.warn("use numpy.linspace", DeprecationWarning) - return np.linspace(*args, **kw) - -def meshgrid(x,y): - warnings.warn("use numpy.meshgrid", DeprecationWarning) - return np.meshgrid(x,y) - -def mean(x, dim=None): - warnings.warn("Use numpy.mean(x) or x.mean()", DeprecationWarning) - if len(x)==0: return None - return np.mean(x, axis=dim) - - def logspace(xmin,xmax,N): return np.exp(np.linspace(np.log(xmin), np.log(xmax), N)) @@ -205,12 +164,6 @@ "No window function; simply return x" return x -#from numpy import convolve as conv -def conv(x, y, mode=2): - 'convolve x with y' - warnings.warn("Use numpy.convolve(x, y, mode='full')", DeprecationWarning) - return np.convolve(x,y,mode) - def detrend(x, key=None): if key is None or key=='constant': return detrend_mean(x) @@ -537,111 +490,7 @@ cohere.__doc__ = cohere.__doc__ % kwdocd -def corrcoef(*args): - """ - corrcoef(*X*) where *X* is a matrix returns a matrix of correlation - coefficients for the columns of *X* - corrcoef(*x*, *y*) where *x* and *y* are vectors returns the matrix of - correlation coefficients for *x* and *y*. - - Numpy arrays can be real or complex. - - The correlation matrix is defined from the covariance matrix *C* - as - - .. math:: - - r_{ij} = \\frac{C_{ij}}{\\sqrt{C_{ii}C_{jj}}} - """ - warnings.warn("Use numpy.corrcoef", DeprecationWarning) - kw = dict(rowvar=False) - return np.corrcoef(*args, **kw) - - -def polyfit(*args, **kwargs): - u""" - polyfit(*x*, *y*, *N*) - - Do a best fit polynomial of order *N* of *y* to *x*. Return value - is a vector of polynomial coefficients [pk ... p1 p0]. Eg, for - *N* = 2:: - - p2*x0^2 + p1*x0 + p0 = y1 - p2*x1^2 + p1*x1 + p0 = y1 - p2*x2^2 + p1*x2 + p0 = y2 - ..... - p2*xk^2 + p1*xk + p0 = yk - - - Method: if *X* is a the Vandermonde Matrix computed from *x* (see - `vandermonds - <http://mathworld.wolfram.com/VandermondeMatrix.html>`_), then the - polynomial least squares solution is given by the '*p*' in - - X*p = y - - where *X* is a (len(*x*) \N{MULTIPLICATION SIGN} *N* + 1) matrix, - *p* is a *N*+1 length vector, and *y* is a (len(*x*) - \N{MULTIPLICATION SIGN} 1) vector. - - This equation can be solved as - - .. math:: - - p = (X_t X)^-1 X_t y - - where :math:`X_t` is the transpose of *X* and -1 denotes the - inverse. Numerically, however, this is not a good method, so we - use :func:`numpy.linalg.lstsq`. - - For more info, see `least squares fitting - <http://mathworld.wolfram.com/LeastSquaresFittingPolynomial.html>`_, - but note that the *k*'s and *n*'s in the superscripts and - subscripts on that page. The linear algebra is correct, however. - - .. seealso:: - - :func:`polyval` - polyval function - """ - warnings.warn("use numpy.polyfit", DeprecationWarning) - return np.polyfit(*args, **kwargs) - - -def polyval(*args, **kwargs): - """ - *y* = polyval(*p*, *x*) - - *p* is a vector of polynomial coeffients and *y* is the polynomial - evaluated at *x*. - - Example code to remove a polynomial (quadratic) trend from y:: - - p = polyfit(x, y, 2) - trend = polyval(p, x) - resid = y - trend - - .. seealso:: - - :func:`polyfit` - polyfit function - """ - warnings.warn("use numpy.polyval", DeprecationWarning) - return np.polyval(*args, **kwargs) - -def vander(*args, **kwargs): - """ - *X* = vander(*x*, *N* = *None*) - - The Vandermonde matrix of vector *x*. The *i*-th column of *X* is the - the *i*-th power of *x*. *N* is the maximum power to compute; if *N* is - *None* it defaults to len(*x*). - """ - warnings.warn("Use numpy.vander()", DeprecationWarning) - return np.vander(*args, **kwargs) - - def donothing_callback(*args): pass @@ -826,24 +675,6 @@ #S = -1.0*np.sum(p*log(p)) return S -def hist(y, bins=10, normed=0): - """ - Return the histogram of *y* with *bins* equally sized bins. If - bins is an array, use those bins. Return value is (*n*, *x*) - where *n* is the count for each bin in *x*. - - If *normed* is *False*, return the counts in the first element of - the returned tuple. If *normed* is *True*, return the probability - density :math:`\\frac{n}{(len(y)\mathrm{dbin}}`. - - If *y* has rank > 1, it will be raveled. If *y* is masked, only the - unmasked values will be used. - - Credits: the Numeric 22 documentation - """ - warnings.warn("Use numpy.histogram()", DeprecationWarning) - return np.histogram(y, bins=bins, range=None, normed=normed) - def normpdf(x, *args): "Return the normal pdf evaluated at *x*; args provides *mu*, *sigma*" mu, sigma = args @@ -879,14 +710,7 @@ res, = np.nonzero(np.ravel(condition)) return res -def trapz(x, y): - """ - Trapezoidal integral of *y*(*x*). - """ - warnings.warn("Use numpy.trapz(y,x) instead of trapz(x,y)", DeprecationWarning) - return np.trapz(y, x) - def longest_contiguous_ones(x): """ Return the indices of the longest stretch of contiguous ones in *x*, @@ -1203,6 +1027,8 @@ *x* is a very long trajectory from a map, and *fprime* returns the derivative of *x*. + This function will be removed from matplotlib. + Returns : .. math:: @@ -1221,6 +1047,9 @@ It also seems that this function's name is badly misspelled. """ + + warnings.warn("This does not belong in matplotlib and will be removed", DeprecationWarning) # 2009/06/13 + return np.mean(np.log(np.absolute(fprime(x)))) class FIFOBuffer: @@ -1330,6 +1159,8 @@ Save the data in *X* to file *fname* using *fmt* string to convert the data to strings. + Deprecated. Use numpy.savetxt. + *fname* can be a filename or a file handle. If the filename ends in '.gz', the file is automatically saved in compressed gzip format. The :func:`load` function understands gzipped files @@ -1346,6 +1177,8 @@ for comma-separated values. """ + warnings.warn("use numpy.savetxt", DeprecationWarning) # 2009/06/13 + if cbook.is_string_like(fname): if fname.endswith('.gz'): import gzip @@ -1377,6 +1210,8 @@ """ Load ASCII data from *fname* into an array and return the array. + Deprecated: use numpy.loadtxt. + The data must be regular, same number of values in every row *fname* can be a filename or a file handle. Support for gzipped @@ -1429,6 +1264,8 @@ Exercises many of these options. """ + warnings.warn("use numpy.loadtxt", DeprecationWarning) # 2009/06/13 + if converters is None: converters = {} fh = cbook.to_filehandle(fname) X = [] @@ -1720,33 +1557,6 @@ return np.array(map(fn,*args)) -#from numpy import zeros_like -def zeros_like(a): - """ - Return an array of zeros of the shape and typecode of *a*. - """ - warnings.warn("Use numpy.zeros_like(a)", DeprecationWarning) - return np.zeros_like(a) - -#from numpy import sum as sum_flat -def sum_flat(a): - """ - Return the sum of all the elements of *a*, flattened out. - - It uses ``a.flat``, and if *a* is not contiguous, a call to - ``ravel(a)`` is made. - """ - warnings.warn("Use numpy.sum(a) or a.sum()", DeprecationWarning) - return np.sum(a) - -#from numpy import mean as mean_flat -def mean_flat(a): - """ - Return the mean of all the elements of *a*, flattened out. - """ - warnings.warn("Use numpy.mean(a) or a.mean()", DeprecationWarning) - return np.mean(a) - def rms_flat(a): """ Return the root mean square of all the elements of *a*, flattened out. @@ -1852,14 +1662,6 @@ return np.arange(npts)*delta+xini # end frange() -#import numpy.diag as diagonal_matrix -def diagonal_matrix(diag): - """ - Return square diagonal matrix whose non-zero elements are given by the - input array. - """ - warnings.warn("Use numpy.diag(d)", DeprecationWarning) - return np.diag(diag) def identity(n, rank=2, dtype='l', typecode=None): """ @@ -1962,73 +1764,11 @@ """ return np.prod(X.shape)==np.max(X.shape) -#from numpy import fromfunction as fromfunction_kw -def fromfunction_kw(function, dimensions, **kwargs): - """ - Drop-in replacement for :func:`numpy.fromfunction`. - - Allows passing keyword arguments to the desired function. - - Call it as (keywords are optional):: - - fromfunction_kw(MyFunction, dimensions, keywords) - - The function ``MyFunction`` is responsible for handling the - dictionary of keywords it will receive. - """ - warnings.warn("Use numpy.fromfunction()", DeprecationWarning) - return np.fromfunction(function, dimensions, **kwargs) - ### end fperez numutils code -def rem(x,y): - """ - Deprecated - see :func:`numpy.remainder` - """ - raise NotImplementedError('Deprecated - see numpy.remainder') - -def norm(x,y=2): - """ - Deprecated - see :func:`numpy.linalg.norm` - """ - raise NotImplementedError('Deprecated - see numpy.linalg.norm') - - -def orth(A): - """ - Deprecated - needs clean room implementation - """ - raise NotImplementedError('Deprecated - needs clean room implementation') - -def rank(x): - """ - Deprecated - see :func:`numpy.rank` - """ - raise NotImplementedError('Deprecated - see numpy.rank') - -def sqrtm(x): - """ - Deprecated - needs clean room implementation - """ - raise NotImplementedError('Deprecated - see scipy.linalg.sqrtm') - - -def mfuncC(f, x): - """ - Deprecated - """ - raise NotImplementedError('Deprecated - needs clean room implementation') - -def approx_real(x): - """ - Deprecated - needs clean room implementation - """ - raise NotImplementedError('Deprecated - needs clean room implementation') - #helpers for loading, saving, manipulating and viewing numpy record arrays - def safe_isnan(x): ':func:`numpy.isnan` for arbitrary types' if cbook.is_string_like(x): @@ -2047,15 +1787,6 @@ except TypeError: return False else: return b -def rec_append_field(rec, name, arr, dtype=None): - """ - Return a new record array with field name populated with data from - array *arr*. This function is Deprecated. Please use - :func:`rec_append_fields`. - """ - warnings.warn("use rec_append_fields", DeprecationWarning) - return rec_append_fields(rec, name, arr, dtype) - def rec_append_fields(rec, names, arrs, dtypes=None): """ Return a new record array with field names populated with data @@ -2114,7 +1845,7 @@ if cbook.is_string_like(names): names = names.split(',') - + arrays = [] for name in names: arrays.append(rec[name]) @@ -2745,7 +2476,7 @@ if fields is not None: r = rec_keep_fields(r, fields) - + if cbook.is_numlike(precision): precision = [precision]*len(r.dtype) Modified: trunk/matplotlib/lib/matplotlib/pylab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/pylab.py 2009-06-13 21:13:14 UTC (rev 7216) +++ trunk/matplotlib/lib/matplotlib/pylab.py 2009-06-14 01:32:20 UTC (rev 7217) @@ -150,12 +150,12 @@ _Statistics + amax - the maximum along dimension m + amin - the minimum along dimension m corrcoef - correlation coefficient cov - covariance matrix - amax - the maximum along dimension m mean - the mean along dimension m median - the median along dimension m - amin - the minimum along dimension m norm - the norm of vector x prod - the product along dimension m ptp - the max-min along dimension m @@ -185,12 +185,14 @@ _Other angle - the angle of a complex array - griddata - interpolate irregularly distributed data to a regular grid - load - load ASCII data into array + griddata - interpolate irregularly distributed data to a regular grid + load - Deprecated--please use loadtxt. + loadtxt - load ASCII data into array. polyfit - fit x, y to an n-th order polynomial polyval - evaluate an n-th order polynomial roots - the roots of the polynomial coefficients in p - save - save an array to an ASCII file + save - Deprecated--please use savetxt. + savetxt - save an array to an ASCII file. trapz - trapezoidal integration __end @@ -198,12 +200,9 @@ """ import sys, warnings -from cbook import flatten, is_string_like, exception_to_str, popd, \ +from cbook import flatten, is_string_like, exception_to_str, \ silent_list, iterable, dedent -import numpy as np -from numpy import ma - from matplotlib import mpl # pulls in most modules from matplotlib.dates import date2num, num2date,\ @@ -214,45 +213,38 @@ DayLocator, HourLocator, MinuteLocator, SecondLocator,\ rrule, MO, TU, WE, TH, FR, SA, SU, YEARLY, MONTHLY,\ WEEKLY, DAILY, HOURLY, MINUTELY, SECONDLY, relativedelta -import matplotlib.dates +import matplotlib.dates # Do we need this at all? + # bring all the symbols in so folks can import them from # pylab in one fell swoop -from matplotlib.mlab import window_hanning, window_none,\ - conv, detrend, detrend_mean, detrend_none, detrend_linear,\ - polyfit, polyval, entropy, normpdf, griddata,\ - levypdf, find, trapz, prepca, rem, norm, orth, rank,\ - sqrtm, prctile, center_matrix, rk4, exp_safe, amap,\ - sum_flat, mean_flat, rms_flat, l1norm, l2norm, norm, frange,\ - diagonal_matrix, base_repr, binary_repr, log2, ispower2,\ - bivariate_normal, load, save -from matplotlib.mlab import stineman_interp, slopes, \ - stineman_interp, inside_poly, poly_below, poly_between, \ +## We are still importing too many things from mlab; more cleanup is needed. + +from matplotlib.mlab import griddata, stineman_interp, slopes, \ + inside_poly, poly_below, poly_between, \ is_closed_polygon, path_length, distances_along_curve, vector_lengths -from numpy import * -from numpy.fft import * -from numpy.random import * -from numpy.linalg import * - -from matplotlib.mlab import window_hanning, window_none, conv, detrend, demean, \ +from matplotlib.mlab import window_hanning, window_none, detrend, demean, \ detrend_mean, detrend_none, detrend_linear, entropy, normpdf, levypdf, \ find, longest_contiguous_ones, longest_ones, prepca, prctile, prctile_rank, \ center_matrix, rk4, bivariate_normal, get_xyz_where, get_sparse_matrix, dist, \ dist_point_to_segment, segments_intersect, fftsurr, liaupunov, movavg, \ save, load, exp_safe, \ - amap, rms_flat, l1norm, l2norm, norm_flat, frange, diagonal_matrix, identity, \ - base_repr, binary_repr, log2, ispower2, fromfunction_kw, rem, norm, orth, rank, sqrtm,\ - mfuncC, approx_real, rec_append_field, rec_drop_fields, rec_join, csv2rec, rec2csv, isvector + amap, rms_flat, l1norm, l2norm, norm_flat, frange, identity, \ + base_repr, binary_repr, log2, ispower2, \ + rec_append_fields, rec_drop_fields, rec_join, csv2rec, rec2csv, isvector +from numpy import * +from numpy.fft import * +from numpy.random import * +from numpy.linalg import * - - - from matplotlib.pyplot import * # provide the recommended module abbrevs in the pylab namespace import matplotlib.pyplot as plt import numpy as np +import numpy.ma as ma + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jo...@us...> - 2009-06-14 05:38:12
|
Revision: 7218 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7218&view=rev Author: jouni Date: 2009-06-14 05:38:11 +0000 (Sun, 14 Jun 2009) Log Message: ----------- Extend backend_driver.py to support running only some test directories Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/tests/backend_driver.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-06-14 01:32:20 UTC (rev 7217) +++ trunk/matplotlib/CHANGELOG 2009-06-14 05:38:11 UTC (rev 7218) @@ -1,3 +1,6 @@ +2009-06-14 Add new command line options to backend_driver.py to support + running only some directories of tests - JKS + 2009-06-13 partial cleanup of mlab and its importation in pylab - EF 2009-06-13 Introduce a rotation_mode property for the Text artist. See Modified: trunk/matplotlib/examples/tests/backend_driver.py =================================================================== --- trunk/matplotlib/examples/tests/backend_driver.py 2009-06-14 01:32:20 UTC (rev 7217) +++ trunk/matplotlib/examples/tests/backend_driver.py 2009-06-14 05:38:11 UTC (rev 7218) @@ -3,30 +3,40 @@ This is used to drive many of the examples across the backends, for regression testing, and comparing backend efficiency. -The script takes one or more arguments specifying backends -to be tested, e.g. +You can specify the backends to be tested either via the --backends +switch, which takes a comma-separated list, or as separate arguments, +e.g. python backend_driver.py agg ps cairo.png cairo.ps -would test the agg and ps backends, and the cairo backend with -output to png and ps files. +would test the agg and ps backends, and the cairo backend with output +to png and ps files. If no arguments are given, a default list of +backends will be tested. -If no arguments are given, a default list of backends will be -tested. +Interspersed with the backend arguments can be switches for the Python +interpreter executing the tests. If entering such arguments causes an +option parsing error with the driver script, separate them from driver +switches with a --. """ from __future__ import division -import os, time, sys, glob - +import os, time, sys, glob, string +from optparse import OptionParser import matplotlib.rcsetup as rcsetup +from matplotlib.cbook import Bunch, dedent all_backends = list(rcsetup.all_backends) # to leave the original list alone all_backends.extend(['cairo.png', 'cairo.ps', 'cairo.pdf', 'cairo.svg']) -pylab_dir = os.path.join('..', 'pylab_examples') -pylab_files = [ +# actual physical directory for each dir +dirs = dict(pylab = os.path.join('..', 'pylab_examples'), + api = os.path.join('..', 'api'), + units = os.path.join('..', 'units'), + mplot3d = os.path.join('..', 'mplot3d')) - +# files in each dir +files = dict() +files['pylab'] = [ 'accented_text.py', 'alignment_test.py', 'annotation_demo.py', @@ -196,8 +206,7 @@ ] -api_dir = os.path.join('..', 'api') -api_files = [ +files['api'] = [ 'agg_oo.py', 'barchart_demo.py', 'bbox_intersect.py', @@ -228,8 +237,7 @@ 'watermark_text.py', ] -units_dir = os.path.join('..', 'units') -units_files = [ +files['units'] = [ 'annotate_with_units.py', #'artist_tests.py', # broken, fixme 'bar_demo2.py', @@ -241,8 +249,7 @@ ] -mplot3d_dir = os.path.join('..', 'mplot3d') -mplot3d_files = [ +files['mplot3d'] = [ '2dcollections3d_demo.py', 'bars3d_demo.py', 'contour3d_demo.py', @@ -263,8 +270,8 @@ # examples that generate multiple figures excluded = { - pylab_dir : ['__init__.py', 'toggle_images.py',], - units_dir : ['__init__.py', 'date_support.py',], + 'pylab' : ['__init__.py', 'toggle_images.py',], + 'units' : ['__init__.py', 'date_support.py',], } def report_missing(dir, flist): @@ -278,24 +285,16 @@ flist = set(flist) missing = list(pyfiles-flist-exclude) missing.sort() - print '%s files not tested: %s'%(dir, ', '.join(missing)) + if missing: + print '%s files not tested: %s'%(dir, ', '.join(missing)) +def report_all_missing(directories): + for f in directories: + report_missing(dirs[f], files[f]) -report_missing(pylab_dir, pylab_files) -report_missing(api_dir, api_files) -report_missing(units_dir, units_files) -report_missing(mplot3d_dir, mplot3d_files) -files = ( - [os.path.join(api_dir, fname) for fname in api_files] + - [os.path.join(pylab_dir, fname) for fname in pylab_files] + - [os.path.join(units_dir, fname) for fname in units_files] + - [os.path.join(mplot3d_dir, fname) for fname in mplot3d_files] - ) - # tests known to fail on a given backend - failbackend = dict( svg = ('tex_demo.py', ), agg = ('hyperlinks.py', ), @@ -317,7 +316,7 @@ def run(arglist): os.system(' '.join(arglist)) -def drive(backend, python=['python'], switches = []): +def drive(backend, directories, python=['python'], switches = []): exclude = failbackend.get(backend, []) # Clear the destination directory for the examples @@ -329,8 +328,12 @@ else: os.mkdir(backend) failures = [] - for fullpath in files: + testcases = [os.path.join(dirs[d], fname) + for d in directories + for fname in files[d]] + + for fullpath in testcases: print ('\tdriving %-40s' % (fullpath)), sys.stdout.flush() @@ -376,21 +379,64 @@ tmpfile.close() start_time = time.time() program = [x % {'name': basename} for x in python] - ret = run(program + [tmpfile_name, switchstring]) + ret = run(program + [tmpfile_name] + switches) end_time = time.time() print (end_time - start_time), ret - #os.system('%s %s %s' % (python, tmpfile_name, switchstring)) + #os.system('%s %s %s' % (python, tmpfile_name, ' '.join(switches))) os.remove(tmpfile_name) if ret: failures.append(fullpath) return failures +def parse_options(): + doc = __doc__.split('\n\n') + op = OptionParser(description=doc[0].strip(), + usage='%prog [options] [--] [backends and switches]', + epilog='\n'.join(doc[1:])) + op.disable_interspersed_args() + op.set_defaults(dirs='pylab,api,units,mplot3d', + clean=False, coverage=False, valgrind=False) + op.add_option('-d', '--dirs', '--directories', type='string', + dest='dirs', help=dedent(''' + Run only the tests in these directories; comma-separated list of + one or more of: pylab (or pylab_examples), api, units, mplot3d''')) + op.add_option('-b', '--backends', type='string', dest='backends', + help=dedent(''' + Run tests only for these backends; comma-separated list of + one or more of: agg, ps, svg, pdf, template, cairo, + cairo.png, cairo.ps, cairo.pdf, cairo.svg. Default is everything + except cairo.''')) + op.add_option('--clean', action='store_true', dest='clean', + help='Remove result directories, run no tests') + op.add_option('-c', '--coverage', action='store_true', dest='coverage', + help='Run in coverage.py') + op.add_option('-v', '--valgrind', action='store_true', dest='valgrind', + help='Run in valgrind') + options, args = op.parse_args() + switches = [x for x in args if x.startswith('--')] + backends = [x.lower() for x in args if not x.startswith('--')] + if options.backends: + backends += map(string.lower, options.backends.split(',')) + + result = Bunch( + dirs = options.dirs.split(','), + backends = backends or ['agg', 'ps', 'svg', 'pdf', 'template'], + clean = options.clean, + coverage = options.coverage, + valgrind = options.valgrind, + switches = switches) + if 'pylab_examples' in result.dirs: + result.dirs[result.dirs.index('pylab_examples')] = 'pylab' + #print result + return result + if __name__ == '__main__': times = {} failures = {} - default_backends = ['agg', 'ps', 'svg', 'pdf', 'template'] - if len(sys.argv)==2 and sys.argv[1]=='--clean': + options = parse_options() + + if options.clean: localdirs = [d for d in glob.glob('*') if os.path.isdir(d)] all_backends_set = set(all_backends) for d in localdirs: @@ -405,38 +451,31 @@ print 'all clean...' raise SystemExit - if '--coverage' in sys.argv: + if options.coverage: python = ['coverage.py', '-x'] - sys.argv.remove('--coverage') - elif '--valgrind' in sys.argv: + elif options.valgrind: python = ['valgrind', '--tool=memcheck', '--leak-check=yes', '--log-file=%(name)s', 'python'] - sys.argv.remove('--valgrind') elif sys.platform == 'win32': python = [r'c:\Python24\python.exe'] else: python = ['python'] - backends = [] - switches = [] - if sys.argv[1:]: - backends = [b.lower() for b in sys.argv[1:] if b.lower() in all_backends] - switches = [s for s in sys.argv[1:] if s.startswith('--')] - if not backends: - backends = default_backends - for backend in backends: - switchstring = ' '.join(switches) - print 'testing %s %s' % (backend, switchstring) + + report_all_missing(options.dirs) + for backend in options.backends: + print 'testing %s %s' % (backend, ' '.join(options.switches)) t0 = time.time() - failures[backend] = drive(backend, python, switches) + failures[backend] = \ + drive(backend, options.dirs, python, options.switches) t1 = time.time() times[backend] = (t1-t0)/60.0 # print times for backend, elapsed in times.items(): - print 'Backend %s took %1.2f minutes to complete' % ( backend, elapsed) + print 'Backend %s took %1.2f minutes to complete' % (backend, elapsed) failed = failures[backend] if failed: print ' Failures: ', failed - if 'Template' in times: + if 'template' in times: print '\ttemplate ratio %1.3f, template residual %1.3f' % ( - elapsed/times['Template'], elapsed-times['Template']) + elapsed/times['template'], elapsed-times['template']) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2009-06-19 04:49:40
|
Revision: 7228 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7228&view=rev Author: leejjoon Date: 2009-06-19 04:49:38 +0000 (Fri, 19 Jun 2009) Log Message: ----------- Merged revisions 7227 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint This is duplicate fix of r7226 in the trunk. ........ r7227 | leejjoon | 2009-06-19 00:39:24 -0400 (Fri, 19 Jun 2009) | 1 line fix sf bug 2806283 (patch by Joonas Paalasmaa) ........ Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7211 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7227 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227 Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211 + /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211 + /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211 + /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2009-06-21 18:53:51
|
Revision: 7230 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7230&view=rev Author: leejjoon Date: 2009-06-21 18:53:49 +0000 (Sun, 21 Jun 2009) Log Message: ----------- Merged revisions 7229 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r7229 | leejjoon | 2009-06-21 14:44:53 -0400 (Sun, 21 Jun 2009) | 2 lines fixed axes.scatter bug that circular symbol style is ignored ........ Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py Property Changed: ---------------- trunk/matplotlib/ Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7227 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7229 Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2009-06-21 18:44:53 UTC (rev 7229) +++ trunk/matplotlib/lib/matplotlib/axes.py 2009-06-21 18:53:49 UTC (rev 7230) @@ -5287,7 +5287,7 @@ syms = { # a dict from symbol to (numsides, angle) 's' : (4,math.pi/4.0,0), # square - 'o' : (20,3,0), # circle + 'o' : (0,0,3), # circle '^' : (3,0,0), # triangle up '>' : (3,math.pi/2.0,0), # triangle right 'v' : (3,math.pi,0), # triangle down @@ -5375,7 +5375,7 @@ numsides, rotation = marker[0], marker[2] sym = True - if marker[1] in (1,2): + if marker[1] in (1,2,3): symstyle = marker[1] else: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2009-06-24 05:47:10
|
Revision: 7233 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7233&view=rev Author: leejjoon Date: 2009-06-24 05:46:08 +0000 (Wed, 24 Jun 2009) Log Message: ----------- axes_grid: floating_axis support added Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/axes_grid/scatter_hist.py trunk/matplotlib/examples/axes_grid/simple_axisline.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_finder.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_helper_curvelinear.py Added Paths: ----------- trunk/matplotlib/examples/axes_grid/demo_floating_axis.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-06-23 12:47:49 UTC (rev 7232) +++ trunk/matplotlib/CHANGELOG 2009-06-24 05:46:08 UTC (rev 7233) @@ -1,3 +1,5 @@ +2009-06-24 axes_grid: floating axis support added. - JJL + 2009-06-14 Add new command line options to backend_driver.py to support running only some directories of tests - JKS Added: trunk/matplotlib/examples/axes_grid/demo_floating_axis.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_floating_axis.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/demo_floating_axis.py 2009-06-24 05:46:08 UTC (rev 7233) @@ -0,0 +1,77 @@ +""" +A floating axes for curvelinear grid. +. +""" + + +def curvelinear_test2(fig): + """ + polar projection, but in a rectangular box. + """ + import numpy as np + import mpl_toolkits.axes_grid.angle_helper as angle_helper + from matplotlib.projections import PolarAxes + from matplotlib.transforms import Affine2D + + from mpl_toolkits.axes_grid.parasite_axes import SubplotHost + + from mpl_toolkits.axes_grid.grid_helper_curvelinear import GridHelperCurveLinear + + # see demo_curvelinear_grid.py for details + tr = Affine2D().scale(np.pi/180., 1.) + PolarAxes.PolarTransform() + + extreme_finder = angle_helper.ExtremeFinderCycle(20, 20, + lon_cycle = 360, + lat_cycle = None, + lon_minmax = None, + lat_minmax = (0, np.inf), + ) + + grid_locator1 = angle_helper.LocatorDMS(12) + + tick_formatter1 = angle_helper.FormatterDMS() + + grid_helper = GridHelperCurveLinear(tr, + extreme_finder=extreme_finder, + grid_locator1=grid_locator1, + tick_formatter1=tick_formatter1 + ) + + + ax1 = SubplotHost(fig, 1, 1, 1, grid_helper=grid_helper) + + # make ticklabels of right and top axis visible. + for axis in ax1.axis.values(): + axis.toggle(all=False) + + fig.add_subplot(ax1) + + # Now creates floating axis + + grid_helper = ax1.get_grid_helper() + # floating axis whose first coordinate (theta) is fixed at 60 + ax1.axis["lat"] = axis = grid_helper.new_floating_axis(0, 60, axes=ax1) + axis.label.set_text(r"$\theta = 60^{\circ}$") + axis.label.set_visible(True) + + # floating axis whose second coordinate (r) is fixed at 6 + ax1.axis["lon"] = axis = grid_helper.new_floating_axis(1, 6, axes=ax1) + axis.label.set_text(r"$r = 6$") + + ax1.set_aspect(1.) + ax1.set_xlim(-5, 12) + ax1.set_ylim(-5, 10) + + ax1.grid(True) + +if __name__ == "__main__": + import matplotlib.pyplot as plt + fig = plt.figure(1, figsize=(5, 5)) + fig.clf() + + curvelinear_test2(fig) + + plt.draw() + plt.show() + + Modified: trunk/matplotlib/examples/axes_grid/scatter_hist.py =================================================================== --- trunk/matplotlib/examples/axes_grid/scatter_hist.py 2009-06-23 12:47:49 UTC (rev 7232) +++ trunk/matplotlib/examples/axes_grid/scatter_hist.py 2009-06-24 05:46:08 UTC (rev 7233) @@ -56,5 +56,5 @@ axHisty.set_xticks([0, 50, 100]) plt.draw() -#plt.show() -plt.savefig("a.pdf") +plt.show() +#plt.savefig("a.pdf") Modified: trunk/matplotlib/examples/axes_grid/simple_axisline.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axisline.py 2009-06-23 12:47:49 UTC (rev 7232) +++ trunk/matplotlib/examples/axes_grid/simple_axisline.py 2009-06-24 05:46:08 UTC (rev 7233) @@ -29,7 +29,8 @@ new_axisline = ax.get_grid_helper().new_fixed_axis ax.axis["right2"] = new_axisline(loc="right", - offset=offset) + offset=offset, + axes=ax) ax.axis["right2"].label.set_text("Label Y2") ax.plot([-2,3,2]) Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py 2009-06-23 12:47:49 UTC (rev 7232) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py 2009-06-24 05:46:08 UTC (rev 7233) @@ -143,7 +143,7 @@ -class AxesGrid(object): +class Grid(object): """ A class that creates a grid of Axes. In matplotlib, the axes location (and size) is specified in the normalized figure @@ -161,6 +161,269 @@ axes_pad = 0.02, add_all=True, share_all=False, + share_x=True, + share_y=True, + #aspect=True, + label_mode="L", + axes_class=None, + ): + """ + Build an :class:`AxesGrid` instance with a grid nrows*ncols + :class:`~matplotlib.axes.Axes` in + :class:`~matplotlib.figure.Figure` *fig* with + *rect=[left, bottom, width, height]* (in + :class:`~matplotlib.figure.Figure` coordinates) or + the subplot position code (e.g., "121"). + + Optional keyword arguments: + + ================ ======== ========================================= + Keyword Default Description + ================ ======== ========================================= + direction "row" [ "row" | "column" ] + axes_pad 0.02 float| pad betweein axes given in inches + add_all True [ True | False ] + share_all False [ True | False ] + aspect True [ True | False ] + label_mode "L" [ "L" | "1" | "all" ] + axes_class None a type object which must be a subclass + of :class:`~matplotlib.axes.Axes` + ================ ======== ========================================= + """ + self._nrows, self._ncols = nrows_ncols + + if ngrids is None: + ngrids = self._nrows * self._ncols + else: + if (ngrids > self._nrows * self._ncols) or (ngrids <= 0): + raise Exception("") + + self.ngrids = ngrids + + self._init_axes_pad(axes_pad) + + if direction not in ["column", "row"]: + raise Exception("") + + self._direction = direction + + + if axes_class is None: + axes_class = LocatableAxes + axes_class_args = {} + else: + if isinstance(axes_class, maxes.Axes): + axes_class_args = {} + else: + axes_class, axes_class_args = axes_class + + self.axes_all = [] + self.axes_column = [[] for i in range(self._ncols)] + self.axes_row = [[] for i in range(self._nrows)] + + + h = [] + v = [] + if cbook.is_string_like(rect) or cbook.is_numlike(rect): + self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v, + aspect=False) + elif len(rect) == 3: + kw = dict(horizontal=h, vertical=v, aspect=False) + self._divider = SubplotDivider(fig, *rect, **kw) + elif len(rect) == 4: + self._divider = Divider(fig, rect, horizontal=h, vertical=v, + aspect=False) + else: + raise Exception("") + + + rect = self._divider.get_position() + + # reference axes + self._column_refax = [None for i in range(self._ncols)] + self._row_refax = [None for i in range(self._nrows)] + self._refax = None + + for i in range(self.ngrids): + + col, row = self._get_col_row(i) + + if share_all: + sharex = self._refax + sharey = self._refax + else: + if share_x: + sharex = self._column_refax[col] + else: + sharex = None + + if share_y: + sharey = self._row_refax[row] + else: + sharey = None + + ax = axes_class(fig, rect, sharex=sharex, sharey=sharey, + **axes_class_args) + + if share_all: + if self._refax is None: + self._refax = ax + else: + if sharex is None: + self._column_refax[col] = ax + if sharey is None: + self._row_refax[row] = ax + + self.axes_all.append(ax) + self.axes_column[col].append(ax) + self.axes_row[row].append(ax) + + self.axes_llc = self.axes_column[0][-1] + + self._update_locators() + + if add_all: + for ax in self.axes_all: + fig.add_axes(ax) + + self.set_label_mode(label_mode) + + + def _init_axes_pad(self, axes_pad): + self._axes_pad = axes_pad + + self._horiz_pad_size = Size.Fixed(axes_pad) + self._vert_pad_size = Size.Fixed(axes_pad) + + + def _update_locators(self): + + h = [] + + h_ax_pos = [] + h_cb_pos = [] + + for ax in self._column_refax: + #if h: h.append(Size.Fixed(self._axes_pad)) + if h: h.append(self._horiz_pad_size) + + h_ax_pos.append(len(h)) + + sz = Size.Scaled(1) + h.append(sz) + + v = [] + + v_ax_pos = [] + v_cb_pos = [] + for ax in self._row_refax[::-1]: + #if v: v.append(Size.Fixed(self._axes_pad)) + if v: v.append(self._vert_pad_size) + + v_ax_pos.append(len(v)) + sz = Size.Scaled(1) + v.append(sz) + + + for i in range(self.ngrids): + col, row = self._get_col_row(i) + locator = self._divider.new_locator(nx=h_ax_pos[col], + ny=v_ax_pos[self._nrows -1 - row]) + self.axes_all[i].set_axes_locator(locator) + + self._divider.set_horizontal(h) + self._divider.set_vertical(v) + + + + def _get_col_row(self, n): + if self._direction == "column": + col, row = divmod(n, self._nrows) + else: + row, col = divmod(n, self._ncols) + + return col, row + + + def __getitem__(self, i): + return self.axes_all[i] + + + def get_geometry(self): + """ + get geometry of the grid. Returns a tuple of two integer, + representing number of rows and number of columns. + """ + return self._nrows, self._ncols + + def set_axes_pad(self, axes_pad): + "set axes_pad" + self._axes_pad = axes_pad + + self._horiz_pad_size.fixed_size = axes_pad + self._vert_pad_size.fixed_size = axes_pad + + + def get_axes_pad(self): + "get axes_pad" + return self._axes_pad + + def set_aspect(self, aspect): + "set aspect" + self._divider.set_aspect(aspect) + + def get_aspect(self): + "get aspect" + return self._divider.get_aspect() + + def set_label_mode(self, mode): + "set label_mode" + if mode == "all": + for ax in self.axes_all: + _tick_only(ax, False, False) + elif mode == "L": + # left-most axes + for ax in self.axes_column[0][:-1]: + _tick_only(ax, bottom_on=True, left_on=False) + # lower-left axes + ax = self.axes_column[0][-1] + _tick_only(ax, bottom_on=False, left_on=False) + + for col in self.axes_column[1:]: + # axes with no labels + for ax in col[:-1]: + _tick_only(ax, bottom_on=True, left_on=True) + + # bottom + ax = col[-1] + _tick_only(ax, bottom_on=False, left_on=True) + + elif mode == "1": + for ax in self.axes_all: + _tick_only(ax, bottom_on=True, left_on=True) + + ax = self.axes_llc + _tick_only(ax, bottom_on=False, left_on=False) + + +class AxesGrid(Grid): + """ + A class that creates a grid of Axes. In matplotlib, the axes + location (and size) is specified in the normalized figure + coordinates. This may not be ideal for images that needs to be + displayed with a given aspect ratio. For example, displaying + images of a same size with some fixed padding between them cannot + be easily done in matplotlib. AxesGrid is used in such case. + """ + + def __init__(self, fig, + rect, + nrows_ncols, + ngrids = None, + direction="row", + axes_pad = 0.02, + add_all=True, + share_all=False, aspect=True, label_mode="L", cbar_mode=None, @@ -217,6 +480,8 @@ self._colorbar_size = cbar_size + self._init_axes_pad(axes_pad) + if direction not in ["column", "row"]: raise Exception("") @@ -312,7 +577,7 @@ h_ax_pos = [] h_cb_pos = [] for ax in self._column_refax: - if h: h.append(Size.Fixed(self._axes_pad)) + if h: h.append(self._horiz_pad_size) #Size.Fixed(self._axes_pad)) h_ax_pos.append(len(h)) @@ -333,7 +598,8 @@ v_ax_pos = [] v_cb_pos = [] for ax in self._row_refax[::-1]: - if v: v.append(Size.Fixed(self._axes_pad)) + if v: v.append(self._horiz_pad_size) #Size.Fixed(self._axes_pad)) + v_ax_pos.append(len(v)) if ax: sz = Size.AxesY(ax) @@ -396,75 +662,27 @@ - def _get_col_row(self, n): - if self._direction == "column": - col, row = divmod(n, self._nrows) - else: - row, col = divmod(n, self._ncols) - return col, row +#if __name__ == "__main__": +if 0: + F = plt.figure(1, (7, 6)) + F.clf() - def __getitem__(self, i): - return self.axes_all[i] + F.subplots_adjust(left=0.15, right=0.9) + grid = Grid(F, 111, # similar to subplot(111) + nrows_ncols = (2, 2), + direction="row", + axes_pad = 0.05, + add_all=True, + label_mode = "1", + ) - def get_geometry(self): - """ - get geometry of the grid. Returns a tuple of two integer, - representing number of rows and number of columns. - """ - return self._nrows, self._ncols - def set_axes_pad(self, axes_pad): - "set axes_pad" - self._axes_pad = axes_pad - def get_axes_pad(self): - "get axes_pad" - return self._axes_pad - - def set_aspect(self, aspect): - "set aspect" - self._divider.set_aspect(aspect) - - def get_aspect(self): - "get aspect" - return self._divider.get_aspect() - - def set_label_mode(self, mode): - "set label_mode" - if mode == "all": - for ax in self.axes_all: - _tick_only(ax, False, False) - elif mode == "L": - # left-most axes - for ax in self.axes_column[0][:-1]: - _tick_only(ax, bottom_on=True, left_on=False) - # lower-left axes - ax = self.axes_column[0][-1] - _tick_only(ax, bottom_on=False, left_on=False) - - for col in self.axes_column[1:]: - # axes with no labels - for ax in col[:-1]: - _tick_only(ax, bottom_on=True, left_on=True) - - # bottom - ax = col[-1] - _tick_only(ax, bottom_on=False, left_on=True) - - elif mode == "1": - for ax in self.axes_all: - _tick_only(ax, bottom_on=True, left_on=True) - - ax = self.axes_llc - _tick_only(ax, bottom_on=False, left_on=False) - - - - if __name__ == "__main__": +#if 0: from axes_divider import get_demo_image F = plt.figure(1, (9, 3.5)) F.clf() Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py 2009-06-23 12:47:49 UTC (rev 7232) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py 2009-06-24 05:46:08 UTC (rev 7233) @@ -21,13 +21,14 @@ class Fixed(_Base): "Simple fixed size with absolute part = *fixed_size* and relative part = 0" def __init__(self, fixed_size): - self._fixed_size = fixed_size + self.fixed_size = fixed_size def get_size(self, renderer): rel_size = 0. - abs_size = self._fixed_size + abs_size = self.fixed_size return rel_size, abs_size + class Scaled(_Base): "Simple scaled(?) size with absolute part = 0 and relative part = *scalable_size*" def __init__(self, scalable_size): Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py 2009-06-23 12:47:49 UTC (rev 7232) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py 2009-06-24 05:46:08 UTC (rev 7233) @@ -54,6 +54,9 @@ from matplotlib.collections import LineCollection from matplotlib import rcParams + +from matplotlib.artist import allow_rasterization + import warnings import numpy as np @@ -127,7 +130,7 @@ will be axes attribute of the caller artist. - # LINE + # LINE (spinal line?) def get_line(self, axes): # path : Path @@ -168,24 +171,27 @@ """ + class _Base(object): - + """ + Base class for axis helper. + """ def __init__(self, label_direction): + """ + label direction must be one of + ["left", "right", "bottom", "top", + "curved"] + """ self.label_direction = label_direction - #def update(self): - # raise UnimplementedException("update method not implemented") - def update_lim(self, axes): pass _label_angles = dict(left=90, right=90, bottom=0, top=0) _ticklabel_angles = dict(left=0, right=0, bottom=0, top=0) - def _get_label_offset_transform(self, pad_points, fontprops, renderer, - bboxes=None, - #trans=None - ): + def _get_label_offset_transform(self, pad_points, fontprops, + renderer, bboxes=None): """ Returns (offset-transform, vertical-alignment, horiz-alignment) @@ -200,6 +206,7 @@ fontprops : font properties for label renderer : renderer bboxes=None : list of bboxes (window extents) of the tick labels. + This only make sense for axis label. all the above parameters are used to estimate the offset. @@ -223,44 +230,44 @@ tr = Affine2D() if self.label_direction == "left": tr.translate(-(pad_pixels+w), 0.) - #trans = trans + tr return tr, "center", "right" elif self.label_direction == "right": tr.translate(+(pad_pixels+w), 0.) - #trans = trans + tr return tr, "center", "left" elif self.label_direction == "bottom": tr.translate(0, -(pad_pixels+font_size_pixels+h)) - #trans = trans + tr return tr, "baseline", "center" elif self.label_direction == "top": tr.translate(0, +(pad_pixels+h)) - #trans = trans + tr return tr, "baseline", "center" + elif self.label_direction == "curved": + #tr.translate(0, +(pad_pixels+h)) + + return tr, "baseline", "center" + else: - raise ValueError("") + raise ValueError("Unknown label direction : %s" \ + % (self.label_direction,)) - def get_label_offset_transform(self, - axes, + def get_label_offset_transform(self, axes, pad_points, fontprops, renderer, bboxes, - #trans=None ): + """ + offset transform for axis label. + """ - tr, va, ha = self._get_label_offset_transform(pad_points, fontprops, - renderer, - bboxes, - #trans - ) + tr, va, ha = self._get_label_offset_transform( \ + pad_points, fontprops, renderer, bboxes) a = self._label_angles[self.label_direction] return tr, va, ha, a @@ -270,11 +277,12 @@ pad_points, fontprops, renderer, ): + """ + offset transform for ticklabels. + """ - tr, va, ha = self._get_label_offset_transform(pad_points, fontprops, - renderer, - None, - ) + tr, va, ha = self._get_label_offset_transform( \ + pad_points, fontprops, renderer, None) a = self._ticklabel_angles[self.label_direction] return tr, va, ha, a @@ -282,6 +290,9 @@ class Fixed(_Base): + """ + Helper class for a fixed (in the axes coordinate) axis. + """ _default_passthru_pt = dict(left=(0, 0), right=(1, 0), @@ -289,8 +300,8 @@ top=(0, 1)) def __init__(self, - loc, nth_coord=None, - passingthrough_point=None, label_direction=None): + loc, + label_direction=None): """ nth_coord = along which coordinate value varies in 2d, nth_coord = 0 -> x axis, nth_coord = 1 -> y axis @@ -298,23 +309,21 @@ if loc not in ["left", "right", "bottom", "top"]: raise ValueError("%s" % loc) - if nth_coord is None: - if loc in ["left", "right"]: - nth_coord = 1 - elif loc in ["bottom", "top"]: - nth_coord = 0 + #if nth_coord is None: + if loc in ["left", "right"]: + nth_coord = 1 + elif loc in ["bottom", "top"]: + nth_coord = 0 self.nth_coord = nth_coord super(AxisArtistHelper.Fixed, self).__init__(loc) - if passingthrough_point is None: - passingthrough_point = self._default_passthru_pt[loc] + self.passthru_pt = self._default_passthru_pt[loc] if label_direction is None: label_direction = loc - self.passthru_pt = passingthrough_point _verts = np.array([[0., 0.], [1., 1.]]) @@ -336,7 +345,7 @@ def get_line_transform(self, axes): return axes.transAxes - # LABLE + # LABEL def get_label_pos(self, axes): """ @@ -358,11 +367,9 @@ tr, va, ha = self._get_label_offset_transform( \ pad_points, fontprops, renderer, bboxes, - #trans ) a = self._label_angles[self.label_direction] - #tr = axes.transAxes + tr return tr, va, ha, a @@ -380,14 +387,12 @@ class Floating(_Base): def __init__(self, nth_coord, - passingthrough_point, label_direction, transform): + value, label_direction): self.nth_coord = nth_coord - self.passingthrough_point = passingthrough_point + self._value = value - self.transform = transform - super(AxisArtistHelper.Floating, self).__init__(label_direction) @@ -396,72 +401,25 @@ return self.nth_coord def get_line(self, axes): - _verts = np.array([[0., 0.], - [1., 1.]]) + raise RuntimeError("get_line method should be defined by the derived class") - fixed_coord = 1-self.nth_coord - trans_passingthrough_point = self.transform + axes.transAxes.inverted() - p = trans_passingthrough_point.transform_point(self.passingthrough_point) - _verts[:,fixed_coord] = p[fixed_coord] - return Path(_verts) - def get_line_transform(self, axes): - return axes.transAxes - def get_label_pos(self, axes): - _verts = [0.5, 0.5] - - fixed_coord = 1-self.nth_coord - trans_passingthrough_point = self.transform + axes.transAxes.inverted() - p = trans_passingthrough_point.transform_point(self.passingthrough_point) - _verts[fixed_coord] = p[fixed_coord] - if not (0. <= _verts[fixed_coord] <= 1.): - return None, None - else: - return _verts, axes.transAxes - - def get_label_transform(self, axes, - pad_points, fontprops, renderer, - bboxes, - ): - - tr, va, ha = self._get_label_offset_transform(pad_points, fontprops, - renderer, - bboxes, - #trans - ) - - a = self._label_angles[self.label_direction] - tr = axes.transAxes + tr - #tr = axes.transAxes + tr - - return tr, va, ha, a - - - - def get_tick_transform(self, axes): - return self.transform - - - - - class AxisArtistHelperRectlinear: class Fixed(AxisArtistHelper.Fixed): def __init__(self, - axes, loc, nth_coord=None, - passingthrough_point=None, label_direction=None): + axes, loc, #nth_coord=None, + label_direction=None): """ nth_coord = along which coordinate value varies in 2d, nth_coord = 0 -> x axis, nth_coord = 1 -> y axis """ super(AxisArtistHelperRectlinear.Fixed, self).__init__( \ - loc, nth_coord, - passingthrough_point, label_direction) + loc, label_direction) self.axis = [axes.xaxis, axes.yaxis][self.nth_coord] @@ -498,7 +456,7 @@ # check if the tick point is inside axes c2 = tr2ax.transform_point(c) - delta=0.001 + delta=0.00001 if 0. -delta<= c2[self.nth_coord] <= 1.+delta: yield c, angle, l @@ -508,14 +466,60 @@ class Floating(AxisArtistHelper.Floating): def __init__(self, axes, nth_coord, - passingthrough_point, label_direction, transform): + passingthrough_point, label_direction): super(AxisArtistHelperRectlinear.Floating, self).__init__( \ - nth_coord, passingthrough_point, label_direction, transform) + nth_coord, passingthrough_point, label_direction) self.axis = [axes.xaxis, axes.yaxis][self.nth_coord] + def get_line(self, axes): + _verts = np.array([[0., 0.], + [1., 1.]]) + + fixed_coord = 1-self.nth_coord + trans_passingthrough_point = axes.transData + axes.transAxes.inverted() + p = trans_passingthrough_point.transform_point([self._value, + self._value]) + _verts[:,fixed_coord] = p[fixed_coord] + + return Path(_verts) + + def get_line_transform(self, axes): + return axes.transAxes + + def get_label_pos(self, axes): + _verts = [0.5, 0.5] + + fixed_coord = 1-self.nth_coord + trans_passingthrough_point = axes.transData + axes.transAxes.inverted() + p = trans_passingthrough_point.transform_point([self._value, + self._value]) + _verts[fixed_coord] = p[fixed_coord] + if not (0. <= _verts[fixed_coord] <= 1.): + return None, None + else: + return _verts, axes.transAxes + + def get_label_transform(self, axes, + pad_points, fontprops, renderer, + bboxes, + ): + + tr, va, ha = self._get_label_offset_transform(pad_points, fontprops, + renderer, bboxes) + + a = self._label_angles[self.label_direction] + tr = axes.transAxes + tr + + return tr, va, ha, a + + + def get_tick_transform(self, axes): + return axes.transData + + def get_tick_iterators(self, axes): """tick_loc, tick_angle, tick_label""" @@ -531,12 +535,12 @@ minor.formatter.set_locs(minorLocs) minorLabels = [minor.formatter(val, i) for i, val in enumerate(minorLocs)] - tr2ax = self.transform + axes.transAxes.inverted() + tr2ax = axes.transData + axes.transAxes.inverted() def _f(locs, labels): for x, l in zip(locs, labels): - c = list(self.passingthrough_point) # copy + c = [self._value, self._value] c[self.nth_coord] = x c1, c2 = tr2ax.transform_point(c) if 0. <= c1 <= 1. and 0. <= c2 <= 1.: @@ -573,7 +577,10 @@ def invalidate(self): self._force_update = True + def valid(self): + return not self._force_update + def get_gridlines(self): return [] @@ -587,26 +594,10 @@ super(GridHelperRectlinear, self).__init__() self.axes = axes - #def set_axes(self, axes): - # self.axes = axes - def _get_axisline_helper_deprecated(self, nth_coord, loc, - passingthrough_point, transform=None): - if transform is None or transform is self.axes.transAxes: - return AxisArtistHelper.Fixed(self.axes, loc, - nth_coord, passingthrough_point) - else: - label_direction = loc - return AxisArtistHelper.Floating(self.axes, - nth_coord, passingthrough_point, - label_direction, - transform) - - def new_fixed_axis(self, loc, - nth_coord=None, passthrough_point=None, - #transform=None, + nth_coord=None, tick_direction="in", label_direction=None, offset=None, @@ -617,65 +608,38 @@ warnings.warn("'new_fixed_axis' explicitly requires the axes keyword.") axes = self.axes - _helper = AxisArtistHelperRectlinear.Fixed(axes, loc, - nth_coord, - passthrough_point) + _helper = AxisArtistHelperRectlinear.Fixed(axes, loc, nth_coord) - axisline = AxisArtist(axes, _helper, - #tick_direction="in", - offset=offset, - ) + axisline = AxisArtist(axes, _helper, offset=offset) return axisline - def new_floating_axis(self, nth_coord=None, passthrough_point=None, - transform=None, + def new_floating_axis(self, nth_coord, value, tick_direction="in", label_direction=None, - axes=None, - ): + axes=None, + ): if axes is None: warnings.warn("'new_floating_axis' explicitly requires the axes keyword.") axes = self.axes + passthrough_point = (value, value) + transform = axes.transData + _helper = AxisArtistHelperRectlinear.Floating( \ - axes, - nth_coord, passthrough_point, - label_direction, - transform) + axes, nth_coord, value, label_direction) - axisline = AxisArtist(axes, _helper, - #tick_direction="in", - ) + axisline = AxisArtist(axes, _helper) + axisline.line.set_clip_on(True) + axisline.line.set_clip_box(axisline.axes.bbox) return axisline - def new_axisline_deprecated(self, loc, - nth_coord=None, passthrough_point=None, - transform=None, - tick_direction="in", - label_direction=None, - offset=None): - warnings.warn("new_axisline is deprecated. Use new_fixed_axis " - "or new_floating_axis instead") - _helper = self._get_axisline_helper(nth_coord, loc, - passthrough_point, - transform) - - axisline = AxisArtist(self.axes, _helper, - #tick_direction="in", - offset=offset, - ) - - return axisline - - - from matplotlib.lines import Line2D class Ticks(Line2D): @@ -691,6 +655,7 @@ kwargs["markeredgewidth"] = "auto" super(Ticks, self).__init__([0.], [0.], **kwargs) + self.set_snap(True) def get_color(self): @@ -724,8 +689,8 @@ return self._markeredgewidth - def update_locs_angles(self, locs_angles, renderer): - self.locs_angles = locs_angles + def update_ticks(self, locs_angles_labels, renderer): + self.locs_angles_labels = locs_angles_labels _tickvert_path = Path([[0., 0.], [0., 1.]]) @@ -763,12 +728,12 @@ offset = renderer.points_to_pixels(size) marker_scale = Affine2D().scale(offset, offset) - for loc, angle in self.locs_angles: + for loc, angle, _ in self.locs_angles_labels: marker_rotation = Affine2D().rotate_deg(angle) #marker_rotation.clear().rotate_deg(angle) marker_transform = marker_scale + marker_rotation - locs = path_trans.transform_non_affine(np.array([loc])) + locs = path_trans.transform_non_affine(np.array([loc, loc])) renderer.draw_markers(gc, self._tickvert_path, marker_transform, Path(locs), path_trans.get_affine()) @@ -780,7 +745,7 @@ class TickLabels(mtext.Text): def __init__(self, size, **kwargs): - self._locs_labels = [] + self.locs_angles_labels = [] self._axis = kwargs.pop("axis", None) if self._axis is not None: @@ -790,10 +755,17 @@ super(TickLabels, self).__init__(x=0., y=0., text="", **kwargs ) + self._rotate_ticklabel = None - def update_locs_labels(self, locs_labels, renderer): - self._locs_labels = locs_labels + def set_rotate_along_line(self, b): + self._rotate_ticklabel = b + def get_rotate_along_line(self): + return self._rotate_ticklabel + + def update_ticks(self, locs_angles_labels, renderer): + self.locs_angles_labels = locs_angles_labels + def get_color(self): if self._color == 'auto': if self._axis is not None: @@ -809,15 +781,45 @@ def draw(self, renderer): if not self.get_visible(): return - for (x, y), l in self._locs_labels: - self.set_x(x) - self.set_y(y) - self.set_text(l) - super(TickLabels, self).draw(renderer) + if self.get_rotate_along_line(): + # curved axis + # save original and adjust some properties + tr = self.get_transform() + rm = self.get_rotation_mode() + + self.set_rotation_mode("anchor") + offset_tr = Affine2D() + self.set_transform(tr+offset_tr) + + # estimate pad + dd = 5 + renderer.points_to_pixels(self.get_size()) + + for (x, y), a, l in self.locs_angles_labels: + theta = (a+90.)/180.*np.pi + dx, dy = dd * np.cos(theta), dd * np.sin(theta) + offset_tr.translate(dx, dy) + self.set_rotation(a-180) + self.set_x(x) + self.set_y(y) + self.set_text(l) + super(TickLabels, self).draw(renderer) + offset_tr.clear() + + # restore original properties + self.set_transform(tr) + self.set_rotation_mode(rm) + else: + for (x, y), a, l in self.locs_angles_labels: + self.set_x(x) + self.set_y(y) + self.set_text(l) + super(TickLabels, self).draw(renderer) + + def get_window_extents(self, renderer): bboxes = [] - for (x, y), l in self._locs_labels: + for (x, y), a, l in self.locs_angles_labels: self.set_x(x) self.set_y(y) self.set_text(l) @@ -825,15 +827,10 @@ bboxes.append(self.get_window_extent()) return [b for b in bboxes if b.width!=0 or b.height!=0] - #if bboxes: - # return Bbox.union([b for b in bboxes if b.width!=0 or b.height!=0]) - #else: - # return Bbox.from_bounds(0, 0, 0, 0) - class AxisLabel(mtext.Text): def __init__(self, *kl, **kwargs): self._axis = kwargs.pop("axis", None) @@ -872,7 +869,6 @@ def draw(self, renderer): if self._grid_helper is not None: self._grid_helper.update_lim(self.axes) - #self.set_transform(self._grid_helper.get_gridlines_transform()) gl = self._grid_helper.get_gridlines() if gl: self.set_segments([np.transpose(l) for l in gl]) @@ -882,12 +878,8 @@ -class AxisGridLineBase(martist.Artist): - def __init__(self, *kl, **kw): - super(AxisGridLineBase, self).__init__(*kl, **kw) - -class AxisArtist(AxisGridLineBase): +class AxisArtist(martist.Artist): """ an artist which draws axis (a line along which the n-th axes coord is constant) line, ticks, ticklabels, and axis label. @@ -900,7 +892,6 @@ def __init__(self, axes, helper, - #offset_transform=None, offset=None, major_tick_size=None, major_tick_pad=None, @@ -910,7 +901,7 @@ """ axes is also used to follow the axis attribute (tick color, etc). """ - AxisGridLineBase.__init__(self, **kw) + super(AxisArtist, self).__init__(**kw) self.axes = axes @@ -922,9 +913,6 @@ self.offset_transform = ScaledTranslation(offset[0], offset[1], self.dpi_transform) - #self.set_transform(axes.transAxes + \ - # self.offset_transform) - self._label_visible = True self._majortick_visible = True self._majorticklabel_visible = True @@ -956,6 +944,14 @@ self.set_zorder(self.ZORDER) + self._rotate_label_along_line = False + + def set_rotate_label_along_line(self, b): + self._rotate_label_along_line = b + + def get_rotate_label_along_line(self): + return self._rotate_label_along_line + def get_transform(self): return self.axes.transAxes + self.offset_transform @@ -992,14 +988,10 @@ size = rcParams['xtick.labelsize'] fontprops = font_manager.FontProperties(size=size) - #tvhl = self._axis_artist_helper.get_ticklabel_transform( tvhl = self._axis_artist_helper.get_ticklabel_offset_transform( \ - self.axes, - self.major_tick_pad, - fontprops=fontprops, - renderer=None, - ) - #trans=transform) + self.axes, self.major_tick_pad, + fontprops=fontprops, renderer=None) + trans, vert, horiz, label_a = tvhl trans = transform + trans @@ -1031,9 +1023,6 @@ x,y,va,ha = self._offsetText_pos[direction] - #d = self._axis_artist_helper.label_direction - #fp = font_manager.FontProperties(size=rcParams['xtick.labelsize']) - #fp = font_manager.FontProperties(size=self.major_ticklabels.get_size()) self.offsetText = mtext.Annotation("", xy=(x,y), xycoords="axes fraction", xytext=(0,0), textcoords="offset points", @@ -1059,20 +1048,12 @@ def _draw_ticks(self, renderer): - #majortick_iter, minortick_iter): - #major_locs, major_angles, - #minor_locs, minor_angles): majortick_iter, minortick_iter = \ self._axis_artist_helper.get_tick_iterators(self.axes) - tick_loc_angles = [] - tick_loc_labels = [] - for tick_loc, tick_angle, tick_label in majortick_iter: - tick_loc_angles.append((tick_loc, tick_angle)) - tick_loc_labels.append((tick_loc, tick_label)) + tick_loc_angle_label = list(majortick_iter) - transform=self._axis_artist_helper.get_tick_transform(self.axes) \ + self.offset_transform fontprops = font_manager.FontProperties(size=12) @@ -1082,7 +1063,7 @@ fontprops=fontprops, renderer=renderer, ) - #trans=transform) + trans, va, ha, a = tvhl trans = transform + trans @@ -1090,20 +1071,16 @@ va=va, ha=ha, rotation=a) - self.major_ticks.update_locs_angles(tick_loc_angles, renderer) - self.major_ticklabels.update_locs_labels(tick_loc_labels, renderer) + self.major_ticks.update_ticks(tick_loc_angle_label, renderer) + self.major_ticklabels.update_ticks(tick_loc_angle_label, renderer) self.major_ticks.draw(renderer) self.major_ticklabels.draw(renderer) - tick_loc_angles = [] - tick_loc_labels = [] - for tick_loc, tick_angle, tick_label in minortick_iter: - tick_loc_angles.append((tick_loc, tick_angle)) - tick_loc_labels.append((tick_loc, tick_label)) + tick_loc_angle_label = list(minortick_iter) - self.minor_ticks.update_locs_angles(tick_loc_angles, renderer) - self.minor_ticklabels.update_locs_labels(tick_loc_labels, renderer) + self.minor_ticks.update_ticks(tick_loc_angle_label, renderer) + self.minor_ticklabels.update_ticks(tick_loc_angle_label, renderer) self.minor_ticks.draw(renderer) self.minor_ticklabels.draw(renderer) @@ -1113,9 +1090,11 @@ return self.major_ticklabels.get_window_extents(renderer) + def _init_label(self): # x in axes coords, y in display coords (to be updated at draw # time by _update_label_positions) + fontprops = font_manager.FontProperties(size=rcParams['axes.labelsize']) textprops = dict(fontproperties = fontprops, color = rcParams['axes.labelcolor'], @@ -1129,7 +1108,6 @@ self.label.set_figure(self.axes.figure) - #self._set_artist_props(label) def _draw_label(self, renderer, bboxes): @@ -1137,31 +1115,50 @@ return fontprops = font_manager.FontProperties(size=rcParams['axes.labelsize']) - pad_points = self.LABELPAD + self.major_tick_pad - xy, tr = self._axis_artist_helper.get_label_pos(self.axes) - if xy is None: return - x, y = xy - tr2, va, ha, a = self._axis_artist_helper.get_label_offset_transform(\ - self.axes, - pad_points, fontprops, - renderer, - bboxes=bboxes, - ) - #trans=tr+self.offset_transform) - tr2 = (tr+self.offset_transform) + tr2 + pad_points = self.major_tick_pad - self.label.set(x=x, y=y, - transform=tr2, - va=va, ha=ha, rotation=a) + if self.get_rotate_label_along_line(): + xy, tr, label_a = self._axis_artist_helper.get_label_pos( \ + self.axes, with_angle=True) + if xy is None: return -# if self.label.get_text() == "__from_axes__": -# label_text = self._helper.axis.get_label().get_text() -# self.label.set_text(label_text) -# self.label.draw(renderer) -# self.label.set_text("__from_axes__") -# else: + x, y = xy + offset_tr = Affine2D() + if self.major_ticklabels.get_visible(): + dd = renderer.points_to_pixels(self.major_ticklabels.get_size() \ + + pad_points + 2*self.LABELPAD ) + else: + dd = renderer.points_to_pixels(pad_points + 2*self.LABELPAD) + + theta = label_a - 0.5 * np.pi #(label_a)/180.*np.pi + dx, dy = dd * np.cos(theta), dd * np.sin(theta) + offset_tr.translate(dx, dy) + tr2 = (tr+offset_tr) #+ tr2 + + self.label.set(x=x, y=y, + rotation_mode="anchor", + transform=tr2, + va="center", ha="center", + rotation=label_a/np.pi*180.) + else: + xy, tr = self._axis_artist_helper.get_label_pos(self.axes) + if xy is None: return + + x, y = xy + tr2, va, ha, a = self._axis_artist_helper.get_label_offset_transform(\ + self.axes, + pad_points+2*self.LABELPAD, fontprops, + renderer, + bboxes=bboxes, + ) + tr2 = (tr+self.offset_transform) + tr2 + + self.label.set(x=x, y=y, + transform=tr2, + va=va, ha=ha, rotation=a) + self.label.draw(renderer) @@ -1169,6 +1166,7 @@ self.label.set_text(s) + @allow_rasterization def draw(self, renderer): 'Draw the axis lines, tick lines and labels' @@ -1239,8 +1237,6 @@ else: self._grid_helper = GridHelperRectlinear(self) - #if self._grid_helper.axes is None: - # self._grid_helper.set_axes(self) self._axisline_on = True super(Axes, self).__init__(*kl, **kw) @@ -1269,7 +1265,7 @@ super(Axes, self)._init_axis() - def _init_axislines(self): + def _init_axis_artists(self): self._axislines = self.AxisDict(self) new_fixed_axis = self.get_grid_helper().new_fixed_axis for loc in ["bottom", "top", "left", "right"]: @@ -1285,7 +1281,7 @@ axis = property(_get_axislines) - def new_gridlines(self, grid_helper=None): + def _init_gridlines(self, grid_helper=None): gridlines = GridlinesCollection(None, transform=self.transData, colors=rcParams['grid.color'], linestyles=rcParams['grid.linestyle'], @@ -1296,14 +1292,14 @@ gridlines.set_grid_helper(grid_helper) gridlines.set_clip_on(True) - return gridlines + self.gridlines = gridlines def cla(self): # gridlines need to b created before cla() since cla calls grid() - self.gridlines = self.new_gridlines() + self._init_gridlines() super(Axes, self).cla() - self._init_axislines() + self._init_axis_artists() def get_grid_helper(self): return self._grid_helper @@ -1322,9 +1318,6 @@ if len(kwargs): martist.setp(self.gridlines, **kwargs) - #def get_gridlines(self): - # return self._grid_helper.get_gridlines() - def get_children(self): if self._axisline_on: children = self._axislines.values()+[self.gridlines] @@ -1334,10 +1327,22 @@ return children def invalidate_grid_helper(self): - #self._grid_helper.update_lim(self, force_update=True) self._grid_helper.invalidate() + def new_floating_axis(self, nth_coord, value, + tick_direction="in", + label_direction=None, + ): + gh = self.get_grid_helper() + axis = gh.new_floating_axis(nth_coord, value, + tick_direction=tick_direction, + label_direction=label_direction, + axes=self) + return axis + + + def draw(self, renderer, inframe=False): if not self._axisline_on: @@ -1359,8 +1364,6 @@ if not self._axisline_on: return bb0 - - #artists = [] bb = [bb0] for axisline in self._axislines.values(): @@ -1397,13 +1400,12 @@ super(AxesZero, self).__init__(*kl, **kw) - def _init_axislines(self): - super(AxesZero, self)._init_axislines() + def _init_axis_artists(self): + super(AxesZero, self)._init_axis_artists() new_floating_axis = self._grid_helper.new_floating_axis xaxis_zero = new_floating_axis(nth_coord=0, - passthrough_point=(0.,0.), - transform=self.transData, + value=0., tick_direction="in", label_direction="bottom", axes=self) @@ -1413,8 +1415,7 @@ self._axislines["xzero"] = xaxis_zero yaxis_zero = new_floating_axis(nth_coord=1, - passthrough_point=(0.,0.), - transform=self.transData, + value=0., tick_direction="in", label_direction="left", axes=self) @@ -1428,6 +1429,8 @@ if __name__ == "__main__": + import matplotlib.pyplot as plt + fig = plt.figure(1, (4,3)) ax = SubplotZero(fig, 1, 1, 1) @@ -1441,7 +1444,8 @@ xx = np.arange(0, 2*np.pi, 0.01) ax.plot(xx, np.sin(xx)) - + ax.set_ylabel("Test") + plt.draw() plt.show() Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_finder.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_finder.py 2009-06-23 12:47:49 UTC (rev 7232) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_finder.py 2009-06-24 05:46:08 UTC (rev 7233) @@ -5,6 +5,7 @@ clip_line_to_rect = clip_path.clip_line_to_rect import matplotlib.ticker as mticker +from matplotlib.transforms import Transform # extremes finder @@ -51,9 +52,11 @@ tick_formatter1=None, tick_formatter2=None): """ - transform : transfrom from the image coordinate (which will be the transData of the axes to the world coordinate. locator1, locator2 : grid locator for 1st and 2nd axis. + + Derived must define "transform_xy, inv_transform_xy" + (may use update_transform) """ super(GridFinderBase, self).__init__() @@ -63,16 +66,14 @@ self.tick_formatter1 = tick_formatter1 self.tick_formatter2 = tick_formatter2 - def get_grid_info(self, - transform_xy, inv_transform_xy, x1, y1, x2, y2): """ lon_values, lat_values : list of grid values. if integer is given, rough number of grids in each direction. """ - extremes = self.extreme_finder(transform_xy, x1, y1, x2, y2) + extremes = self.extreme_finder(self.inv_transform_xy, x1, y1, x2, y2) # min & max rage of lat (or lon) for each grid line will be drawn. # i.e., gridline of lon=0 will be drawn from lat_min to lat_max. @@ -93,8 +94,7 @@ lat_values = np.asarray(lat_levs[:lat_n]/lat_factor) - lon_lines, lat_lines = self._get_raw_grid_lines(inv_transform_xy, - lon_values, + lon_lines, lat_lines = self._get_raw_grid_lines(lon_values, lat_values, lon_min, lon_max, lat_min, lat_max) @@ -132,23 +132,21 @@ return grid_info - def _get_raw_grid_lines(self, inv_transform_xy, + def _get_raw_grid_lines(self, lon_values, lat_values, lon_min, lon_max, lat_min, lat_max): lons_i = np.linspace(lon_min, lon_max, 100) # for interpolation lats_i = np.linspace(lat_min, lat_max, 100) - lon_lines = [inv_transform_xy(np.zeros_like(lats_i)+lon, lats_i) \ + lon_lines = [self.transform_xy(np.zeros_like(lats_i)+lon, lats_i) \ for lon in lon_values] - lat_lines = [inv_transform_xy(lons_i, np.zeros_like(lons_i)+lat) \ + lat_lines = [self.transform_xy(lons_i, np.zeros_like(lons_i)+lat) \ for lat in lat_values] return lon_lines, lat_lines - - def _clip_grid_lines_and_find_ticks(self, lines, values, levs, bb): gi = dict() gi["values"] = [] @@ -174,76 +172,45 @@ return gi - def _update_label_deprecated(self): - pass + def update_transform(self, aux_trans): + if isinstance(aux_trans, Transform): + def transform_xy(x, y): + x, y = np.asarray(x), np.asarray(y) + ll1 = np.concatenate((x[:,np.newaxis], y[:,np.newaxis]), 1) + ll2 = aux_trans.transform(ll1) + lon, lat = ll2[:,0], ll2[:,1] + return lon, lat - def _find_grid_values_deprecated(self, x1, y1, x2, y2, den_x, den_y): - """ - values_lon, values_lat : list of grid values. if integer is given, - rough number of grids in each direction. - """ - nx, ny = den_x * 20, den_y*20 + def inv_transform_xy(x, y): + x, y = np.asarray(x), np.asarray(y) + ll1 = np.concatenate((x[:,np.newaxis], y[:,np.newaxis]), 1) + ll2 = aux_trans.inverted().transform(ll1) + lon, lat = ll2[:,0], ll2[:,1] + return lon, lat - extremes = self.get_extremes(x1, y1, x2, y2, nx, ny) - lon_min, lon_max, lat_min, lat_max = extremes + else: + transform_xy, inv_transform_xy = aux_trans - lon_levs, lon_n, lon_factor = \ - self.grid_locator1(lon_min, lon_max) - lat_levs, lat_n, lat_factor = \ - self.grid_locator2(lat_min, lat_max) + self.transform_xy = transform_xy + self.inv_transform_xy = inv_transform_xy - return lon_levs, lon_n, lon_factor, lat_levs, lat_n, lat_factor + def update(self, **kw): + for k in kw: + if k in ["extreme_finder", + "grid_locator1", + "grid_locator2", + "tick_formatter1", + "tick_formatter2"]: + setattr(self, k, kw[k]) + else: + raise ValueError("unknwonw update property") -class GridFinder(GridFinderBase): - def __init__(self, - transform_xy, inv_transform_xy, - extreme_finder=None, - grid_locator1=None, - grid_locator2=None, - tick_formatter1=None, - tick_formatter2=None): - """ - transform : transfrom from the image coordinate (which will be - the transData of the axes to the world coordinate. - locator1, locator2 : grid locator for 1st and 2nd axis. - """ - if extreme_finder is None: - extreme_finder = ExtremeFinderSimple(20, 20) - if grid_locator1 is None: - grid_locator1 = MaxNLocator() - if grid_locator2 is None: - grid_locator2 = MaxNLocator() - if tick_formatter1 is None: - tick_formatter1 = FormatterPrettyPrint() - if tick_formatter2 is None: - tick_formatter2 = FormatterPrettyPrint() +class GridFinder(GridFinderBase): - super(GridFinder, self).__init__( \ - extreme_finder, - grid_locator1, - grid_locator2, - tick_formatter1, - tick_formatter2) - - self._transform_xy = transform_xy - self._inv_transform_xy = inv_transform_xy - - - def get_grid_info(self, - x1, y1, x2, y2): - - return super(GridFinder,self).get_grid_info( \ - self._inv_transform_xy, self._transform_xy, - x1, y1, x2, y2) - - - -class GridFinderMplTransform(GridFinderBase): - def __init__(self, transform, extreme_finder=None, @@ -254,6 +221,9 @@ """ transform : transfrom from the image coordinate (which will be the transData of the axes to the world coordinate. + + or transfor... [truncated message content] |
From: <jd...@us...> - 2009-06-24 21:04:26
|
Revision: 7239 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7239&view=rev Author: jdh2358 Date: 2009-06-24 21:01:53 +0000 (Wed, 24 Jun 2009) Log Message: ----------- some tweaks to csv2rec and rec2csv Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/api/api_changes.rst trunk/matplotlib/doc/devel/release_guide.rst trunk/matplotlib/lib/matplotlib/mlab.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-06-24 18:53:48 UTC (rev 7238) +++ trunk/matplotlib/CHANGELOG 2009-06-24 21:01:53 UTC (rev 7239) @@ -1,3 +1,8 @@ +2009-06-24 Add withheader option to mlab.rec2csv and changed + use_mrecords default to False in mlab.csv2rec since this is + partially broken - JDH + + 2009-06-24 backend_agg.draw_marker quantizes the main path (as in the draw_path). - JJL Modified: trunk/matplotlib/doc/api/api_changes.rst =================================================================== --- trunk/matplotlib/doc/api/api_changes.rst 2009-06-24 18:53:48 UTC (rev 7238) +++ trunk/matplotlib/doc/api/api_changes.rst 2009-06-24 21:01:53 UTC (rev 7239) @@ -1,3 +1,4 @@ + =========== API Changes =========== @@ -20,7 +21,10 @@ Changes beyond 0.98.x ===================== -* Axes instanaces no longer have a "frame" attribute. Instead, use the +* changed use_mrecords default to False in mlab.csv2rec since this is + partially broken + +* Axes instances no longer have a "frame" attribute. Instead, use the new "spines" attribute. Spines is a dictionary where the keys are the names of the spines (e.g. 'left','right' and so on) and the values are the artists that draw the spines. For normal Modified: trunk/matplotlib/doc/devel/release_guide.rst =================================================================== --- trunk/matplotlib/doc/devel/release_guide.rst 2009-06-24 18:53:48 UTC (rev 7238) +++ trunk/matplotlib/doc/devel/release_guide.rst 2009-06-24 21:01:53 UTC (rev 7239) @@ -64,16 +64,18 @@ or off any platform specific build options you need. Importantly, you also need to make sure that you delete the :file:`build` dir after any changes to file:`setup.cfg` before rebuilding since cruft - in the :file:`build` dir can get carried along. I will add this to - the devel release notes, + in the :file:`build` dir can get carried along. * on windows, unix2dos the rc file * We have a Makefile for the OS X builds in the mpl source dir :file:`release/osx`, so use this to prepare the OS X releases. +* We have a Makefile for the win32 mingw builds in the mpl source dir + :file:`release/win32` which you can use this to prepare the windows + releases, but this is currently broken for python2.6 as described at + http://www.nabble.com/binary-installers-for-python2.6--libpng-segfault%2C-MSVCR90.DLL-and-%09mingw-td23971661.html - .. _release-candidate-testing: Release candidate testing: Modified: trunk/matplotlib/lib/matplotlib/mlab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mlab.py 2009-06-24 18:53:48 UTC (rev 7238) +++ trunk/matplotlib/lib/matplotlib/mlab.py 2009-06-24 21:01:53 UTC (rev 7239) @@ -2052,7 +2052,7 @@ def csv2rec(fname, comments='#', skiprows=0, checkrows=0, delimiter=',', converterd=None, names=None, missing='', missingd=None, - use_mrecords=True): + use_mrecords=False): """ Load data from comma/space/tab delimited file in *fname* into a numpy record array and return the record array. @@ -2560,7 +2560,7 @@ def rec2csv(r, fname, delimiter=',', formatd=None, missing='', - missingd=None): + missingd=None, withheader=True): """ Save the data from numpy recarray *r* into a comma-/space-/tab-delimited file. The record array dtype names @@ -2569,6 +2569,9 @@ *fname*: can be a filename or a file handle. Support for gzipped files is automatic, if the filename ends in '.gz' + *withheader*: if withheader is False, do not write the attribute + names in the first row + .. seealso:: :func:`csv2rec` @@ -2595,7 +2598,8 @@ fh, opened = cbook.to_filehandle(fname, 'w', return_opened=True) writer = csv.writer(fh, delimiter=delimiter) header = r.dtype.names - writer.writerow(header) + if withheader: + writer.writerow(header) # Our list of specials for missing values mvals = [] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2009-06-25 05:17:11
|
Revision: 7241 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7241&view=rev Author: leejjoon Date: 2009-06-25 05:17:10 +0000 (Thu, 25 Jun 2009) Log Message: ----------- axes_grid: doc update Modified Paths: -------------- trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/index.rst trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/overview.rst trunk/matplotlib/examples/axes_grid/demo_floating_axis.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_helper_curvelinear.py Modified: trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/index.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/index.rst 2009-06-25 04:57:48 UTC (rev 7240) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/index.rst 2009-06-25 05:17:10 UTC (rev 7241) @@ -11,3 +11,4 @@ overview.rst axes_divider.rst + axislines.rst Modified: trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/overview.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/overview.rst 2009-06-25 04:57:48 UTC (rev 7240) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/overview.rst 2009-06-25 05:17:10 UTC (rev 7241) @@ -388,3 +388,13 @@ .. plot:: mpl_toolkits/axes_grid/figures/inset_locator_demo2.py :include-source: + +Curvelinear Grid +================ + +You can draw a cuvelinear grid and ticks. Also a floating axis can be +created. See :ref:`axislines-manual` for more details. + +.. plot:: mpl_toolkits/axes_grid/figures/demo_floating_axis.py + + Modified: trunk/matplotlib/examples/axes_grid/demo_floating_axis.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_floating_axis.py 2009-06-25 04:57:48 UTC (rev 7240) +++ trunk/matplotlib/examples/axes_grid/demo_floating_axis.py 2009-06-25 05:17:10 UTC (rev 7241) @@ -40,9 +40,6 @@ ax1 = SubplotHost(fig, 1, 1, 1, grid_helper=grid_helper) - # make ticklabels of right and top axis visible. - for axis in ax1.axis.values(): - axis.toggle(all=False) fig.add_subplot(ax1) Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_helper_curvelinear.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_helper_curvelinear.py 2009-06-25 04:57:48 UTC (rev 7240) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_helper_curvelinear.py 2009-06-25 05:17:10 UTC (rev 7241) @@ -315,10 +315,13 @@ def new_floating_axis(self, nth_coord, value, tick_direction="in", - label_direction="top", + label_direction=None, axes=None, ): + if label_direction is None: + label_direction = "top" + _helper = FloatingAxisArtistHelper(self, nth_coord, value, label_direction=label_direction, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2009-06-29 15:11:04
|
Revision: 7244 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7244&view=rev Author: leejjoon Date: 2009-06-29 15:11:00 +0000 (Mon, 29 Jun 2009) Log Message: ----------- axes_grid: doc update Modified Paths: -------------- trunk/matplotlib/examples/axes_grid/demo_floating_axis.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_helper_curvelinear.py Added Paths: ----------- trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/axislines.rst Added: trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/axislines.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/axislines.rst (rev 0) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/axislines.rst 2009-06-29 15:11:00 UTC (rev 7244) @@ -0,0 +1,250 @@ +.. _axislines-manual: + +========= +Axislines +========= + +Axislines includes a derived Axes implementation. The +biggest difference is that the artists responsible to draw axis line, +ticks, ticklabel and axis labels are separated out from the mpl's Axis +class, which are much more than artists in the original +mpl. This change was strongly motivated to support curvlinear +grid. Here are a few things that axes_grid.axislines.Axes is different +from original Axes from mpl. + +* Axis elements (axis line(spine), ticks, ticklabel and axis labels) + are drawn by a AxisArtist instance. Unlike Axis, left, right, top + and bottom axis are drawn by separate artists. And each of them may + have different tick location and different tick labels. + +* gridlines are drawn by a Gridlines instance. The change was + motivated that in curvelinear coordinate, a gridline may not cross + axislines (i.e., no associated ticks). In the original Axes class, + gridlines are tied to ticks. + +* ticklines can be rotated if necessary (i.e, along the gridlines) + +In summary, all these changes was to support + +* a curvelinear grid. +* a floating axis + +.. plot:: mpl_toolkits/axes_grid/figures/demo_floating_axis.py + + +*axes_grid.axislines.Axes* defines a *axis* attribute, which is a +dictionary of AxisArtist instances. By default, the dictionary has 4 +AxisArtist instances, responsible for drawing of left, right, bottom +and top axis. + +xaxis and yaxis attributes are still available, however they are set +to not visible. As separate artists are used for rendering axis, some +axis-related method in mpl may have no effect. +In addition to AxisArtist instances, the axes_grid.axislines.Axes will +have *gridlines* attribute (Gridlines), which obviously draws grid +lines. + +In both AxisArtist and Gridlines, the calculation of tick and grid +location is delegated to an instance of GridHelper class. +axes_grid.axislines.Axes class uses GridHelperRectlinear as a grid +helper. The GridHelperRectlinear class is a wrapper around the *xaxis* +and *yaxis* of mpl's original Axes, and it was meant to work as the +way how mpl's original axes works. For example, tick location changes +using set_ticks method and etc. should work as expected. But change in +artist properties (e.g., color) will not work in general, although +some effort has been made so that some often-change attributes (color, +etc.) are respected. + + +AxisArtist +========== + +AxisArtist can be considered as a container artist with following +attributes which will draw ticks, labels, etc. + + * line + * major_ticks, major_ticklabels + * minor_ticks, minor_ticklabels + * offsetText + * label + + +line +---- + +Derived from Line2d class. Responsible for drawing a spinal(?) line. + +major_ticks, minor_ticks +------------------------ + +Derived from Line2d class. Note that ticks are markers. + + +major_ticklabels, minor_ticklabels +---------------------------------- + +Derived from Text. Note that it is not a list of Text artist, but a +single artist (similar to a collection). + +axislabel +--------- + +Derived from Text. + + +Default AxisArtists +------------------- + +By default, following for axis artists are defined.:: + + ax.axis["left"], ax.axis["bottom"], ax.axis["right"], ax.axis["top"] + +The ticklabels and axislabel of the top and the right axis are set to +not visible. + + +HowTo +===== + +1. Changing tick locations and label. + + Same as the original mpl's axes.:: + + ax.set_xticks([1,2,3]) + +2. Changing axis properties like color, etc. + + Change the properties of appropriate artists. For example, to change + the color of the ticklabels:: + + ax.axis["left"].major_ticklabels.set_color("r") + + +GridHelper +========== + +To actually define a curvelinear coordinate, you have to use your own +grid helper. A generalised version of grid helper class is supplied +and this class should be suffice in most of cases. A user may provide +two functions which defines a transformation (and its inverse pair) +from the curved coordinate to (rectlinear) image coordinate. Note that +while ticks and grids are drawn for curved coordinate, the data +transform of the axes itself (ax.transData) is still rectlinear +(image) coordinate. :: + + + from mpl_toolkits.axes_grid.grid_helper_curvelinear \ + import GridHelperCurveLinear + from mpl_toolkits.axes_grid.axislines import Subplot + + # from curved coordinate to rectlinear coordinate. + def tr(x, y): + x, y = np.asarray(x), np.asarray(y) + return x, y-x + + # from rectlinear coordinate to curved coordinate. + def inv_tr(x,y): + x, y = np.asarray(x), np.asarray(y) + return x, y+x + + + grid_helper = GridHelperCurveLinear((tr, inv_tr)) + + ax1 = Subplot(fig, 1, 1, 1, grid_helper=grid_helper) + + fig.add_subplot(ax1) + + +You may use matplotlib's Transform instance instead (but a +inverse transformation must be defined). Often, coordinate range in a +curved coordinate system may have a limited range, or may have +cycles. In those cases, a more customized version of grid helper is +required. :: + + + import mpl_toolkits.axes_grid.angle_helper as angle_helper + + # PolarAxes.PolarTransform takes radian. However, we want our coordinate + # system in degree + tr = Affine2D().scale(np.pi/180., 1.) + PolarAxes.PolarTransform() + + + # extreme finder : find a range of coordinate. + # 20, 20 : number of sampling points along x, y direction + # The first coordinate (longitude, but theta in polar) + # has a cycle of 360 degree. + # The second coordinate (latitude, but radius in polar) has a minimum of 0 + extreme_finder = angle_helper.ExtremeFinderCycle(20, 20, + lon_cycle = 360, + lat_cycle = None, + lon_minmax = None, + lat_minmax = (0, np.inf), + ) + + # Find a grid values appropriate for the coordinate (degree, + # minute, second). The argument is a approximate number of grids. + grid_locator1 = angle_helper.LocatorDMS(12) + + # And also uses an appropriate formatter. Note that,the + # acceptable Locator and Formatter class is a bit different than + # that of mpl's, and you cannot directly use mpl's Locator and + # Formatter here (but may be possible in the future). + tick_formatter1 = angle_helper.FormatterDMS() + + grid_helper = GridHelperCurveLinear(tr, + extreme_finder=extreme_finder, + grid_locator1=grid_locator1, + tick_formatter1=tick_formatter1 + ) + + +Again, the *transData* of the axes is still a rectlinear coordinate +(image coordinate). You may manually do conversion between two +coordinates, or you may use Parasite Axes for convenience.:: + + ax1 = SubplotHost(fig, 1, 2, 2, grid_helper=grid_helper) + + # A parasite axes with given transform + ax2 = ParasiteAxesAuxTrans(ax1, tr, "equal") + # note that ax2.transData == tr + ax1.transData + # Anthing you draw in ax2 will match the ticks and grids of ax1. + ax1.parasites.append(ax2) + + +.. plot:: mpl_toolkits/axes_grid/figures/demo_curvelinear_grid.py + + + +FloatingAxis +============ + +A floating axis is an axis one of whose data coordinate is fixed, i.e, +its location is not fixed in Axes coordinate but changes as axes data +limits changes. A floating axis can be created using +*new_floating_axis* method. However, it is your responsibility that +the resulting AxisArtist is properly added to the axes. A recommended +way is to add it as an item of Axes's axis attribute.:: + + # floating axis whose first (index starts from 0) coordinate + # (theta) is fixed at 60 + + ax1.axis["lat"] = axis = ax1.new_floating_axis(0, 60) + axis.label.set_text(r"$\theta = 60^{\circ}$") + axis.label.set_visible(True) + + +See the first example of this page. + +Current Limitations and TODO's +============================== + +The code need more refinement. Here is a incomplete list of issues and TODO's + +* No easy way to support a user customized tick location (for + curvelinear grid). A new Locator class needs to be created. + +* FloatingAxis may have coordinate limits, e.g., a floating axis of x + = 0, but y only spans from 0 to 1. + +* The location of axislabel of FloatingAxis needs to be optionally + given as a coordinate value. ex, a floating axis of x=0 with label at y=1 Modified: trunk/matplotlib/examples/axes_grid/demo_floating_axis.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_floating_axis.py 2009-06-27 13:13:50 UTC (rev 7243) +++ trunk/matplotlib/examples/axes_grid/demo_floating_axis.py 2009-06-29 15:11:00 UTC (rev 7244) @@ -1,6 +1,5 @@ """ -A floating axes for curvelinear grid. -. +An experimental support for curvelinear grid. """ @@ -8,6 +7,7 @@ """ polar projection, but in a rectangular box. """ + global ax1 import numpy as np import mpl_toolkits.axes_grid.angle_helper as angle_helper from matplotlib.projections import PolarAxes @@ -40,19 +40,18 @@ ax1 = SubplotHost(fig, 1, 1, 1, grid_helper=grid_helper) - fig.add_subplot(ax1) # Now creates floating axis - grid_helper = ax1.get_grid_helper() + #grid_helper = ax1.get_grid_helper() # floating axis whose first coordinate (theta) is fixed at 60 - ax1.axis["lat"] = axis = grid_helper.new_floating_axis(0, 60, axes=ax1) + ax1.axis["lat"] = axis = ax1.new_floating_axis(0, 60) axis.label.set_text(r"$\theta = 60^{\circ}$") axis.label.set_visible(True) # floating axis whose second coordinate (r) is fixed at 6 - ax1.axis["lon"] = axis = grid_helper.new_floating_axis(1, 6, axes=ax1) + ax1.axis["lon"] = axis = ax1.new_floating_axis(1, 6) axis.label.set_text(r"$r = 6$") ax1.set_aspect(1.) Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_helper_curvelinear.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_helper_curvelinear.py 2009-06-27 13:13:50 UTC (rev 7243) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/grid_helper_curvelinear.py 2009-06-29 15:11:00 UTC (rev 7244) @@ -14,7 +14,7 @@ """ Helper class for a fixed axis. """ - + def __init__(self, grid_helper, side, nth_coord_ticks=None): """ nth_coord = along which coordinate value varies. @@ -100,7 +100,7 @@ lon_factor, lon_levs) - grid_info["lat_labels"] = grid_finder.tick_formatter1("bottom", + grid_info["lat_labels"] = grid_finder.tick_formatter2("bottom", lat_factor, lat_levs) @@ -321,7 +321,7 @@ if label_direction is None: label_direction = "top" - + _helper = FloatingAxisArtistHelper(self, nth_coord, value, label_direction=label_direction, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-07-01 20:01:03
|
Revision: 7246 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7246&view=rev Author: mdboom Date: 2009-07-01 20:01:00 +0000 (Wed, 01 Jul 2009) Log Message: ----------- Merged revisions 7245 via svnmerge from https://matplotlib.svn.sf.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r7245 | mdboom | 2009-07-01 15:55:17 -0400 (Wed, 01 Jul 2009) | 1 line Fix out-of-memory errors leading to segfaults ........ Modified Paths: -------------- trunk/matplotlib/src/_path.cpp trunk/matplotlib/src/_png.cpp Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7229 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7245 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227,7245 Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227,7245 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227,7245 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227,7245 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227 + /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227,7245 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227 + /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227,7245 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227 + /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042,7072,7080,7176,7209-7211,7227,7245 Modified: trunk/matplotlib/src/_path.cpp =================================================================== --- trunk/matplotlib/src/_path.cpp 2009-07-01 19:55:17 UTC (rev 7245) +++ trunk/matplotlib/src/_path.cpp 2009-07-01 20:01:00 UTC (rev 7246) @@ -886,6 +886,9 @@ size_t size = p->size(); dims[0] = p->size(); PyArrayObject* pyarray = (PyArrayObject*)PyArray_SimpleNew(2, dims, PyArray_DOUBLE); + if (pyarray == NULL) { + throw Py::MemoryError("Could not allocate result array"); + } for (size_t i = 0; i < size; ++i) { ((double *)pyarray->data)[2*i] = (*p)[i].x; @@ -955,6 +958,9 @@ result = (PyArrayObject*)PyArray_SimpleNew (PyArray_NDIM(vertices), PyArray_DIMS(vertices), PyArray_DOUBLE); + if (result == NULL) { + throw Py::MemoryError("Could not allocate memory for path"); + } if (PyArray_NDIM(vertices) == 2) { size_t n = PyArray_DIM(vertices, 0); Modified: trunk/matplotlib/src/_png.cpp =================================================================== --- trunk/matplotlib/src/_png.cpp 2009-07-01 19:55:17 UTC (rev 7245) +++ trunk/matplotlib/src/_png.cpp 2009-07-01 20:01:00 UTC (rev 7246) @@ -266,6 +266,10 @@ double max_value = (1 << ((bit_depth < 8) ? 8 : bit_depth)) - 1; PyArrayObject *A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, PyArray_FLOAT); + if (A == NULL) { + throw Py::MemoryError("Could not allocate image array"); + } + for (png_uint_32 y = 0; y < height; y++) { png_byte* row = row_pointers[y]; for (png_uint_32 x = 0; x < width; x++) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-07-06 19:43:06
|
Revision: 7248 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7248&view=rev Author: mdboom Date: 2009-07-06 19:43:00 +0000 (Mon, 06 Jul 2009) Log Message: ----------- [2687673] Fix problems with Mollweide projection, enable it, and add to geo_demo.py Modified Paths: -------------- trunk/matplotlib/examples/pylab_examples/geo_demo.py trunk/matplotlib/lib/matplotlib/projections/__init__.py trunk/matplotlib/lib/matplotlib/projections/geo.py Modified: trunk/matplotlib/examples/pylab_examples/geo_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/geo_demo.py 2009-07-03 19:35:35 UTC (rev 7247) +++ trunk/matplotlib/examples/pylab_examples/geo_demo.py 2009-07-06 19:43:00 UTC (rev 7248) @@ -4,13 +4,19 @@ from pylab import * subplot(221, projection="aitoff") +title("Aitoff") grid(True) subplot(222, projection="hammer") +title("Hammer") grid(True) subplot(223, projection="lambert") +title("Lambert") grid(True) +subplot(224, projection="mollweide") +title("Mollweide") +grid(True) show() Modified: trunk/matplotlib/lib/matplotlib/projections/__init__.py =================================================================== --- trunk/matplotlib/lib/matplotlib/projections/__init__.py 2009-07-03 19:35:35 UTC (rev 7247) +++ trunk/matplotlib/lib/matplotlib/projections/__init__.py 2009-07-06 19:43:00 UTC (rev 7248) @@ -1,4 +1,4 @@ -from geo import AitoffAxes, HammerAxes, LambertAxes +from geo import AitoffAxes, HammerAxes, LambertAxes, MollweideAxes from polar import PolarAxes from matplotlib import axes @@ -38,7 +38,8 @@ PolarAxes, AitoffAxes, HammerAxes, - LambertAxes) + LambertAxes, + MollweideAxes) def register_projection(cls): Modified: trunk/matplotlib/lib/matplotlib/projections/geo.py =================================================================== --- trunk/matplotlib/lib/matplotlib/projections/geo.py 2009-07-03 19:35:35 UTC (rev 7247) +++ trunk/matplotlib/lib/matplotlib/projections/geo.py 2009-07-06 19:43:00 UTC (rev 7248) @@ -422,10 +422,21 @@ self._resolution = resolution def transform(self, ll): + def d(theta): + delta = -(theta + np.sin(theta) - pi_sin_l) / (1 + np.cos(theta)) + return delta, delta > 0.001 + longitude = ll[:, 0:1] latitude = ll[:, 1:2] - aux = 2.0 * np.arcsin((2.0 * latitude) / np.pi) + pi_sin_l = np.pi * np.sin(latitude) + theta = 2.0 * latitude + delta, large_delta = d(theta) + while np.any(large_delta): + theta += np.where(large_delta, delta, 0) + delta, large_delta = d(theta) + aux = theta / 2 + x = (2.0 * np.sqrt(2.0) * longitude * np.cos(aux)) / np.pi y = (np.sqrt(2.0) * np.sin(aux)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ds...@us...> - 2009-07-08 21:15:54
|
Revision: 7250 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7250&view=rev Author: dsdale Date: 2009-07-08 21:15:46 +0000 (Wed, 08 Jul 2009) Log Message: ----------- improve resizing behavior of qt4 backend Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py trunk/matplotlib/lib/matplotlib/backends/backend_qt4agg.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-07-07 12:41:45 UTC (rev 7249) +++ trunk/matplotlib/CHANGELOG 2009-07-08 21:15:46 UTC (rev 7250) @@ -1,3 +1,7 @@ +2009-07-08 Attempt to improve performance of qt4 backend, do not call + qApp.processEvents while processing an event. Thanks Ole + Streicher for tracking this down - DSD + 2009-06-24 Add withheader option to mlab.rec2csv and changed use_mrecords default to False in mlab.csv2rec since this is partially broken - JDH @@ -2,3 +6,2 @@ - 2009-06-24 backend_agg.draw_marker quantizes the main path (as in the Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2009-07-07 12:41:45 UTC (rev 7249) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2009-07-08 21:15:46 UTC (rev 7250) @@ -158,7 +158,6 @@ def resizeEvent( self, event ): if DEBUG: print 'resize (%d x %d)' % (event.size().width(), event.size().height()) - QtGui.QWidget.resizeEvent( self, event ) w = event.size().width() h = event.size().height() if DEBUG: print "FigureCanvasQtAgg.resizeEvent(", w, ",", h, ")" @@ -167,20 +166,9 @@ hinch = h/dpival self.figure.set_size_inches( winch, hinch ) self.draw() + self.update() + QtGui.QWidget.resizeEvent(self, event) - def resize( self, w, h ): - # Pass through to Qt to resize the widget. - QtGui.QWidget.resize( self, w, h ) - - # Resize the figure by converting pixels to inches. - pixelPerInch = self.figure.dpi - wInch = w / pixelPerInch - hInch = h / pixelPerInch - self.figure.set_size_inches( wInch, hInch ) - - # Redraw everything. - self.draw() - def sizeHint( self ): w, h = self.get_width_height() return QtCore.QSize( w, h ) Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt4agg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt4agg.py 2009-07-07 12:41:45 UTC (rev 7249) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt4agg.py 2009-07-08 21:15:46 UTC (rev 7250) @@ -61,9 +61,6 @@ self.replot = True self.setAttribute(QtCore.Qt.WA_OpaquePaintEvent) - def resizeEvent( self, e ): - FigureCanvasQT.resizeEvent( self, e ) - def drawRectangle( self, rect ): self.rect = rect self.drawRect = True @@ -132,8 +129,6 @@ self.replot = True FigureCanvasAgg.draw(self) self.update() - # Added following line to improve realtime pan/zoom on windows: - QtGui.qApp.processEvents() def blit(self, bbox=None): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2009-07-11 12:42:51
|
Revision: 7254 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7254&view=rev Author: jdh2358 Date: 2009-07-11 12:42:46 +0000 (Sat, 11 Jul 2009) Log Message: ----------- Merged revisions 7253 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r7253 | jdh2358 | 2009-07-11 07:39:29 -0500 (Sat, 11 Jul 2009) | 1 line applied osx setpext patch from sf #2818964 ........ Modified Paths: -------------- trunk/matplotlib/setupext.py Property Changed: ---------------- trunk/matplotlib/ Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7245 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7253 Modified: trunk/matplotlib/setupext.py =================================================================== --- trunk/matplotlib/setupext.py 2009-07-11 12:39:29 UTC (rev 7253) +++ trunk/matplotlib/setupext.py 2009-07-11 12:42:46 UTC (rev 7254) @@ -138,6 +138,9 @@ try: options['build_wxagg'] = config.getboolean("gui_support", "wxagg") except: options['build_wxagg'] = 'auto' + try: options['build_macosx'] = config.getboolean("gui_support", "macosx") + except: options['build_macosx'] = 'auto' + try: options['backend'] = config.get("rc_options", "backend") except: pass This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2009-07-11 16:52:47
|
Revision: 7255 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7255&view=rev Author: jdh2358 Date: 2009-07-11 16:52:44 +0000 (Sat, 11 Jul 2009) Log Message: ----------- added fillstyle property to Line2D Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/lines.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-07-11 12:42:46 UTC (rev 7254) +++ trunk/matplotlib/CHANGELOG 2009-07-11 16:52:44 UTC (rev 7255) @@ -1,3 +1,6 @@ +2009-07-11 Added a fillstyle Line2D property for half filled markers + -- see examples/pylab_examples/fillstyle_demo.py JDH + 2009-07-08 Attempt to improve performance of qt4 backend, do not call qApp.processEvents while processing an event. Thanks Ole Streicher for tracking this down - DSD Modified: trunk/matplotlib/lib/matplotlib/lines.py =================================================================== --- trunk/matplotlib/lib/matplotlib/lines.py 2009-07-11 12:42:46 UTC (rev 7254) +++ trunk/matplotlib/lib/matplotlib/lines.py 2009-07-11 16:52:44 UTC (rev 7255) @@ -172,6 +172,7 @@ markeredgewidth = None, markeredgecolor = None, markerfacecolor = None, + fillstyle = 'full', antialiased = None, dash_capstyle = None, solid_capstyle = None, @@ -238,6 +239,8 @@ self.set_markerfacecolor(markerfacecolor) self.set_markeredgecolor(markeredgecolor) self.set_markeredgewidth(markeredgewidth) + self.set_fillstyle(fillstyle) + self._point_size_reduction = 0.5 self.verticalOffset = None @@ -324,7 +327,22 @@ """ self.pickradius = d + def get_fillstyle(self): + """ + return the marker fillstyle + """ + return self._fillstyle + def set_fillstyle(self, fs): + """ + Set the marker fill style; full means fill the whole marker. + The other options are for half fills + + ACCEPTS: string ['full' | 'left' | 'right' | 'bottom' | 'top'] + """ + assert fs in ['full', 'left' , 'right' , 'bottom' , 'top'] + self._fillstyle = fs + def set_markevery(self, every): """ Set the markevery property to subsample the plot when using @@ -918,6 +936,10 @@ def _draw_point(self, renderer, gc, path, path_trans): + fs = self.get_fillstyle() + if fs!='full': + raise NotImplementedError('non-full markers have not been implemented for this marker style yet; please contribute') + w = renderer.points_to_pixels(self._markersize) * \ self._point_size_reduction * 0.5 gc.set_snap(renderer.points_to_pixels(self._markersize) > 3.0) @@ -929,6 +951,10 @@ _draw_pixel_transform = Affine2D().translate(-0.5, -0.5) def _draw_pixel(self, renderer, gc, path, path_trans): + fs = self.get_fillstyle() + if fs!='full': + raise NotImplementedError('non-full markers have not been implemented for this marker style yet; please contribute') + rgbFace = self._get_rgb_face() gc.set_snap(False) renderer.draw_markers(gc, Path.unit_rectangle(), @@ -937,6 +963,10 @@ def _draw_circle(self, renderer, gc, path, path_trans): + fs = self.get_fillstyle() + if fs!='full': + raise NotImplementedError('non-full markers have not been implemented for this marker style yet; please contribute') + w = renderer.points_to_pixels(self._markersize) * 0.5 gc.set_snap(renderer.points_to_pixels(self._markersize) > 3.0) rgbFace = self._get_rgb_face() @@ -948,6 +978,11 @@ _triangle_path = Path([[0.0, 1.0], [-1.0, -1.0], [1.0, -1.0], [0.0, 1.0]]) def _draw_triangle_up(self, renderer, gc, path, path_trans): + + fs = self.get_fillstyle() + if fs!='full': + raise NotImplementedError('non-full markers have not been implemented for this marker style yet; please contribute') + gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0) offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset, offset) @@ -957,6 +992,10 @@ def _draw_triangle_down(self, renderer, gc, path, path_trans): + fs = self.get_fillstyle() + if fs!='full': + raise NotImplementedError('non-full markers have not been implemented for this marker style yet; please contribute') + gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0) offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset, -offset) @@ -966,6 +1005,10 @@ def _draw_triangle_left(self, renderer, gc, path, path_trans): + fs = self.get_fillstyle() + if fs!='full': + raise NotImplementedError('non-full markers have not been implemented for this marker style yet; please contribute') + gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0) offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset, offset).rotate_deg(90) @@ -975,6 +1018,10 @@ def _draw_triangle_right(self, renderer, gc, path, path_trans): + fs = self.get_fillstyle() + if fs!='full': + raise NotImplementedError('non-full markers have not been implemented for this marker style yet; please contribute') + gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0) offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset, offset).rotate_deg(-90) @@ -988,11 +1035,31 @@ side = renderer.points_to_pixels(self._markersize) transform = Affine2D().translate(-0.5, -0.5).scale(side) rgbFace = self._get_rgb_face() - renderer.draw_markers(gc, Path.unit_rectangle(), transform, - path, path_trans, rgbFace) + fs = self.get_fillstyle() + if fs=='full': + renderer.draw_markers(gc, Path.unit_rectangle(), transform, + path, path_trans, rgbFace) + else: + # build a bottom filled square out of two rectangles, one + # filled. Use the rotation to support left, right, bottom + # or top + if fs=='bottom': rotate = 0. + elif fs=='top': rotate = 180. + elif fs=='left': rotate = 270. + else: rotate = 90. + bottom = Path([[0.0, 0.0], [1.0, 0.0], [1.0, 0.5], [0.0, 0.5], [0.0, 0.0]]) + top = Path([[0.0, 0.5], [1.0, 0.5], [1.0, 1.0], [0.0, 1.0], [0.0, 0.05]]) + transform = transform.rotate_deg(rotate) + renderer.draw_markers(gc, bottom, transform, + path, path_trans, rgbFace) + renderer.draw_markers(gc, top, transform, + path, path_trans, None) def _draw_diamond(self, renderer, gc, path, path_trans): + fs = self.get_fillstyle() + if fs!='full': + raise NotImplementedError('non-full markers have not been implemented for this marker style yet; please contribute') gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0) side = renderer.points_to_pixels(self._markersize) transform = Affine2D().translate(-0.5, -0.5).rotate_deg(45).scale(side) @@ -1002,6 +1069,9 @@ def _draw_thin_diamond(self, renderer, gc, path, path_trans): + fs = self.get_fillstyle() + if fs!='full': + raise NotImplementedError('non-full markers have not been implemented for this marker style yet; please contribute') gc.set_snap(renderer.points_to_pixels(self._markersize) >= 3.0) offset = renderer.points_to_pixels(self._markersize) transform = Affine2D().translate(-0.5, -0.5) \ @@ -1012,6 +1082,9 @@ def _draw_pentagon(self, renderer, gc, path, path_trans): + fs = self.get_fillstyle() + if fs!='full': + raise NotImplementedError('non-full markers have not been implemented for this marker style yet; please contribute') gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0) offset = 0.5 * renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) @@ -1020,6 +1093,9 @@ path, path_trans, rgbFace) def _draw_star(self, renderer, gc, path, path_trans): + fs = self.get_fillstyle() + if fs!='full': + raise NotImplementedError('non-full markers have not been implemented for this marker style yet; please contribute') gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0) offset = 0.5 * renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) @@ -1030,6 +1106,9 @@ def _draw_hexagon1(self, renderer, gc, path, path_trans): + fs = self.get_fillstyle() + if fs!='full': + raise NotImplementedError('non-full markers have not been implemented for this marker style yet; please contribute') gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0) offset = 0.5 * renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) @@ -1039,6 +1118,9 @@ def _draw_hexagon2(self, renderer, gc, path, path_trans): + fs = self.get_fillstyle() + if fs!='full': + raise NotImplementedError('non-full markers have not been implemented for this marker style yet; please contribute') gc.set_snap(renderer.points_to_pixels(self._markersize) >= 5.0) offset = 0.5 * renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(30) @@ -1203,6 +1285,7 @@ self._markerfacecolor = other._markerfacecolor self._markeredgecolor = other._markeredgecolor self._markeredgewidth = other._markeredgewidth + self._fillstyle = other._fillstyle self._dashSeq = other._dashSeq self._dashcapstyle = other._dashcapstyle self._dashjoinstyle = other._dashjoinstyle This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |