-class PolyBar(PolyPoints):
- """Class to define one or more bars for bar chart. All bars in a
- PolyBar share same style etc.
- - All methods except __init__ are private.
- """
-
- _attributes = {'colour': 'black',
- 'width': 1,
- 'size': 2,
- 'legend': '',
- 'fillcolour': None,
- 'fillstyle': wx.SOLID}
-
- def __init__(self, points, **attr):
- """Creates several bars.
- points - sequence (array, tuple or list) of (x,y) points
- indicating *top left* corner of bar. Can also be
- just one (x,y) tuple if labels attribute is just
- a string (not a list)
- **attr - key word attributes
- Defaults:
- 'colour'= wx.BLACK, - wx.Pen Colour
- 'width'= 1, - Pen width
- 'size'= 2, - Bar size
- 'fillcolour'= same as colour, - wx.Brush Colour
- 'fillstyle'= wx.SOLID, - wx.Brush fill style (use wx.TRANSPARENT for no fill)
- 'legend'= '' - string used for PolyBar legend
- 'labels'= '' - string if only one point, or list of labels, one per point
- Note that if no legend is given the label is used.
- """
- barPoints = [(0,0)] # needed so height of bar can be determined
- self.labels = []
- # add labels and points to above data members:
- try:
- labels = attr['labels']
- del attr['labels']
- except:
- labels = None
- if labels is None: # figure out if we have 1 point or many
- try:
- points[0][0] # ok: we have a seq of points
- barPoints.extend(points)
- except: # failed, so have just one point:
- barPoints.append(points)
- elif isinstance(labels, list) or isinstance(labels, tuple):
- # labels is a sequence so points must be too, with same length:
- self.labels.extend(labels)
- barPoints.extend(points)
- if len(labels) != len(points):
- msg = "%d bar labels missing" % (len(points)-len(labels))
- raise ValueError, msg
- else: # label given, but only one, so must be only one point:
- barPoints.append(points)
- self.labels.append(labels)
-
- PolyPoints.__init__(self, barPoints, attr)
-
- def draw(self, dc, printerScale, coord= None):
- colour = self.attributes['colour']
- width = self.attributes['width'] * printerScale
- size = self.attributes['size'] * printerScale
- fillcolour = self.attributes['fillcolour']
- fillstyle = self.attributes['fillstyle']
-
- dc.SetPen(wx.Pen(colour,int(width)))
- if fillcolour:
- dc.SetBrush(wx.Brush(fillcolour,fillstyle))
- else:
- dc.SetBrush(wx.Brush(colour, fillstyle))
- if coord == None:
- self._drawbar(dc, self.scaled, size)
- else:
- self._drawLegendMarker(dc, coord, size) #draw legend marker
-
- def _drawLegendMarker(self, dc, coord, size):
- fact= 10
- wh= 2*fact
- rect= _Numeric.zeros((len(coord),4),_Numeric.Float)+[0.0,0.0,wh,wh]
- rect[:,0:2]= coord-[fact,fact]
- dc.DrawRectangleList(rect.astype(_Numeric.Int32))
-
- def offset(self, heights, howMany = 1, shift=0.25):
- """Return a list of points, where x's are those of this bar,
- shifted by shift*howMany (in caller's units, not pixel units), and
- heights are given in heights."""
- points = [(point[0][0]+shift*howMany,point[1]) for point
- in zip(self.points[1:], heights)]
- return points
-
- def getSymExtent(self, printerScale):
- """Width and Height of bar symbol"""
- s= 5*self.attributes['size'] * printerScale
- return (s,s)
-
- def getLegend(self):
- """This returns a comma-separated list of bar labels (one string)"""
- try: legendItem = self.attributes['legend']
- except:
- legendItem = ", ".join(self.labels)
- return legendItem
-
- def _drawbar(self, dc, coords, size=1):
- width = 5.0*size
- y0 = coords[0][1]
- bars = []
- for coord in coords[1:]:
- x = coord[0] # - width/2 not as good
- y = coord[1]
- height = int(y0) - int(y)
- bars.append((int(x),int(y),int(width),int(height)))
- #print x,y,width, height
- dc.DrawRectangleList(bars)
-
- def getTicks(self):
- """Get the list of (tick pos, label) pairs for this PolyBar.
- It is unlikely you need this, but it is used by
- getBarTicksGen."""
- ticks = []
- # remember to skip first point:
- for point, label in zip(self.points[1:], self.labels):
- ticks.append((point[0], label))
- return ticks
-
-def getBarTicksGen(*polyBars):
- """Get a function that can be given as xTicks argument when
- calling PolyCanvas.Draw() when plotting one or more PolyBar.
- The returned function allows the bar chart to have the bars
- labelled at the x axis. """
- ticks = []
- for polyBar in polyBars:
- ticks.extend(polyBar.getTicks())
-
- def tickGenerator(lower,upper,gg,ff):
- tickPairs = []
- for tick in ticks:
- if lower <= tick[0] < upper:
- tickPairs.append(tick)
- return tickPairs
-
- return tickGenerator
-
-