def draw(self, renderer, *args, **kwargs): 'Draw the axis lines, grid lines, tick lines and labels' renderer.open_group(__name__) ticklabelBoxes = [] majorTicks = self.get_major_ticks() majorLocs = self._majorLocator() self._majorFormatter.set_locs(majorLocs) majorLabels = [self._majorFormatter(val, i) for i, val in enumerate(majorLocs)] seen = {} interval = self.get_view_interval() for tick, loc, label in zip(majorTicks, majorLocs, majorLabels): if not interval.contains(loc): continue seen[loc] = 1 tick.update_position(loc) tick.set_label1(label) tick.set_label2(label) tick.draw(renderer) extent = tick.label1.get_window_extent(renderer) ticklabelBoxes.append(extent) minorTicks = self.get_minor_ticks() minorLocs = self._minorLocator() self._minorFormatter.set_locs(minorLocs) minorLabels = [self._minorFormatter(val, i) for i, val in enumerate(minorLocs)] for tick, loc, label in zip(minorTicks, minorLocs, minorLabels): if not interval.contains(loc): continue if seen.has_key(loc): continue tick.update_position(loc) tick.set_label(label) tick.draw(renderer) extent = tick.label1.get_window_extent(renderer) ticklabelBoxes.append(extent) # find the tick labels that are close to the axis labels. I # scale up the axis label box to also find the neighbors, not # just the tick labels that actually overlap note we need a # *copy* of the axis label box because we don't wan't to scale # the actual bbox labelBox = self._label.get_window_extent(renderer) self._update_label_postion(ticklabelBoxes) self._label.draw(renderer) # memory leak here, vertical text if 0: # draw the bounding boxes around the text for debug for tick in majorTicks: label = tick.label1 bbox_artist(label, renderer) bbox_artist(self._label, renderer) renderer.close_group(__name__)
def to_rgba_list(self, c): """ Returns a list of rgba tuples. Accepts a single mpl color spec or a sequence of specs. If the sequence is a list, the list items are changed in place. """ # This can be improved after removing float-as-grayscale. if not is_string_like(c): try: N = len(c) # raises TypeError if it is not a sequence # Temporary hack: keep single rgb or rgba from being # treated as grayscale. if N==3 or N==4: L = [x for x in c if x>=0 and x<=1] if len(L) == N: raise ValueError # If c is a list, we need to return the same list but # with modified items so that items can be appended to # it. This is needed for examples/dynamic_collections.py. if not isinstance(c, list): # specific; don't need duck-typing c = list(c) self._gray = False for i, cc in enumerate(c): c[i] = self.to_rgba(cc, warn=False) # change in place if self._gray: msg = "In argument %s: use string, not float, for grayscale" % str(c) warnings.warn(msg, DeprecationWarning) return c except (ValueError, TypeError): pass try: return [self.to_rgba(c)] except (ValueError, TypeError): raise TypeError('c must be a matplotlib color arg or a sequence of them')
def key_press_callback(self, event): 'whenever a key is pressed' if not event.inaxes: return if event.key=='t': self.showverts = not self.showverts self.line.set_visible(self.showverts) if not self.showverts: self._ind = None elif event.key=='d': ind = self.get_ind_under_point(event) if ind is not None: self.poly.verts = [tup for i,tup in enumerate(self.poly.verts) if i!=ind] self.line.set_data(zip(*self.poly.verts)) elif event.key=='i': xys = self.poly.get_transform().seq_xy_tups(self.poly.verts) p = event.x, event.y # display coords for i in range(len(xys)-1): s0 = xys[i] s1 = xys[i+1] d = dist_point_to_segment(p, s0, s1) if d<=self.epsilon: self.poly.verts.insert(i+1, (event.xdata, event.ydata)) self.line.set_data(zip(*self.poly.verts)) break self.canvas.draw()
def press_zoom(self, event): "the press mouse button in zoom to rect mode callback" if event.button == 1: self._button_pressed = 1 elif event.button == 3: self._button_pressed = 3 else: self._button_pressed = None return x, y = event.x, event.y # push the current view to define home if stack is empty if self._views.empty(): self.push_current() for i, a in enumerate(self.canvas.figure.get_axes()): if event.inaxes == a: xmin, xmax = a.get_xlim() ymin, ymax = a.get_ylim() lim = xmin, xmax, ymin, ymax self._xypress = x, y, a, i, lim, a.transData.deepcopy() break self.press(event)
def inline_labels(self, levels, contours, colors, fslist, fmt): trans = self.ax.transData contourNum = 0 for lev, con, color, fsize in zip(levels, contours, colors, fslist): toremove = [] toadd = [] lw = self.get_label_width(lev, fmt, fsize) for segNum, linecontour in enumerate(con._segments): key = contourNum, segNum # for closed contours add one more point to # avoid division by zero if linecontour[0] == linecontour[-1]: linecontour.append(linecontour[1]) # transfer all data points to screen coordinates slc = trans.seq_xy_tups(linecontour) if self.print_label(slc,lw): x,y, rotation, ind = self.locate_label(slc, lw) # transfer the location of the label back to # data coordinates dx,dy = trans.inverse_xy_tup((x,y)) t = Text(dx, dy, rotation = rotation, horizontalalignment='center', verticalalignment='center') self.labeld[key] = t text = self.get_text(lev,fmt) self.set_label_props(t, text, color) self.cl.append(t) new = self.break_linecontour(linecontour, rotation, lw, ind) for c in new: toadd.append(c) toremove.append(linecontour) for c in toremove: con._segments.remove(c) for c in toadd: con._segments.append(c) contourNum += 1
def press_pan(self, event): 'the press mouse button in pan/zoom mode callback' if event.button == 1: self._button_pressed=1 elif event.button == 3: self._button_pressed=3 else: self._button_pressed=None return x, y = event.x, event.y # push the current view to define home if stack is empty if self._views.empty(): self.push_current() for i, a in enumerate(self.canvas.figure.get_axes()): if event.inaxes == a and event.inaxes.get_navigate(): xmin, xmax = a.get_xlim() ymin, ymax = a.get_ylim() lim = xmin, xmax, ymin, ymax self._xypress = x, y, a, i, lim,a.transData.deepcopy() self.canvas.mpl_disconnect(self._idDrag) self._idDrag=self.canvas.mpl_connect('motion_notify_event', self.drag_pan) break self.press(event)
def press_pan(self, event): 'the press mouse button in pan/zoom mode callback' if event.button == 1: self._button_pressed = 1 elif event.button == 3: self._button_pressed = 3 else: self._button_pressed = None return x, y = event.x, event.y # push the current view to define home if stack is empty if self._views.empty(): self.push_current() for i, a in enumerate(self.canvas.figure.get_axes()): if event.inaxes == a: xmin, xmax = a.get_xlim() ymin, ymax = a.get_ylim() lim = xmin, xmax, ymin, ymax self._xypress = x, y, a, i, lim, a.transData.deepcopy() self.canvas.mpl_disconnect(self._idDrag) self._idDrag = self.canvas.mpl_connect('motion_notify_event', self.drag_pan) break self.press(event)
def key_press_callback(self, event): 'whenever a key is pressed' if not event.inaxes: return if event.key == 't': self.showverts = not self.showverts self.line.set_visible(self.showverts) if not self.showverts: self._ind = None elif event.key == 'd': ind = self.get_ind_under_point(event) if ind is not None: self.poly.verts = [ tup for i, tup in enumerate(self.poly.verts) if i != ind ] self.line.set_data(zip(*self.poly.verts)) elif event.key == 'i': xys = self.poly.get_transform().seq_xy_tups(self.poly.verts) p = event.x, event.y # display coords for i in range(len(xys) - 1): s0 = xys[i] s1 = xys[i + 1] d = dist_point_to_segment(p, s0, s1) if d <= self.epsilon: self.poly.verts.insert(i + 1, (event.xdata, event.ydata)) self.line.set_data(zip(*self.poly.verts)) break self.canvas.draw()
def draw_regpoly_collection(self, clipbox, offsets, transOffset, verts, sizes, facecolors, edgecolors, linewidths, antialiaseds): """ Draw a regular poly collection offsets - is a sequence is x,y tuples transOffset - maps this to display coords verts - are the vertices of the regular polygon at the origin sizes are the area of the circle that circumscribes the polygon in points^2 facecolors and edgecolors are a sequence of RGBA tuples linewidths are a sequence of linewidths antialiaseds are a sequence of 0,1 integers whether to use aa """ gc = self.new_gc() if clipbox is not None: gc.set_clip_rectangle(clipbox.get_bounds()) xverts, yverts = zip(*verts) xverts = asarray(xverts) yverts = asarray(yverts) Nface = len(facecolors) Nedge = len(edgecolors) Nlw = len(linewidths) Naa = len(antialiaseds) Nsizes = len(sizes) for i, loc in enumerate(offsets): xo, yo = transOffset.xy_tup(loc) #print 'xo, yo', loc, (xo, yo) scale = sizes[i % Nsizes] thisxverts = scale * xverts + xo thisyverts = scale * yverts + yo #print 'xverts', xverts rf, gf, bf, af = facecolors[i % Nface] re, ge, be, ae = edgecolors[i % Nedge] if af == 0: rgbFace = None else: rgbFace = rf, gf, bf # the draw_poly interface can't handle separate alphas for # edge and face so we'll just use alpha = max(af, ae) gc.set_foreground((re, ge, be), isRGB=True) gc.set_alpha(alpha) gc.set_linewidth(linewidths[i % Nlw]) gc.set_antialiased(antialiaseds[i % Naa]) #print 'verts', zip(thisxverts, thisyverts) self.draw_polygon(gc, rgbFace, zip(thisxverts, thisyverts))
def draw_regpoly_collection( self, clipbox, offsets, transOffset, verts, sizes, facecolors, edgecolors, linewidths, antialiaseds): """ Draw a regular poly collection offsets - is a sequence is x,y tuples transOffset - maps this to display coords verts - are the vertices of the regular polygon at the origin sizes are the area of the circle that circumscribes the polygon in points^2 facecolors and edgecolors are a sequence of RGBA tuples linewidths are a sequence of linewidths antialiaseds are a sequence of 0,1 integers whether to use aa """ gc = self.new_gc() if clipbox is not None: gc.set_clip_rectangle(clipbox.get_bounds()) xverts, yverts = zip(*verts) xverts = asarray(xverts) yverts = asarray(yverts) Nface = len(facecolors) Nedge = len(edgecolors) Nlw = len(linewidths) Naa = len(antialiaseds) Nsizes = len(sizes) for i, loc in enumerate(offsets): xo,yo = transOffset.xy_tup(loc) #print 'xo, yo', loc, (xo, yo) scale = sizes[i % Nsizes] thisxverts = scale*xverts + xo thisyverts = scale*yverts + yo #print 'xverts', xverts rf,gf,bf,af = facecolors[i % Nface] re,ge,be,ae = edgecolors[i % Nedge] if af==0: rgbFace = None else: rgbFace = rf,gf,bf # the draw_poly interface can't handle separate alphas for # edge and face so we'll just use alpha = max(af,ae) gc.set_foreground( (re,ge,be), isRGB=True) gc.set_alpha( alpha ) gc.set_linewidth( linewidths[i % Nlw] ) gc.set_antialiased( antialiaseds[i % Naa] ) #print 'verts', zip(thisxverts, thisyverts) self.draw_polygon(gc, rgbFace, zip(thisxverts, thisyverts))
def _update_view(self): 'update the viewlim from the view stack for each axes' lims = self._views() if lims is None: return for i, a in enumerate(self.canvas.figure.get_axes()): xmin, xmax, ymin, ymax = lims[i] a.set_xlim((xmin, xmax)) a.set_ylim((ymin, ymax)) self.draw()
def changed(self): colors = [ (tuple(rgba),) for rgba in self.to_rgba(self.levels)] contourNum = 0 for color, collection in zip(colors, self.collections): collection.set_color(color) Ncolor = len(color) # collections could have more than 1 in principle for segNum, segment in enumerate(collection._segments): key = contourNum, segNum t = self.labeld.get(key) if t is not None: t.set_color(color[segNum%Ncolor]) contourNum += 1 ScalarMappable.changed(self)
def set_ticklabels(self, ticklabels, *args, **kwargs): """ Set the text values of the tick labels. Return a list of Text instances. ACCEPTS: sequence of strings""" ticklabels = [str(l) for l in ticklabels] self.set_major_formatter(FixedFormatter(ticklabels)) ret = [] for i, tick in enumerate(self.get_major_ticks()): if i < len(ticklabels): ret.append(tick.label1) tick.label1.update(kwargs) return ret
def set_ticklabels(self, ticklabels, *args, **kwargs): """ Set the text values of the tick labels. ticklabels is a sequence of strings. Return a list of Text instances """ ticklabels = [str(l) for l in ticklabels] self.set_major_formatter(FixedFormatter(ticklabels)) override = {} override = _process_text_args(override, *args, **kwargs) ret = [] for i, tick in enumerate(self.get_major_ticks()): if i < len(ticklabels): ret.append(tick.label1) tick.label1.update(override) return ret
def set_ticklabels(self, ticklabels, *args, **kwargs): """ Set the text values of the tick labels. ticklabels is a sequence of strings. Return a list of Text instances """ ticklabels = [str(l) for l in ticklabels] self.set_major_formatter( FixedFormatter(ticklabels) ) override = {} override = _process_text_args(override, *args, **kwargs) ret = [] for i, tick in enumerate(self.get_major_ticks()): if i<len(ticklabels): ret.append(tick.label1) tick.label1.update(override) return ret
def labels(self, inline): levels = self.label_levels fslist = self.fslist trans = self.ax.transData colors = self.label_mappable.to_rgba(self.label_cvalues) fmt = self.fmt for icon, lev, color, cvalue, fsize in zip(self.label_indices, self.label_levels, colors, self.label_cvalues, fslist): con = self.collections[icon] toremove = [] toadd = [] lw = self.get_label_width(lev, fmt, fsize) for segNum, linecontour in enumerate(con._segments): # for closed contours add one more point to # avoid division by zero if linecontour[0] == linecontour[-1]: linecontour.append(linecontour[1]) # transfer all data points to screen coordinates slc = trans.seq_xy_tups(linecontour) if self.print_label(slc, lw): x, y, rotation, ind = self.locate_label(slc, lw) # transfer the location of the label back to # data coordinates dx, dy = trans.inverse_xy_tup((x, y)) t = Text(dx, dy, rotation=rotation, horizontalalignment='center', verticalalignment='center') text = self.get_text(lev, fmt) self.set_label_props(t, text, color) self.cl.append(t) self.cl_cvalues.append(cvalue) if inline: new = self.break_linecontour(linecontour, rotation, lw, ind) toadd.extend(new) #for c in new: toadd.append(c) toremove.append(linecontour) for c in toremove: con._segments.remove(c) for c in toadd: con._segments.append(c)
def labels(self, inline): levels = self.label_levels fslist = self.fslist trans = self.ax.transData colors = self.label_mappable.to_rgba(self.label_cvalues) fmt = self.fmt for icon, lev, color, cvalue, fsize in zip(self.label_indices, self.label_levels, colors, self.label_cvalues, fslist): con = self.collections[icon] toremove = [] toadd = [] lw = self.get_label_width(lev, fmt, fsize) for segNum, linecontour in enumerate(con._segments): # for closed contours add one more point to # avoid division by zero if linecontour[0] == linecontour[-1]: linecontour.append(linecontour[1]) # transfer all data points to screen coordinates slc = trans.seq_xy_tups(linecontour) if self.print_label(slc,lw): x,y, rotation, ind = self.locate_label(slc, lw) # transfer the location of the label back to # data coordinates dx,dy = trans.inverse_xy_tup((x,y)) t = Text(dx, dy, rotation = rotation, horizontalalignment='center', verticalalignment='center') text = self.get_text(lev,fmt) self.set_label_props(t, text, color) self.cl.append(t) self.cl_cvalues.append(cvalue) if inline: new = self.break_linecontour(linecontour, rotation, lw, ind) toadd.extend(new) #for c in new: toadd.append(c) toremove.append(linecontour) for c in toremove: con._segments.remove(c) for c in toadd: con._segments.append(c)
def set_ticklabels(self, ticklabels, *args, **kwargs): """ Set the text values of the tick labels. Return a list of Text instances. Use kwarg minor=True to select minor ticks. ACCEPTS: sequence of strings """ #ticklabels = [str(l) for l in ticklabels] minor = kwargs.pop('minor', False) if minor: self.set_minor_formatter(FixedFormatter(ticklabels)) ticks = self.get_minor_ticks() else: self.set_major_formatter( FixedFormatter(ticklabels) ) ticks = self.get_major_ticks() ret = [] for i, tick in enumerate(ticks): if i<len(ticklabels): tick.label1.set_text(ticklabels[i]) ret.append(tick.label1) tick.label1.update(kwargs) return ret
def to_rgba_list(self, c): """ Returns a list of rgba tuples. Accepts a single mpl color spec or a sequence of specs. If the sequence is a list, the list items are changed in place. """ # This can be improved after removing float-as-grayscale. if not is_string_like(c): try: N = len(c) # raises TypeError if it is not a sequence # Temporary hack: keep single rgb or rgba from being # treated as grayscale. if N == 3 or N == 4: L = [x for x in c if x >= 0 and x <= 1] if len(L) == N: raise ValueError # If c is a list, we need to return the same list but # with modified items so that items can be appended to # it. This is needed for examples/dynamic_collections.py. if not isinstance(c, list): # specific; don't need duck-typing c = list(c) self._gray = False for i, cc in enumerate(c): c[i] = self.to_rgba(cc, warn=False) # change in place if self._gray: msg = "In argument %s: use string, not float, for grayscale" % str( c) warnings.warn(msg, DeprecationWarning) return c except (ValueError, TypeError): pass try: return [self.to_rgba(c)] except (ValueError, TypeError): raise TypeError( 'c must be a matplotlib color arg or a sequence of them')
def press_zoom(self, event): 'the press mouse button in zoom to rect mode callback' if event.button == 1: self._button_pressed = 1 elif event.button == 3: self._button_pressed = 3 else: self._button_pressed = None return x, y = event.x, event.y # push the current view to define home if stack is empty if self._views.empty(): self.push_current() for i, a in enumerate(self.canvas.figure.get_axes()): if event.inaxes == a: xmin, xmax = a.get_xlim() ymin, ymax = a.get_ylim() lim = xmin, xmax, ymin, ymax self._xypress = x, y, a, i, lim, a.transData.deepcopy() break self.press(event)
def draw(self, renderer, *args, **kwargs): 'Draw the axis lines, grid lines, tick lines and labels' if not self.get_visible(): return renderer.open_group(__name__) ticklabelBoxes = [] ticklabelBoxes2 = [] majorTicks = self.get_major_ticks() majorLocs = self.major.locator() self.major.formatter.set_locs(majorLocs) majorLabels = [ self.major.formatter(val, i) for i, val in enumerate(majorLocs) ] seen = {} interval = self.get_view_interval() for tick, loc, label in zip(majorTicks, majorLocs, majorLabels): if tick is None: continue if not interval.contains(loc): continue seen[loc] = 1 tick.update_position(loc) tick.set_label1(label) tick.set_label2(label) tick.draw(renderer) if tick.label1On: extent = tick.label1.get_window_extent(renderer) ticklabelBoxes.append(extent) if tick.label2On: extent = tick.label2.get_window_extent(renderer) ticklabelBoxes2.append(extent) minorTicks = self.get_minor_ticks() minorLocs = self.minor.locator() self.minor.formatter.set_locs(minorLocs) minorLabels = [ self.minor.formatter(val, i) for i, val in enumerate(minorLocs) ] for tick, loc, label in zip(minorTicks, minorLocs, minorLabels): if tick is None: continue if not interval.contains(loc): continue if seen.has_key(loc): continue tick.update_position(loc) tick.set_label1(label) tick.set_label2(label) tick.draw(renderer) if tick.label1On: extent = tick.label1.get_window_extent(renderer) ticklabelBoxes.append(extent) if tick.label2On: extent = tick.label2.get_window_extent(renderer) ticklabelBoxes2.append(extent) # scale up the axis label box to also find the neighbors, not # just the tick labels that actually overlap note we need a # *copy* of the axis label box because we don't wan't to scale # the actual bbox self._update_label_position(ticklabelBoxes, ticklabelBoxes2) self.label.draw(renderer) self._update_offset_text_position(ticklabelBoxes, ticklabelBoxes2) self.offsetText.set_text(self.major.formatter.get_offset()) self.offsetText.draw(renderer) if 0: # draw the bounding boxes around the text for debug for tick in majorTicks: label = tick.label1 bbox_artist(label, renderer) bbox_artist(self.label, renderer) renderer.close_group(__name__)
def clabel(self, *args, **kwargs): """ clabel(CS, **kwargs) - add labels to line contours in CS, where CS is a ContourSet object returned by contour. clabel(CS, V, **kwargs) - only label contours listed in V keyword arguments: * fontsize = None: as described in http://matplotlib.sf.net/fonts.html * colors = None: - a tuple of matplotlib color args (string, float, rgb, etc), different labels will be plotted in different colors in the order specified - one string color, e.g. colors = 'r' or colors = 'red', all labels will be plotted in this color - if colors == None, the color of each label matches the color of the corresponding contour * inline = True: controls whether the underlying contour is removed (inline = True) or not (False) * fmt = '%1.3f': a format string for the label """ fontsize = kwargs.get('fontsize', None) inline = kwargs.get('inline', 1) self.fmt = kwargs.get('fmt', '%1.3f') colors = kwargs.get('colors', None) if len(args) == 0: levels = self.levels indices = range(len(self.levels)) elif len(args) == 1: levlabs = list(args[0]) indices, levels = [], [] for i, lev in enumerate(self.levels): if lev in levlabs: indices.append(i) levels.append(lev) if len(levels) < len(levlabs): msg = "Specified levels " + str(levlabs) msg += "\n don't match available levels " msg += str(self.levels) raise ValueError(msg) else: raise TypeError("Illegal arguments to clabel, see help(clabel)") self.label_levels = levels self.label_indices = indices self.fp = FontProperties() if fontsize == None: font_size = int(self.fp.get_size_in_points()) else: if type(fontsize) not in [int, float, str]: raise TypeError("Font size must be an integer number.") # Can't it be floating point, as indicated in line above? else: if type(fontsize) == str: font_size = int(self.fp.get_size_in_points()) else: self.fp.set_size(fontsize) font_size = fontsize self.fslist = [font_size] * len(levels) if colors == None: self.label_mappable = self self.label_cvalues = take(self.cvalues, self.label_indices) else: cmap = ListedColormap(colors, N=len(self.label_levels)) self.label_cvalues = range(len(self.label_levels)) self.label_mappable = ScalarMappable(cmap = cmap, norm = no_norm()) #self.cl = [] # Initialized in ContourSet.__init__ #self.cl_cvalues = [] # same self.cl_xy = [] self.labels(inline) for label in self.cl: self.ax.add_artist(label) self.label_list = silent_list('Text', self.cl) return self.label_list
def _get_layout(self, renderer): key = self.get_prop_tup() if self.cached.has_key(key): return self.cached[key] horizLayout = [] thisx, thisy = 0.0, 0.0 xmin, ymin = 0.0, 0.0 width, height = 0.0, 0.0 lines = self._text.split('\n') whs = npy.zeros((len(lines), 2)) horizLayout = npy.zeros((len(lines), 4)) # Find full vertical extent of font, # including ascenders and descenders: tmp, heightt, bl = renderer.get_text_width_height_descent( 'lp', self._fontproperties, ismath=False) offsety = heightt * self._linespacing baseline = None for i, line in enumerate(lines): w, h, d = renderer.get_text_width_height_descent( line, self._fontproperties, ismath=self.is_math_text(line)) if baseline is None: baseline = h - d whs[i] = w, h horizLayout[i] = thisx, thisy, w, h thisy -= offsety width = max(width, w) ymin = horizLayout[-1][1] ymax = horizLayout[0][1] + horizLayout[0][3] height = ymax-ymin xmax = xmin + width # get the rotation matrix M = Affine2D().rotate_deg(self.get_rotation()) offsetLayout = npy.zeros((len(lines), 2)) offsetLayout[:] = horizLayout[:, 0:2] # now offset the individual text lines within the box if len(lines)>1: # do the multiline aligment malign = self._get_multialignment() if malign == 'center': offsetLayout[:, 0] += width/2.0 - horizLayout[:, 2] / 2.0 elif malign == 'right': offsetLayout[:, 0] += width - horizLayout[:, 2] # the corners of the unrotated bounding box cornersHoriz = npy.array( [(xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)], npy.float_) # now rotate the bbox cornersRotated = M.transform(cornersHoriz) txs = cornersRotated[:, 0] tys = cornersRotated[:, 1] # compute the bounds of the rotated box xmin, xmax = txs.min(), txs.max() ymin, ymax = tys.min(), tys.max() width = xmax - xmin height = ymax - ymin # Now move the box to the targe position offset the display bbox by alignment 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 if valign=='center': offsety = (ymin + height/2.0) elif valign=='top': offsety = (ymin + height) elif valign=='baseline': offsety = (ymin + height) + baseline else: offsety = ymin xmin -= offsetx ymin -= offsety bbox = Bbox.from_bounds(xmin, ymin, width, height) # now rotate the positions around the first x,y position xys = M.transform(offsetLayout) xys -= (offsetx, offsety) xs, ys = xys[:, 0], xys[:, 1] ret = bbox, zip(lines, whs, xs, ys) self.cached[key] = ret return ret
def clabel(self, *args, **kwargs): """ clabel(CS, **kwargs) - add labels to line contours in CS, where CS is a ContourSet object returned by contour. clabel(CS, V, **kwargs) - only label contours listed in V keyword arguments: * fontsize = None: as described in http://matplotlib.sf.net/fonts.html * colors = None: - a tuple of matplotlib color args (string, float, rgb, etc), different labels will be plotted in different colors in the order specified - one string color, e.g. colors = 'r' or colors = 'red', all labels will be plotted in this color - if colors == None, the color of each label matches the color of the corresponding contour * inline = True: controls whether the underlying contour is removed (inline = True) or not (False) * fmt = '%1.3f': a format string for the label """ fontsize = kwargs.get('fontsize', None) inline = kwargs.get('inline', 1) self.fmt = kwargs.get('fmt', '%1.3f') colors = kwargs.get('colors', None) if len(args) == 0: levels = self.levels indices = range(len(self.levels)) elif len(args) == 1: levlabs = list(args[0]) indices, levels = [], [] for i, lev in enumerate(self.levels): if lev in levlabs: indices.append(i) levels.append(lev) if len(levels) < len(levlabs): msg = "Specified levels " + str(levlabs) msg += "\n don't match available levels " msg += str(self.levels) raise ValueError(msg) else: raise TypeError("Illegal arguments to clabel, see help(clabel)") self.label_levels = levels self.label_indices = indices self.fp = FontProperties() if fontsize == None: font_size = int(self.fp.get_size_in_points()) else: if type(fontsize) not in [int, float, str]: raise TypeError("Font size must be an integer number.") # Can't it be floating point, as indicated in line above? else: if type(fontsize) == str: font_size = int(self.fp.get_size_in_points()) else: self.fp.set_size(fontsize) font_size = fontsize self.fslist = [font_size] * len(levels) if colors == None: self.label_mappable = self self.label_cvalues = take(self.cvalues, self.label_indices) else: cmap = ListedColormap(colors, N=len(self.label_levels)) self.label_cvalues = range(len(self.label_levels)) self.label_mappable = ScalarMappable(cmap=cmap, norm=no_norm()) #self.cl = [] # Initialized in ContourSet.__init__ #self.cl_cvalues = [] # same self.cl_xy = [] self.labels(inline) for label in self.cl: self.ax.add_artist(label) self.label_list = silent_list('Text', self.cl) return self.label_list
def draw(self, renderer, *args, **kwargs): 'Draw the axis lines, grid lines, tick lines and labels' if not self.get_visible(): return renderer.open_group(__name__) ticklabelBoxes = [] ticklabelBoxes2 = [] majorTicks = self.get_major_ticks() majorLocs = self.major.locator() self.major.formatter.set_locs(majorLocs) majorLabels = [self.major.formatter(val, i) for i, val in enumerate(majorLocs)] seen = {} interval = self.get_view_interval() for tick, loc, label in zip(majorTicks, majorLocs, majorLabels): if tick is None: continue if not interval.contains(loc): continue seen[loc] = 1 tick.update_position(loc) tick.set_label1(label) tick.set_label2(label) tick.draw(renderer) if tick.label1On: extent = tick.label1.get_window_extent(renderer) ticklabelBoxes.append(extent) if tick.label2On: extent = tick.label2.get_window_extent(renderer) ticklabelBoxes2.append(extent) minorTicks = self.get_minor_ticks() minorLocs = self.minor.locator() self.minor.formatter.set_locs(minorLocs) minorLabels = [self.minor.formatter(val, i) for i, val in enumerate(minorLocs)] for tick, loc, label in zip(minorTicks, minorLocs, minorLabels): if tick is None: continue if not interval.contains(loc): continue if seen.has_key(loc): continue tick.update_position(loc) tick.set_label1(label) tick.set_label2(label) tick.draw(renderer) if tick.label1On: extent = tick.label1.get_window_extent(renderer) ticklabelBoxes.append(extent) if tick.label2On: extent = tick.label2.get_window_extent(renderer) ticklabelBoxes2.append(extent) # scale up the axis label box to also find the neighbors, not # just the tick labels that actually overlap note we need a # *copy* of the axis label box because we don't wan't to scale # the actual bbox self._update_label_position(ticklabelBoxes, ticklabelBoxes2) self.label.draw(renderer) self._update_offset_text_position(ticklabelBoxes, ticklabelBoxes2) self.offsetText.set_text( self.major.formatter.get_offset() ) self.offsetText.draw(renderer) if 0: # draw the bounding boxes around the text for debug for tick in majorTicks: label = tick.label1 bbox_artist(label, renderer) bbox_artist(self.label, renderer) renderer.close_group(__name__)
def _get_layout(self, renderer): key = self.get_prop_tup() if self.cached.has_key(key): return self.cached[key] horizLayout = [] thisx, thisy = 0.0, 0.0 xmin, ymin = 0.0, 0.0 width, height = 0.0, 0.0 lines = self._text.split('\n') whs = npy.zeros((len(lines), 2)) horizLayout = npy.zeros((len(lines), 4)) # Find full vertical extent of font, # including ascenders and descenders: tmp, heightt, bl = renderer.get_text_width_height_descent( 'lp', self._fontproperties, ismath=False) offsety = heightt * self._linespacing baseline = None for i, line in enumerate(lines): w, h, d = renderer.get_text_width_height_descent( line, self._fontproperties, ismath=self.is_math_text(line)) if baseline is None: baseline = h - d whs[i] = w, h horizLayout[i] = thisx, thisy, w, h thisy -= offsety width = max(width, w) ymin = horizLayout[-1][1] ymax = horizLayout[0][1] + horizLayout[0][3] height = ymax - ymin xmax = xmin + width # get the rotation matrix M = Affine2D().rotate_deg(self.get_rotation()) offsetLayout = npy.zeros((len(lines), 2)) offsetLayout[:] = horizLayout[:, 0:2] # now offset the individual text lines within the box if len(lines) > 1: # do the multiline aligment malign = self._get_multialignment() if malign == 'center': offsetLayout[:, 0] += width / 2.0 - horizLayout[:, 2] / 2.0 elif malign == 'right': offsetLayout[:, 0] += width - horizLayout[:, 2] # the corners of the unrotated bounding box cornersHoriz = npy.array([(xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)], npy.float_) # now rotate the bbox cornersRotated = M.transform(cornersHoriz) txs = cornersRotated[:, 0] tys = cornersRotated[:, 1] # compute the bounds of the rotated box xmin, xmax = txs.min(), txs.max() ymin, ymax = tys.min(), tys.max() width = xmax - xmin height = ymax - ymin # Now move the box to the targe position offset the display bbox by alignment 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 if valign == 'center': offsety = (ymin + height / 2.0) elif valign == 'top': offsety = (ymin + height) elif valign == 'baseline': offsety = (ymin + height) + baseline else: offsety = ymin xmin -= offsetx ymin -= offsety bbox = Bbox.from_bounds(xmin, ymin, width, height) # now rotate the positions around the first x,y position xys = M.transform(offsetLayout) xys -= (offsetx, offsety) xs, ys = xys[:, 0], xys[:, 1] ret = bbox, zip(lines, whs, xs, ys) self.cached[key] = ret return ret