def __init__(self, x=0, y=0, text='', color=None, # defaults to rc params verticalalignment='bottom', horizontalalignment='left', multialignment=None, fontproperties=None, # defaults to FontProperties() rotation=None, linespacing=None, **kwargs ): Artist.__init__(self) if color is None: colors= rcParams['text.color'] if fontproperties is None: fontproperties = FontProperties() elif is_string_like(fontproperties): fontproperties = FontProperties(fontproperties) self._animated = False # if is_string_like(text): # text = [text] self._textobjs = [Text(x[ind], y[ind], text[ind], color, verticalalignment, horizontalalignment, multialignment, fontproperties, rotation, linespacing, **kwargs) for ind in xrange(len(x))] self.update(kwargs)
def poly_changed(self, poly): """ Changed Polygon """ # this method is called whenever the polygon object is called # only copy the artist props to the line (except visibility) vis = self.line.get_visible() Artist.update_from(self.line, poly) self.line.set_visible(vis) # don't use the poly visibility state
def __init__(self, graph, bbox, palette=None, *args, **kwds): """Constructs a graph artist that draws the given graph within the given bounding box. `graph` must be an instance of `igraph.Graph`. `bbox` must either be an instance of `igraph.drawing.BoundingBox` or a 4-tuple (`left`, `top`, `width`, `height`). The tuple will be passed on to the constructor of `BoundingBox`. `palette` is an igraph palette that is used to transform numeric color IDs to RGB values. If `None`, a default grayscale palette is used from igraph. All the remaining positional and keyword arguments are passed on intact to `igraph.Graph.__plot__`. """ Artist.__init__(self) if not isinstance(graph, ig.Graph): raise TypeError("expected igraph.Graph, got %r" % type(graph)) self.graph = graph self.palette = palette or ig.palettes["rainbow"] self.bbox = ig.BoundingBox(bbox) self.args = args self.kwds = kwds
def __init__( self, x=0, y=0, text='', color=None, # defaults to rc params verticalalignment='bottom', horizontalalignment='left', multialignment=None, fontproperties=None, # defaults to FontProperties() rotation=None, linespacing=None, **kwargs): Artist.__init__(self) if color is None: colors = rcParams['text.color'] if fontproperties is None: fontproperties = FontProperties() elif is_string_like(fontproperties): fontproperties = FontProperties(fontproperties) self._animated = False # if is_string_like(text): # text = [text] self._textobjs = [ Text(x[ind], y[ind], text[ind], color, verticalalignment, horizontalalignment, multialignment, fontproperties, rotation, linespacing, **kwargs) for ind in xrange(len(x)) ] self.update(kwargs)
def poly_changed(self, controlpoly, curve_r): vis = self.line_poly.get_visible() Artist.update_from(self.line_poly, controlpoly) self.line_poly.set_visible(vis) vis = self.line_r.get_visible() Artist.update_from(self.line_r, curve_r) self.line_r.set_visible(vis) return
def delete_oldest_record(self): ''' delete the oldest plotting ''' try: p = self.plot_record.pop(0) Artist.remove(p.point) except Exception as e: print e pass
def __init__ ( self, x, boxstats, offset, **kwargs ): Artist.__init__ ( self ) self.x = x self.boxstats = boxstats self.notch = kwargs.setdefault ( 'notch', 0 ) self.vert = kwargs.setdefault ( 'vert', 0 ) self.color = kwargs.setdefault ( 'color', [0,0,0] ) self.offset = offset self.lw = kwargs.setdefault ( 'linewidth', 1 )
def poly_changed(self, poly): 'this method is called whenever the polygon object is called' # only copy the artist props to the line (except visibility) #plt.cla() vis = self.line.get_visible() Artist.update_from(self.line, poly) self.line.set_visible(vis) # don't use the poly visibility state #os.system('rm -f updated_model') '''
def points_changed(self, points): """This method is called whenever the points object is called.""" # Only copy the artist props to the line (except visibility). vis = self.line.get_visible() Artist.update_from(self.line, points) # Don't use the points visibility state. self.line.set_visible(vis) if self.verbose: print("\nPoints modified.")
def __init__(self, axis, axisnum, spine): self._axis = axis self._axisnum = axisnum self.line = spine if isinstance(axis, XAxis): self._axis_direction = ["bottom", "top"][axisnum-1] elif isinstance(axis, YAxis): self._axis_direction = ["left", "right"][axisnum-1] else: raise ValueError("axis must be instance of XAxis or YAxis : %s is provided" % (axis,)) Artist.__init__(self)
def __init__(self, color, linewidth, xbounds, ybounds): """ color: str indicating color of line linewidth: width of line to draw xbounds, ybounds: tuple (min,max) of data on x and y axis """ Artist.__init__(self) self.color = color self.linewidth = linewidth self.xbounds = xbounds self.ybounds = ybounds
def __init__(self, graph, bbox, palette=None, *args, **kwds): Artist.__init__(self) if not isinstance(graph, Graph): raise TypeError("expected igraph.Graph, got %r" % type(graph)) self.graph = graph self.palette = palette or palettes["gray"] self.bbox = BoundingBox(bbox) self.args = args self.kwds = kwds
def __init__(self, graph, figsize, dpi, palette=None, *args, **kwds): Artist.__init__(self) if not isinstance(graph, Graph): raise TypeError("expected igraph.Graph, got %r" % type(graph)) self.graph = graph self.palette = palette or palettes["gray"] self.figsize = figsize self.dpi = dpi self.args = args self.kwds = kwds
def __init__(self, svg, x=0, y=0, xscale=1, yscale=1, **kwargs): """ Creates an object instance. svg should be an instance of :class:`rsvg.Handle`. """ Artist.__init__(self) self._svg = svg self.set_x(x) self.set_y(y) self.set_xscale(xscale) self.set_yscale(yscale) self.update(kwargs)
def __init__(self, xmax, barwidth, color=None, linewidth=None): """ color: color to use for bottom line linewidth: width of bottom line """ Artist.__init__(self) if color is None: color = (.5, .5, .5) if linewidth is None: linewidth = 3 self.color = color self.linewidth = linewidth self.xmax = xmax self.barwidth = barwidth
def removeElement(self, element: Artist): """ remove an Artis from the figure """ # create_key = key+".new" created_by_pylustrator = (element, ".new") in self.changes # delete changes related to this element keys = [k for k in self.changes] for reference_obj, reference_command in keys: if reference_obj == element: del self.changes[reference_obj, reference_command] if not created_by_pylustrator: self.addChange(element, ".set_visible(False)") element.set_visible(False) else: element.remove() self.figure.selection.remove_target(element)
def get_picked_element(self, event: MouseEvent, element: Artist = None, picked_element: Artist = None, last_selected: Artist = None): """ get the picked element that an event refers to. To implement selection of elements at the back with multiple clicks. """ # start with the figure if element is None: element = self.figure finished = False # iterate over all children for child in sorted(element.get_children(), key=lambda x: x.get_zorder()): # check if the element is contained in the event and has an active dragger #if child.contains(event)[0] and ((getattr(child, "_draggable", None) and getattr(child, "_draggable", # None).connected) or isinstance(child, GrabberGeneric) or isinstance(child, GrabbableRectangleSelection)): if child.get_visible() and child.contains(event)[0] and ( child.pickable() or isinstance(child, GrabberGeneric) ) and not (child.get_label() is not None and child.get_label().startswith("_")): # if the element is the last selected, finish the search if child == last_selected: return picked_element, True # use this element as the current best matching element picked_element = child # iterate over the children's children picked_element, finished = self.get_picked_element( event, child, picked_element, last_selected=last_selected) # if the subcall wants to finish, just break the loop if finished: break return picked_element, finished
def update_el(self, el, state): ''' el = TSCS.EL state = STATL.TELDRIVE ''' self.logger.debug('updating el=%s state=%s' % (str(el), state)) val, color = self.__get_val_state(el, state) try: Artist.remove(self.el) el_kwargs = dict(alpha=0.5, fc=color, ec=color, lw=8) self.el = mpatches.Wedge((1, 0), 0.99, 180 - val, 180, **el_kwargs) self.axes.add_patch(self.el) self.draw() except Exception as e: self.logger.error('error: updating. %s' % str(e)) pass
def __init__(self, edgecolor=None, facecolor=None, linewidth=None, antialiased=None, fill=1, **kwargs): Artist.__init__(self) if edgecolor is None: edgecolor = rc.patch.edgecolor if facecolor is None: facecolor = rc.patch.facecolor if linewidth is None: linewidth = rc.patch.linewidth if antialiased is None: antialiased = rc.patch.antialiased self.edgecolor = edgecolor self.facecolor = facecolor self.linewidth = linewidth self.antialiased = antialiased self.fill = fill
def __init__(self, color, linewidth, xbounds, ybounds, xpos='bottom', ypos='left'): """ color: str indicating color of line linewidth: width of line to draw xbounds, ybounds: tuple (min,max) of data on x and y axis, as a fraction of the axes size. xpos, ypos: tuple of str the position of the lines ('bottom' or 'top' for xpos; 'left' or 'right' for ypos) """ Artist.__init__(self) self.color = color self.linewidth = linewidth self.xbounds = xbounds self.ybounds = ybounds self.xpos = dict(bottom=0, top=1).get(xpos, 0) self.ypos = dict(left=0, right=1).get(ypos, 0)
def _update_axes_datalim(self, chart: "Chart", text_artist: Artist): """ Extends the area of the Axes in a chart so that text is shown correctly (isn't clipped). """ bbox = text_artist.get_window_extent(chart.figure.canvas.get_renderer()) ax = chart.axes bbox_data = bbox.transformed(ax.transData.inverted()) ax.update_datalim(bbox_data.corners()) ax.autoscale_view()
def poly_changed(self, poly): """ Polygon changed. Parameters ---------- poly : TYPE DESCRIPTION. Returns ------- None. """ # this method is called whenever the polygon object is called # only copy the artist props to the line (except visibility) vis = self.line.get_visible() Artist.update_from(self.line, poly) self.line.set_visible(vis) # don't use the poly visibility state
def __init__(self, Q, X, Y, U, label, **kw): Artist.__init__(self) self.Q = Q self.X = X self.Y = Y self.U = U self.coord = kw.pop('coordinates', 'axes') self.color = kw.pop('color', None) self.label = label self.labelsep = T.Value(kw.pop('labelsep', 0.1)) * Q.ax.figure.dpi self.labelpos = kw.pop('labelpos', 'N') self.labelcolor = kw.pop('labelcolor', None) self.fontproperties = kw.pop('fontproperties', dict()) self.kw = kw self.text = Text(text=label, horizontalalignment=self.halign[self.labelpos], verticalalignment=self.valign[self.labelpos], fontproperties=FontProperties(**self.fontproperties)) if self.labelcolor is not None: self.text.set_color(self.labelcolor) self._initialized = False self.zorder = Q.zorder + 0.1
def progress(i, y, ax1, ax2, n, test, fig): # if i==1: #style.use('fivethirtyeight') #fig = plt.figure() #ax1 = fig.add_subplot(1,1,1) #plt.ylabel('convergence') #plt.xlabel('iteration') # else: err_range = (np.amax(y) - np.amin(y)) / 2.0 #ax2.cla() ax1.errorbar(i, np.mean(y), yerr=err_range, fmt='o') if i != 0: #Artist.remove(ax1.texts) #fig.text.remove() #print(ax1.get_extents) [Artist.remove(txt) for txt in ax1.texts] [txt.set_visible(False) for txt in ax1.texts] #if i != 0: # textvar = ax1.texts #textvar.remove(True) #ax1.remove(textvar) #ax1.texts.set_visible(False) # [txt.set_visible(False) for txt in ax1.texts] #for txt in ax1.texts: #txt.set_visible(False) text_box = AnchoredText(np.amin(y), frameon=True, loc=1, pad=0.5) plt.setp(text_box.patch, facecolor='white', alpha=1) ax1.add_artist(text_box) #plot_text = ax1.text(3, 9, np.amin(y),bbox=dict(facecolor='white', alpha=1)) #plot_text._bbox_patch._mutation_aspect = 0.1 #plot_text.get_bbox_patch().set_boxstyle("square", pad=1) #ax2.text(n,4,np.amin(y),bbox=dict(facecolor='white', alpha=1)) ax2.plot(range(3), y, c=[0, 0, 0]) #ax2.xaxis.font(12) ax2.tick_params(labelsize='small') #fig.clf() #ax2.draw() #ax2.text() plt.pause(0.5) #time it waits for plot to update
def add_target(self, target: Artist): """ add an artist to the selection """ target = TargetWrapper(target) new_points = np.array(target.get_positions()) if len(new_points) == 0: return self.targets.append(target) x0, y0, x1, y1 = np.min(new_points[:, 0]), np.min( new_points[:, 1]), np.max(new_points[:, 0]), np.max(new_points[:, 1]) rect1 = Rectangle((x0, y0), x1 - x0, y1 - y0, picker=False, figure=self.figure, linestyle="-", edgecolor="w", facecolor="#FFFFFF00", zorder=900, label="_rect for %s" % str(target)) rect2 = Rectangle((x0, y0), x1 - x0, y1 - y0, picker=False, figure=self.figure, linestyle="--", edgecolor="k", facecolor="#FFFFFF00", zorder=900, label="_rect2 for %s" % str(target)) self.figure.patches.append(rect1) self.figure.patches.append(rect2) self.targets_rects.append(rect1) self.targets_rects.append(rect2) self.update_extent()
def __init__( self, parent, handles, labels, loc=None, numpoints=None, # the number of points in the legend line markerscale=None, # the relative size of legend markers vs. original scatterpoints=3, # TODO: may be an rcParam scatteryoffsets=None, prop=None, # properties for the legend texts # the following dimensions are in axes coords pad=None, # deprecated; use borderpad labelsep=None, # deprecated; use labelspacing handlelen=None, # deprecated; use handlelength handletextsep=None, # deprecated; use handletextpad axespad=None, # deprecated; use borderaxespad # spacing & pad defined as a fraction of the font-size borderpad=None, # the whitespace inside the legend border labelspacing=None, #the vertical space between the legend entries handlelength=None, # the length of the legend handles handletextpad=None, # the pad between the legend handle and text borderaxespad=None, # the pad between the axes and legend border columnspacing=None, # spacing between columns ncol=1, # number of columns mode=None, # mode for horizontal distribution of columns. None, "expand" fancybox=None, # True use a fancy box, false use a rounded box, none use rc shadow=None, ): """ - *parent* : the artist that contains the legend - *handles* : a list of artists (lines, patches) to add to the legend - *labels* : a list of strings to label the legend Optional keyword arguments: ================ ================================================================== Keyword Description ================ ================================================================== loc a location code or a tuple of coordinates numpoints the number of points in the legend line prop the font property markerscale the relative size of legend markers vs. original fancybox if True, draw a frame with a round fancybox. If None, use rc shadow if True, draw a shadow behind legend scatteryoffsets a list of yoffsets for scatter symbols in legend borderpad the fractional whitespace inside the legend border labelspacing the vertical space between the legend entries handlelength the length of the legend handles handletextpad the pad between the legend handle and text borderaxespad the pad between the axes and legend border columnspacing the spacing between columns ================ ================================================================== The dimensions of pad and spacing are given as a fraction of the fontsize. Values from rcParams will be used if None. """ from matplotlib.axes import Axes # local import only to avoid circularity from matplotlib.figure import Figure # local import only to avoid circularity Artist.__init__(self) if prop is None: self.prop = FontProperties(size=rcParams["legend.fontsize"]) else: self.prop = prop self.fontsize = self.prop.get_size_in_points() propnames = [ 'numpoints', 'markerscale', 'shadow', "columnspacing", "scatterpoints" ] localdict = locals() for name in propnames: if localdict[name] is None: value = rcParams["legend." + name] else: value = localdict[name] setattr(self, name, value) # Take care the deprecated keywords deprecated_kwds = { "pad": "borderpad", "labelsep": "labelspacing", "handlelen": "handlelength", "handletextsep": "handletextpad", "axespad": "borderaxespad" } # convert values of deprecated keywords (ginve in axes coords) # to new vaules in a fraction of the font size # conversion factor bbox = parent.bbox axessize_fontsize = min(bbox.width, bbox.height) / self.fontsize for k, v in deprecated_kwds.items(): # use deprecated value if not None and if their newer # counter part is None. if localdict[k] is not None and localdict[v] is None: warnings.warn("Use '%s' instead of '%s'." % (v, k), DeprecationWarning) setattr(self, v, localdict[k] * axessize_fontsize) continue # Otherwise, use new keywords if localdict[v] is None: setattr(self, v, rcParams["legend." + v]) else: setattr(self, v, localdict[v]) del localdict self._ncol = ncol if self.numpoints <= 0: raise ValueError("numpoints must be >= 0; it was %d" % numpoints) # introduce y-offset for handles of the scatter plot if scatteryoffsets is None: self._scatteryoffsets = np.array([3. / 8., 4. / 8., 2.5 / 8.]) else: self._scatteryoffsets = np.asarray(scatteryoffsets) reps = int(self.numpoints / len(self._scatteryoffsets)) + 1 self._scatteryoffsets = np.tile(self._scatteryoffsets, reps)[:self.scatterpoints] # _legend_box is an OffsetBox instance that contains all # legend items and will be initialized from _init_legend_box() # method. self._legend_box = None if isinstance(parent, Axes): self.isaxes = True self.set_figure(parent.figure) elif isinstance(parent, Figure): self.isaxes = False self.set_figure(parent) else: raise TypeError("Legend needs either Axes or Figure as parent") self.parent = parent if loc is None: loc = rcParams["legend.loc"] if not self.isaxes and loc in [0, 'best']: loc = 'upper right' if is_string_like(loc): if loc not in self.codes: if self.isaxes: warnings.warn( 'Unrecognized location "%s". Falling back on "best"; ' 'valid locations are\n\t%s\n' % (loc, '\n\t'.join(self.codes.keys()))) loc = 0 else: warnings.warn( 'Unrecognized location "%s". Falling back on "upper right"; ' 'valid locations are\n\t%s\n' % (loc, '\n\t'.join(self.codes.keys()))) loc = 1 else: loc = self.codes[loc] if not self.isaxes and loc == 0: warnings.warn( 'Automatic legend placement (loc="best") not implemented for figure legend. ' 'Falling back on "upper right".') loc = 1 self._loc = loc self._mode = mode # We use FancyBboxPatch to draw a legend frame. The location # and size of the box will be updated during the drawing time. self.legendPatch = FancyBboxPatch(xy=(0.0, 0.0), width=1., height=1., facecolor='w', edgecolor='k', mutation_scale=self.fontsize, snap=True) # The width and height of the legendPatch will be set (in the # draw()) to the length that includes the padding. Thus we set # pad=0 here. if fancybox is None: fancybox = rcParams["legend.fancybox"] if fancybox == True: self.legendPatch.set_boxstyle("round", pad=0, rounding_size=0.2) else: self.legendPatch.set_boxstyle("square", pad=0) self._set_artist_props(self.legendPatch) self._drawFrame = True # init with null renderer self._init_legend_box(handles, labels) self._last_fontsize_points = self.fontsize
def __init__(self, mappable=None, label=None, orientation=None, length_fraction=None, width_fraction=None, location=None, pad=None, border_pad=None, sep=None, frameon=None, color=None, box_color=None, box_alpha=None, font_properties=None, ticks=None, ticklabels=None, ticklocation=None): """ Creates a new color bar. :arg mappable: scalar mappable object which implements the methods: :meth:`get_cmap` and :meth:`get_array` (default: ``None``, the mappable can be specified later) :arg label: label on top of the color bar (default: ``None``, no label is shown) :arg orientation: orientation, ``vertical`` or ``horizontal`` (default: rcParams['colorbar.orientation'] or ``vertical``) :arg length_fraction: length of the color bar as a fraction of the axes's width (horizontal) or height (vertical) depending on the orientation (default: rcParams['colorbar.length_fraction'] or ``0.2``) :arg width_fraction: width of the color bar as a fraction of the axes's height (horizontal) or width (vertical) depending on the orientation (default: rcParams['colorbar.width_fraction'] or ``0.02`` :arg location: a location code (same as legend) (default: rcParams['colorbar.location'] or ``upper right``) :arg pad: fraction of the font size (default: rcParams['colorbar.pad'] or ``0.2``) :arg border_pad: fraction of the font size (default: rcParams['colorbar.border_pad'] or ``0.1``) :arg sep: separation between color bar and label in points (default: rcParams['colorbar.sep'] or ``5``) :arg frameon: if True, will draw a box around the color bar (default: rcParams['colorbar.frameon'] or ``True``) :arg color: color for the tick text and label (default: rcParams['colorbar.color'] or ``k``) :arg box_color: color of the box (if *frameon*) (default: rcParams['colorbar.box_color'] or ``w``) :arg box_alpha: transparency of box (default: rcParams['colorbar.box_alpha'] or ``1.0``) :arg font_properties: a matplotlib.font_manager.FontProperties instance, optional sets the font properties for the label text :arg ticks: ticks location (default: minimal and maximal values) :arg ticklabels: a list of tick labels (same length as ``ticks`` argument) :arg ticklocation: location of the ticks: ``left`` or ``right`` for vertical oriented colorbar, ``bottom`` or ``top for horizontal oriented colorbar, or ``auto`` for automatic adjustment (``right`` for vertical and ``bottom`` for horizontal oriented colorbar). (default: rcParams['colorbar.ticklocation'] or ``auto``) """ Artist.__init__(self) self.mappable = mappable self.label = label self.orientation = orientation self.length_fraction = length_fraction self.width_fraction = width_fraction self.location = location self.pad = pad self.border_pad = border_pad self.sep = sep self.frameon = frameon self.color = color self.box_color = box_color self.box_alpha = box_alpha self.font_properties = FontProperties(font_properties) self.ticks = ticks self.ticklabels = ticklabels self.ticklocation = ticklocation
def poly_changed(self, poly): 'this method is called whenever the polygon object is called' vis = self.line.get_visible() Artist.update_from(self.line, poly) self.line.set_visible(vis)
def __init__(self, parent, handles, labels, loc=None, numpoints=None, # the number of points in the legend line markerscale=None, # the relative size of legend markers # vs. original markerfirst=True, # controls ordering (left-to-right) of # legend marker and label scatterpoints=None, # number of scatter points scatteryoffsets=None, prop=None, # properties for the legend texts fontsize=None, # keyword to set font size directly # spacing & pad defined as a fraction of the font-size borderpad=None, # the whitespace inside the legend border labelspacing=None, # the vertical space between the legend # entries handlelength=None, # the length of the legend handles handleheight=None, # the height of the legend handles handletextpad=None, # the pad between the legend handle # and text borderaxespad=None, # the pad between the axes and legend # border columnspacing=None, # spacing between columns ncol=1, # number of columns mode=None, # mode for horizontal distribution of columns. # None, "expand" fancybox=None, # True use a fancy box, false use a rounded # box, none use rc shadow=None, title=None, # set a title for the legend title_fontsize=None, # set to ax.fontsize if None framealpha=None, # set frame alpha edgecolor=None, # frame patch edgecolor facecolor=None, # frame patch facecolor bbox_to_anchor=None, # bbox that the legend will be anchored. bbox_transform=None, # transform for the bbox frameon=None, # draw frame handler_map=None, ): """ Parameters ---------- parent : `~matplotlib.axes.Axes` or `.Figure` The artist that contains the legend. handles : sequence of `.Artist` A list of Artists (lines, patches) to be added to the legend. labels : sequence of strings A list of labels to show next to the artists. The length of handles and labels should be the same. If they are not, they are truncated to the smaller of both lengths. Other Parameters ---------------- %(_legend_kw_doc)s Notes ----- Users can specify any arbitrary location for the legend using the *bbox_to_anchor* keyword argument. bbox_to_anchor can be an instance of BboxBase(or its derivatives) or a tuple of 2 or 4 floats. See :meth:`set_bbox_to_anchor` for more detail. The legend location can be specified by setting *loc* with a tuple of 2 floats, which is interpreted as the lower-left corner of the legend in the normalized axes coordinate. """ # local import only to avoid circularity from matplotlib.axes import Axes from matplotlib.figure import Figure Artist.__init__(self) if prop is None: if fontsize is not None: self.prop = FontProperties(size=fontsize) else: self.prop = FontProperties(size=rcParams["legend.fontsize"]) elif isinstance(prop, dict): self.prop = FontProperties(**prop) if "size" not in prop: self.prop.set_size(rcParams["legend.fontsize"]) else: self.prop = prop self._fontsize = self.prop.get_size_in_points() self.texts = [] self.legendHandles = [] self._legend_title_box = None #: A dictionary with the extra handler mappings for this Legend #: instance. self._custom_handler_map = handler_map locals_view = locals() for name in ["numpoints", "markerscale", "shadow", "columnspacing", "scatterpoints", "handleheight", 'borderpad', 'labelspacing', 'handlelength', 'handletextpad', 'borderaxespad']: if locals_view[name] is None: value = rcParams["legend." + name] else: value = locals_view[name] setattr(self, name, value) del locals_view # trim handles and labels if illegal label... _lab, _hand = [], [] for label, handle in zip(labels, handles): if isinstance(label, str) and label.startswith('_'): cbook._warn_external('The handle {!r} has a label of {!r} ' 'which cannot be automatically added to' ' the legend.'.format(handle, label)) else: _lab.append(label) _hand.append(handle) labels, handles = _lab, _hand handles = list(handles) if len(handles) < 2: ncol = 1 self._ncol = ncol if self.numpoints <= 0: raise ValueError("numpoints must be > 0; it was %d" % numpoints) # introduce y-offset for handles of the scatter plot if scatteryoffsets is None: self._scatteryoffsets = np.array([3. / 8., 4. / 8., 2.5 / 8.]) else: self._scatteryoffsets = np.asarray(scatteryoffsets) reps = self.scatterpoints // len(self._scatteryoffsets) + 1 self._scatteryoffsets = np.tile(self._scatteryoffsets, reps)[:self.scatterpoints] # _legend_box is an OffsetBox instance that contains all # legend items and will be initialized from _init_legend_box() # method. self._legend_box = None if isinstance(parent, Axes): self.isaxes = True self.axes = parent self.set_figure(parent.figure) elif isinstance(parent, Figure): self.isaxes = False self.set_figure(parent) else: raise TypeError("Legend needs either Axes or Figure as parent") self.parent = parent self._loc_used_default = loc is None if loc is None: loc = rcParams["legend.loc"] if not self.isaxes and loc in [0, 'best']: loc = 'upper right' if isinstance(loc, str): if loc not in self.codes: if self.isaxes: cbook.warn_deprecated( "3.1", message="Unrecognized location {!r}. Falling " "back on 'best'; valid locations are\n\t{}\n" "This will raise an exception %(removal)s." .format(loc, '\n\t'.join(self.codes))) loc = 0 else: cbook.warn_deprecated( "3.1", message="Unrecognized location {!r}. Falling " "back on 'upper right'; valid locations are\n\t{}\n'" "This will raise an exception %(removal)s." .format(loc, '\n\t'.join(self.codes))) loc = 1 else: loc = self.codes[loc] if not self.isaxes and loc == 0: cbook.warn_deprecated( "3.1", message="Automatic legend placement (loc='best') not " "implemented for figure legend. Falling back on 'upper " "right'. This will raise an exception %(removal)s.") loc = 1 self._mode = mode self.set_bbox_to_anchor(bbox_to_anchor, bbox_transform) # We use FancyBboxPatch to draw a legend frame. The location # and size of the box will be updated during the drawing time. if facecolor is None: facecolor = rcParams["legend.facecolor"] if facecolor == 'inherit': facecolor = rcParams["axes.facecolor"] if edgecolor is None: edgecolor = rcParams["legend.edgecolor"] if edgecolor == 'inherit': edgecolor = rcParams["axes.edgecolor"] self.legendPatch = FancyBboxPatch( xy=(0.0, 0.0), width=1., height=1., facecolor=facecolor, edgecolor=edgecolor, mutation_scale=self._fontsize, snap=True ) # The width and height of the legendPatch will be set (in the # draw()) to the length that includes the padding. Thus we set # pad=0 here. if fancybox is None: fancybox = rcParams["legend.fancybox"] if fancybox: self.legendPatch.set_boxstyle("round", pad=0, rounding_size=0.2) else: self.legendPatch.set_boxstyle("square", pad=0) self._set_artist_props(self.legendPatch) self._drawFrame = frameon if frameon is None: self._drawFrame = rcParams["legend.frameon"] # init with null renderer self._init_legend_box(handles, labels, markerfirst) # If shadow is activated use framealpha if not # explicitly passed. See Issue 8943 if framealpha is None: if shadow: self.get_frame().set_alpha(1) else: self.get_frame().set_alpha(rcParams["legend.framealpha"]) else: self.get_frame().set_alpha(framealpha) tmp = self._loc_used_default self._set_loc(loc) self._loc_used_default = tmp # ignore changes done by _set_loc # figure out title fontsize: if title_fontsize is None: title_fontsize = rcParams['legend.title_fontsize'] tprop = FontProperties(size=title_fontsize) self.set_title(title, prop=tprop) self._last_fontsize_points = self._fontsize self._draggable = None
def set_visible(self, b): self.toggle(all=b) self.line.set_visible(b) self._axis.set_visible(True) Artist.set_visible(self, b)
def __init__(self, artist_list, filter): self._artist_list = artist_list self._filter = filter Artist.__init__(self)
def __init__( self, parent, handles, labels, loc=None, numpoints=None, # the number of points in the legend line markerscale=None, # the relative size of legend markers # vs. original markerfirst=True, # controls ordering (left-to-right) of # legend marker and label scatterpoints=None, # number of scatter points scatteryoffsets=None, prop=None, # properties for the legend texts fontsize=None, # keyword to set font size directly # spacing & pad defined as a fraction of the font-size borderpad=None, # the whitespace inside the legend border labelspacing=None, # the vertical space between the legend # entries handlelength=None, # the length of the legend handles handleheight=None, # the height of the legend handles handletextpad=None, # the pad between the legend handle # and text borderaxespad=None, # the pad between the axes and legend # border columnspacing=None, # spacing between columns ncol=1, # number of columns mode=None, # mode for horizontal distribution of columns. # None, "expand" fancybox=None, # True use a fancy box, false use a rounded # box, none use rc shadow=None, title=None, # set a title for the legend title_fontsize=None, # set to ax.fontsize if None framealpha=None, # set frame alpha edgecolor=None, # frame patch edgecolor facecolor=None, # frame patch facecolor bbox_to_anchor=None, # bbox that the legend will be anchored. bbox_transform=None, # transform for the bbox frameon=None, # draw frame handler_map=None, ): """ Parameters ---------- parent : `~matplotlib.axes.Axes` or `.Figure` The artist that contains the legend. handles : sequence of `.Artist` A list of Artists (lines, patches) to be added to the legend. labels : sequence of strings A list of labels to show next to the artists. The length of handles and labels should be the same. If they are not, they are truncated to the smaller of both lengths. Other Parameters ---------------- %(_legend_kw_doc)s Notes ----- Users can specify any arbitrary location for the legend using the *bbox_to_anchor* keyword argument. bbox_to_anchor can be an instance of BboxBase(or its derivatives) or a tuple of 2 or 4 floats. See :meth:`set_bbox_to_anchor` for more detail. The legend location can be specified by setting *loc* with a tuple of 2 floats, which is interpreted as the lower-left corner of the legend in the normalized axes coordinate. """ # local import only to avoid circularity from matplotlib.axes import Axes from matplotlib.figure import Figure Artist.__init__(self) if prop is None: if fontsize is not None: self.prop = FontProperties(size=fontsize) else: self.prop = FontProperties(size=rcParams["legend.fontsize"]) elif isinstance(prop, dict): self.prop = FontProperties(**prop) if "size" not in prop: self.prop.set_size(rcParams["legend.fontsize"]) else: self.prop = prop self._fontsize = self.prop.get_size_in_points() self.texts = [] self.legendHandles = [] self._legend_title_box = None #: A dictionary with the extra handler mappings for this Legend #: instance. self._custom_handler_map = handler_map locals_view = locals() for name in [ "numpoints", "markerscale", "shadow", "columnspacing", "scatterpoints", "handleheight", 'borderpad', 'labelspacing', 'handlelength', 'handletextpad', 'borderaxespad' ]: if locals_view[name] is None: value = rcParams["legend." + name] else: value = locals_view[name] setattr(self, name, value) del locals_view # trim handles and labels if illegal label... _lab, _hand = [], [] for label, handle in zip(labels, handles): if isinstance(label, str) and label.startswith('_'): warnings.warn('The handle {!r} has a label of {!r} which ' 'cannot be automatically added to the ' 'legend.'.format(handle, label)) else: _lab.append(label) _hand.append(handle) labels, handles = _lab, _hand handles = list(handles) if len(handles) < 2: ncol = 1 self._ncol = ncol if self.numpoints <= 0: raise ValueError("numpoints must be > 0; it was %d" % numpoints) # introduce y-offset for handles of the scatter plot if scatteryoffsets is None: self._scatteryoffsets = np.array([3. / 8., 4. / 8., 2.5 / 8.]) else: self._scatteryoffsets = np.asarray(scatteryoffsets) reps = self.scatterpoints // len(self._scatteryoffsets) + 1 self._scatteryoffsets = np.tile(self._scatteryoffsets, reps)[:self.scatterpoints] # _legend_box is an OffsetBox instance that contains all # legend items and will be initialized from _init_legend_box() # method. self._legend_box = None if isinstance(parent, Axes): self.isaxes = True self.axes = parent self.set_figure(parent.figure) elif isinstance(parent, Figure): self.isaxes = False self.set_figure(parent) else: raise TypeError("Legend needs either Axes or Figure as parent") self.parent = parent if loc is None: loc = rcParams["legend.loc"] if not self.isaxes and loc in [0, 'best']: loc = 'upper right' if isinstance(loc, str): if loc not in self.codes: if self.isaxes: warnings.warn('Unrecognized location "%s". Falling back ' 'on "best"; valid locations are\n\t%s\n' % (loc, '\n\t'.join(self.codes))) loc = 0 else: warnings.warn('Unrecognized location "%s". Falling back ' 'on "upper right"; ' 'valid locations are\n\t%s\n' % (loc, '\n\t'.join(self.codes))) loc = 1 else: loc = self.codes[loc] if not self.isaxes and loc == 0: warnings.warn('Automatic legend placement (loc="best") not ' 'implemented for figure legend. ' 'Falling back on "upper right".') loc = 1 self._mode = mode self.set_bbox_to_anchor(bbox_to_anchor, bbox_transform) # We use FancyBboxPatch to draw a legend frame. The location # and size of the box will be updated during the drawing time. if facecolor is None: facecolor = rcParams["legend.facecolor"] if facecolor == 'inherit': facecolor = rcParams["axes.facecolor"] if edgecolor is None: edgecolor = rcParams["legend.edgecolor"] if edgecolor == 'inherit': edgecolor = rcParams["axes.edgecolor"] self.legendPatch = FancyBboxPatch(xy=(0.0, 0.0), width=1., height=1., facecolor=facecolor, edgecolor=edgecolor, mutation_scale=self._fontsize, snap=True) # The width and height of the legendPatch will be set (in the # draw()) to the length that includes the padding. Thus we set # pad=0 here. if fancybox is None: fancybox = rcParams["legend.fancybox"] if fancybox: self.legendPatch.set_boxstyle("round", pad=0, rounding_size=0.2) else: self.legendPatch.set_boxstyle("square", pad=0) self._set_artist_props(self.legendPatch) self._drawFrame = frameon if frameon is None: self._drawFrame = rcParams["legend.frameon"] # init with null renderer self._init_legend_box(handles, labels, markerfirst) # If shadow is activated use framealpha if not # explicitly passed. See Issue 8943 if framealpha is None: if shadow: self.get_frame().set_alpha(1) else: self.get_frame().set_alpha(rcParams["legend.framealpha"]) else: self.get_frame().set_alpha(framealpha) self._loc = loc # figure out title fontsize: if title_fontsize is None: title_fontsize = rcParams['legend.title_fontsize'] tprop = FontProperties(size=title_fontsize) self.set_title(title, prop=tprop) self._last_fontsize_points = self._fontsize self._draggable = None
def __init__( self, parent, handles, labels, loc=None, numpoints=None, # the number of points in the legend line markerscale=None, # the relative size of legend markers vs. original scatterpoints=3, # TODO: may be an rcParam scatteryoffsets=None, prop=None, # properties for the legend texts pad=None, # deprecated; use borderpad labelsep=None, # deprecated; use labelspacing handlelen=None, # deprecated; use handlelength handletextsep=None, # deprecated; use handletextpad axespad=None, # deprecated; use borderaxespad borderpad=None, # the whitespace inside the legend border labelspacing=None, # the vertical space between the legend entries handlelength=None, # the length of the legend handles handletextpad=None, # the pad between the legend handle and text borderaxespad=None, # the pad between the axes and legend border columnspacing=None, # spacing between columns ncol=1, # number of columns mode=None, # mode for horizontal distribution of columns. None, "expand" fancybox=None, # True use a fancy box, false use a rounded box, none use rc shadow=None, title=None, # set a title for the legend bbox_to_anchor=None, # bbox that the legend will be anchored. bbox_transform=None, # transform for the bbox ): """ - *parent* : the artist that contains the legend - *handles* : a list of artists (lines, patches) to add to the legend - *labels* : a list of strings to label the legend Optional keyword arguments: ================ ================================================================== Keyword Description ================ ================================================================== loc a location code prop the font property markerscale the relative size of legend markers vs. original numpoints the number of points in the legend for line scatterpoints the number of points in the legend for scatter plot scatteryoffsets a list of yoffsets for scatter symbols in legend fancybox if True, draw a frame with a round fancybox. If None, use rc shadow if True, draw a shadow behind legend ncol number of columns borderpad the fractional whitespace inside the legend border labelspacing the vertical space between the legend entries handlelength the length of the legend handles handletextpad the pad between the legend handle and text borderaxespad the pad between the axes and legend border columnspacing the spacing between columns title the legend title bbox_to_anchor the bbox that the legend will be anchored. bbox_transform the transform for the bbox. transAxes if None. ================ ================================================================== The dimensions of pad and spacing are given as a fraction of the _fontsize. Values from rcParams will be used if None. Users can specify any arbitrary location for the legend using the *bbox_to_anchor* keyword argument. bbox_to_anchor can be an instance of BboxBase(or its derivatives) or a tuple of 2 or 4 floats. See :meth:`set_bbox_to_anchor` for more detail. The legend location can be specified by setting *loc* with a tuple of 2 floats, which is interpreted as the lower-left corner of the legend in the normalized axes coordinate. """ from matplotlib.axes import Axes # local import only to avoid circularity from matplotlib.figure import Figure # local import only to avoid circularity Artist.__init__(self) if prop is None: self.prop = FontProperties(size=rcParams["legend.fontsize"]) elif isinstance(prop, dict): self.prop = FontProperties(**prop) if "size" not in prop: self.prop.set_size(rcParams["legend.fontsize"]) else: self.prop = prop self._fontsize = self.prop.get_size_in_points() propnames = ["numpoints", "markerscale", "shadow", "columnspacing", "scatterpoints"] self.texts = [] self.legendHandles = [] self._legend_title_box = None localdict = locals() for name in propnames: if localdict[name] is None: value = rcParams["legend." + name] else: value = localdict[name] setattr(self, name, value) deprecated_kwds = { "pad": "borderpad", "labelsep": "labelspacing", "handlelen": "handlelength", "handletextsep": "handletextpad", "axespad": "borderaxespad", } bbox = parent.bbox axessize_fontsize = min(bbox.width, bbox.height) / self._fontsize for k, v in deprecated_kwds.items(): if localdict[k] is not None and localdict[v] is None: warnings.warn("Use '%s' instead of '%s'." % (v, k), DeprecationWarning) setattr(self, v, localdict[k] * axessize_fontsize) continue if localdict[v] is None: setattr(self, v, rcParams["legend." + v]) else: setattr(self, v, localdict[v]) del localdict handles = list(handles) if len(handles) < 2: ncol = 1 self._ncol = ncol if self.numpoints <= 0: raise ValueError("numpoints must be >= 0; it was %d" % numpoints) if scatteryoffsets is None: self._scatteryoffsets = np.array([3.0 / 8.0, 4.0 / 8.0, 2.5 / 8.0]) else: self._scatteryoffsets = np.asarray(scatteryoffsets) reps = int(self.numpoints / len(self._scatteryoffsets)) + 1 self._scatteryoffsets = np.tile(self._scatteryoffsets, reps)[: self.scatterpoints] self._legend_box = None if isinstance(parent, Axes): self.isaxes = True self.set_axes(parent) self.set_figure(parent.figure) elif isinstance(parent, Figure): self.isaxes = False self.set_figure(parent) else: raise TypeError("Legend needs either Axes or Figure as parent") self.parent = parent if loc is None: loc = rcParams["legend.loc"] if not self.isaxes and loc in [0, "best"]: loc = "upper right" if is_string_like(loc): if loc not in self.codes: if self.isaxes: warnings.warn( 'Unrecognized location "%s". Falling back on "best"; ' "valid locations are\n\t%s\n" % (loc, "\n\t".join(self.codes.keys())) ) loc = 0 else: warnings.warn( 'Unrecognized location "%s". Falling back on "upper right"; ' "valid locations are\n\t%s\n" % (loc, "\n\t".join(self.codes.keys())) ) loc = 1 else: loc = self.codes[loc] if not self.isaxes and loc == 0: warnings.warn( 'Automatic legend placement (loc="best") not implemented for figure legend. ' 'Falling back on "upper right".' ) loc = 1 self._loc = loc self._mode = mode self.set_bbox_to_anchor(bbox_to_anchor, bbox_transform) self.legendPatch = FancyBboxPatch( xy=(0.0, 0.0), width=1.0, height=1.0, facecolor="w", edgecolor="k", mutation_scale=self._fontsize, snap=True ) if fancybox is None: fancybox = rcParams["legend.fancybox"] if fancybox == True: self.legendPatch.set_boxstyle("round", pad=0, rounding_size=0.2) else: self.legendPatch.set_boxstyle("square", pad=0) self._set_artist_props(self.legendPatch) self._drawFrame = True self._init_legend_box(handles, labels) self.set_title(title) self._last_fontsize_points = self._fontsize
def poly_changed(self, poly): 'this method is called whenever the polygon object is called' vis = self.line.get_visible() Artist.update_from(self.line, poly) self.line.set_visible(vis) # don't use the poly visibility state
def __init__(self, figsize = None, # defaults to rc figure.figsize dpi = None, # defaults to rc figure.dpi facecolor = None, # defaults to rc figure.facecolor edgecolor = None, # defaults to rc figure.edgecolor linewidth = 0.0, # the default linewidth of the frame frameon = True, # whether or not to draw the figure frame subplotpars = None, # default to rc tight_layout = None, # default to rc figure.autolayout ): """ *figsize* w,h tuple in inches *dpi* Dots per inch *facecolor* The figure patch facecolor; defaults to rc ``figure.facecolor`` *edgecolor* The figure patch edge color; defaults to rc ``figure.edgecolor`` *linewidth* The figure patch edge linewidth; the default linewidth of the frame *frameon* If *False*, suppress drawing the figure frame *subplotpars* A :class:`SubplotParams` instance, defaults to rc *tight_layout* If *False* use *subplotpars*; if *True* adjust subplot parameters using :meth:`tight_layout`. Defaults to rc ``figure.autolayout``. """ Artist.__init__(self) self.callbacks = cbook.CallbackRegistry() if figsize is None : figsize = rcParams['figure.figsize'] if dpi is None : dpi = rcParams['figure.dpi'] if facecolor is None: facecolor = rcParams['figure.facecolor'] if edgecolor is None: edgecolor = rcParams['figure.edgecolor'] self.dpi_scale_trans = Affine2D() self.dpi = dpi self.bbox_inches = Bbox.from_bounds(0, 0, *figsize) self.bbox = TransformedBbox(self.bbox_inches, self.dpi_scale_trans) self.frameon = frameon self.transFigure = BboxTransformTo(self.bbox) # the figurePatch name is deprecated self.patch = self.figurePatch = Rectangle( xy=(0,0), width=1, height=1, facecolor=facecolor, edgecolor=edgecolor, linewidth=linewidth, ) self._set_artist_props(self.patch) self.patch.set_aa(False) self._hold = rcParams['axes.hold'] self.canvas = None if subplotpars is None: subplotpars = SubplotParams() self.subplotpars = subplotpars self.set_tight_layout(tight_layout) self._axstack = AxesStack() # track all figure axes and current axes self.clf() self._cachedRenderer = None
def line_changed(self, line): vis = self.line.get_visible() Artist.update_from(self.line, line) self.line.set_visible(vis)
def __init__(self, dx, units='m', dimension=SI_LENGTH, label=None, length_fraction=None, height_fraction=None, location=None, pad=None, border_pad=None, sep=None, frameon=None, color=None, box_color=None, box_alpha=None, scale_loc=None, label_loc=None, font_properties=None): """ Creates a new scale bar. :arg dx: size of one pixel in *units* Set ``dx`` to 1.0 if the axes image has already been calibrated by setting its ``extent``. :type dx: :class:`float` :arg units: units of *dx* (default: ``m``) :type units: :class:`str` :arg dimension: dimension of *dx* and *units*. It can either be equal * ``:const:`SI_LENGTH```: scale bar showing km, m, cm, etc. * ``:const:`IMPERIAL_LENGTH```: scale bar showing in, ft, yd, mi, etc. * ``:const:`SI_LENGTH_RECIPROCAL```: scale bar showing 1/m, 1/cm, etc. * a :class:`matplotlib_scalebar.dimension._Dimension` object :type dimension: :class:`str` or :class:`matplotlib_scalebar.dimension._Dimension` :arg label: optional label associated with the scale bar (default: ``None``, no label is shown) :type label: :class:`str` :arg length_fraction: length of the scale bar as a fraction of the axes's width (default: rcParams['scalebar.lenght_fraction'] or ``0.2``) :type length_fraction: :class:`float` :arg height_fraction: height of the scale bar as a fraction of the axes's height (default: rcParams['scalebar.height_fraction'] or ``0.01``) :type length_fraction: :class:`float` :arg location: a location code (same as legend) (default: rcParams['scalebar.location'] or ``upper right``) :type location: :class:`str` :arg pad: fraction of the font size (default: rcParams['scalebar.pad'] or ``0.2``) :type pad: :class:`float` :arg border_pad : fraction of the font size (default: rcParams['scalebar.border_pad'] or ``0.1``) :type border_pad: :class:`float` :arg sep : separation between scale bar and label in points (default: rcParams['scalebar.sep'] or ``5``) :type sep: :class:`float` :arg frameon : if True, will draw a box around the scale bar and label (default: rcParams['scalebar.frameon'] or ``True``) :type frameon: :class:`bool` :arg color : color for the scale bar and label (default: rcParams['scalebar.color'] or ``k``) :type color: :class:`str` :arg box_color: color of the box (if *frameon*) (default: rcParams['scalebar.box_color'] or ``w``) :type box_color: :class:`str` :arg box_alpha: transparency of box (default: rcParams['scalebar.box_alpha'] or ``1.0``) :type box_alpha: :class:`float` :arg scale_loc : either ``bottom``, ``top``, ``left``, ``right`` (default: rcParams['scalebar.scale_loc'] or ``bottom``) :type scale_loc: :class:`str` :arg label_loc: either ``bottom``, ``top``, ``left``, ``right`` (default: rcParams['scalebar.label_loc'] or ``top``) :type label_loc: :class:`str` :arg font_properties: font properties of the label text, specified either as dict or `fontconfig <http://www.fontconfig.org/>`_ pattern (XML). :type font_properties: :class:`matplotlib.font_manager.FontProperties`, :class:`str` or :class:`dict` """ Artist.__init__(self) self.dx = dx self.dimension = dimension # Should be initialize before units self.units = units self.label = label self.length_fraction = length_fraction self.height_fraction = height_fraction self.location = location self.pad = pad self.border_pad = border_pad self.sep = sep self.frameon = frameon self.color = color self.box_color = box_color self.box_alpha = box_alpha self.scale_loc = scale_loc self.label_loc = label_loc if font_properties is None: font_properties = FontProperties() elif isinstance(font_properties, dict): font_properties = FontProperties(**font_properties) elif isinstance(font_properties,six.string_types): font_properties = FontProperties(font_properties) else: raise TypeError("Unsupported type for `font_properties`. Pass " "either a dict or a font config pattern as string.") self.font_properties = font_properties
def __init__(self, parent, handles, labels, loc=None, numpoints=None, # the number of points in the legend line markerscale=None, # the relative size of legend markers # vs. original markerfirst=True, # controls ordering (left-to-right) of # legend marker and label scatterpoints=None, # number of scatter points scatteryoffsets=None, prop=None, # properties for the legend texts fontsize=None, # keyword to set font size directly # spacing & pad defined as a fraction of the font-size borderpad=None, # the whitespace inside the legend border labelspacing=None, # the vertical space between the legend # entries handlelength=None, # the length of the legend handles handleheight=None, # the height of the legend handles handletextpad=None, # the pad between the legend handle # and text borderaxespad=None, # the pad between the axes and legend # border columnspacing=None, # spacing between columns ncol=1, # number of columns mode=None, # mode for horizontal distribution of columns. # None, "expand" fancybox=None, # True use a fancy box, false use a rounded # box, none use rc shadow=None, title=None, # set a title for the legend framealpha=None, # set frame alpha bbox_to_anchor=None, # bbox that the legend will be anchored. bbox_transform=None, # transform for the bbox frameon=None, # draw frame handler_map=None, displace=None, ): """ - *parent*: the artist that contains the legend - *handles*: a list of artists (lines, patches) to be added to the legend - *labels*: a list of strings to label the legend Optional keyword arguments: ================ ==================================================== Keyword Description ================ ==================================================== loc a location code prop the font property fontsize the font size (used only if prop is not specified) markerscale the relative size of legend markers vs. original markerfirst If true, place legend marker to left of label If false, place legend marker to right of label numpoints the number of points in the legend for line scatterpoints the number of points in the legend for scatter plot scatteryoffsets a list of yoffsets for scatter symbols in legend frameon if True, draw a frame around the legend. If None, use rc fancybox if True, draw a frame with a round fancybox. If None, use rc shadow if True, draw a shadow behind legend framealpha If not None, alpha channel for the frame. ncol number of columns borderpad the fractional whitespace inside the legend border labelspacing the vertical space between the legend entries handlelength the length of the legend handles handleheight the height of the legend handles handletextpad the pad between the legend handle and text borderaxespad the pad between the axes and legend border columnspacing the spacing between columns title the legend title bbox_to_anchor the bbox that the legend will be anchored. bbox_transform the transform for the bbox. transAxes if None. displace the legend posistion will be anchored ================ ==================================================== The pad and spacing parameters are measured in font-size units. e.g., a fontsize of 10 points and a handlelength=5 implies a handlelength of 50 points. Values from rcParams will be used if None. Users can specify any arbitrary location for the legend using the *bbox_to_anchor* keyword argument. bbox_to_anchor can be an instance of BboxBase(or its derivatives) or a tuple of 2 or 4 floats. See :meth:`set_bbox_to_anchor` for more detail. The legend location can be specified by setting *loc* with a tuple of 2 floats, which is interpreted as the lower-left corner of the legend in the normalized axes coordinate. """ # local import only to avoid circularity from matplotlib.axes import Axes from matplotlib.figure import Figure Artist.__init__(self) if prop is None: if fontsize is not None: self.prop = FontProperties(size=fontsize) else: self.prop = FontProperties(size=rcParams["legend.fontsize"]) elif isinstance(prop, dict): self.prop = FontProperties(**prop) if "size" not in prop: self.prop.set_size(rcParams["legend.fontsize"]) else: self.prop = prop self._fontsize = self.prop.get_size_in_points() self.texts = [] self.legendHandles = [] self._legend_title_box = None #: A dictionary with the extra handler mappings for this Legend #: instance. self._custom_handler_map = handler_map locals_view = locals() for name in ["numpoints", "markerscale", "shadow", "columnspacing", "scatterpoints", "handleheight", 'borderpad', 'labelspacing', 'handlelength', 'handletextpad', 'borderaxespad']: if locals_view[name] is None: value = rcParams["legend." + name] else: value = locals_view[name] setattr(self, name, value) del locals_view handles = list(handles) if len(handles) < 2: ncol = 1 self._ncol = ncol if self.numpoints <= 0: raise ValueError("numpoints must be > 0; it was %d" % numpoints) # introduce y-offset for handles of the scatter plot if scatteryoffsets is None: self._scatteryoffsets = np.array([3. / 8., 4. / 8., 2.5 / 8.]) else: self._scatteryoffsets = np.asarray(scatteryoffsets) reps = int(self.scatterpoints / len(self._scatteryoffsets)) + 1 self._scatteryoffsets = np.tile(self._scatteryoffsets, reps)[:self.scatterpoints] # _legend_box is an OffsetBox instance that contains all # legend items and will be initialized from _init_legend_box() # method. self._legend_box = None if isinstance(parent, Axes): self.isaxes = True self.axes = parent self.set_figure(parent.figure) elif isinstance(parent, Figure): self.isaxes = False self.set_figure(parent) else: raise TypeError("Legend needs either Axes or Figure as parent") self.parent = parent if loc is None: loc = rcParams["legend.loc"] if not self.isaxes and loc in [0, 'best']: loc = 'upper right' if is_string_like(loc): if loc not in self.codes: if self.isaxes: warnings.warn('Unrecognized location "%s". Falling back ' 'on "best"; valid locations are\n\t%s\n' % (loc, '\n\t'.join( six.iterkeys(self.codes)))) loc = 0 else: warnings.warn('Unrecognized location "%s". Falling back ' 'on "upper right"; ' 'valid locations are\n\t%s\n' % (loc, '\n\t'.join( six.iterkeys(self.codes)))) loc = 1 else: loc = self.codes[loc] if not self.isaxes and loc == 0: warnings.warn('Automatic legend placement (loc="best") not ' 'implemented for figure legend. ' 'Falling back on "upper right".') loc = 1 self._mode = mode self.set_bbox_to_anchor(bbox_to_anchor, bbox_transform) # We use FancyBboxPatch to draw a legend frame. The location # and size of the box will be updated during the drawing time. if rcParams["legend.facecolor"] == 'inherit': facecolor = rcParams["axes.facecolor"] else: facecolor = rcParams["legend.facecolor"] if rcParams["legend.edgecolor"] == 'inherit': edgecolor = rcParams["axes.edgecolor"] else: edgecolor = rcParams["legend.edgecolor"] self.legendPatch = FancyBboxPatch( xy=(0.0, 0.0), width=1., height=1., facecolor=facecolor, edgecolor=edgecolor, mutation_scale=self._fontsize, snap=True ) # The width and height of the legendPatch will be set (in the # draw()) to the length that includes the padding. Thus we set # pad=0 here. if fancybox is None: fancybox = rcParams["legend.fancybox"] if fancybox: self.legendPatch.set_boxstyle("round", pad=0, rounding_size=0.2) else: self.legendPatch.set_boxstyle("square", pad=0) self._set_artist_props(self.legendPatch) self._drawFrame = frameon if frameon is None: self._drawFrame = rcParams["legend.frameon"] # init with null renderer self._init_legend_box(handles, labels, markerfirst) if framealpha is None: self.get_frame().set_alpha(rcParams["legend.framealpha"]) else: self.get_frame().set_alpha(framealpha) self._loc = loc self.set_title(title) self._last_fontsize_points = self._fontsize self._draggable = None if displace is not None: self.set_displace(displace)
def __init__ ( self, x, y, trim=False ): Artist.__init__(self) self.x = x self.y = y self.trim = trim
def __init__(self, mappable=None, label=None, orientation=None, length_fraction=None, width_fraction=None, location=None, pad=None, border_pad=None, sep=None, frameon=None, color=None, box_color=None, box_alpha=None, font_properties=None, ticks=None, ticklabels=None, ticklocation=None): """ Creates a new color bar. :arg mappable: scalar mappable object which implements the methods: :meth:`get_cmap` and :meth:`get_array` (default: ``None``, the mappable can be specified later) :arg label: label on top of the color bar (default: ``None``, no label is shown) :arg orientation: orientation, ``vertical`` or ``horizontal`` (default: rcParams['colorbar.orientation'] or ``vertical``) :arg length_fraction: length of the color bar as a fraction of the axes's width (horizontal) or height (vertical) depending on the orientation (default: rcParams['colorbar.length_fraction'] or ``0.2``) :arg width_fraction: width of the color bar as a fraction of the axes's height (horizontal) or width (vertical) depending on the orientation (default: rcParams['colorbar.width_fraction'] or ``0.02`` :arg location: a location code (same as legend) (default: rcParams['colorbar.location'] or ``upper right``) :arg pad: fraction of the font size (default: rcParams['colorbar.pad'] or ``0.2``) :arg border_pad: fraction of the font size (default: rcParams['colorbar.border_pad'] or ``0.1``) :arg sep: separation between color bar and label in points (default: rcParams['colorbar.sep'] or ``5``) :arg frameon: if True, will draw a box around the color bar (default: rcParams['colorbar.frameon'] or ``True``) :arg color: color for the tick text and label (default: rcParams['colorbar.color'] or ``k``) :arg box_color: color of the box (if *frameon*) (default: rcParams['colorbar.box_color'] or ``w``) :arg box_alpha: transparency of box (default: rcParams['colorbar.box_alpha'] or ``1.0``) :arg font_properties: font properties of the label text, specified either as dict or `fontconfig <http://www.fontconfig.org/>`_ pattern (XML). :type font_properties: :class:`matplotlib.font_manager.FontProperties`, :class:`str` or :class:`dict` :arg ticks: ticks location (default: minimal and maximal values) :arg ticklabels: a list of tick labels (same length as ``ticks`` argument) :arg ticklocation: location of the ticks: ``left`` or ``right`` for vertical oriented colorbar, ``bottom`` or ``top for horizontal oriented colorbar, or ``auto`` for automatic adjustment (``right`` for vertical and ``bottom`` for horizontal oriented colorbar). (default: rcParams['colorbar.ticklocation'] or ``auto``) """ Artist.__init__(self) self.mappable = mappable self.label = label self.orientation = orientation self.length_fraction = length_fraction self.width_fraction = width_fraction self.location = location self.pad = pad self.border_pad = border_pad self.sep = sep self.frameon = frameon self.color = color self.box_color = box_color self.box_alpha = box_alpha if font_properties is None: font_properties = FontProperties() elif isinstance(font_properties, dict): font_properties = FontProperties(**font_properties) elif isinstance(font_properties, six.string_types): font_properties = FontProperties(font_properties) else: raise TypeError( "Unsupported type for `font_properties`. Pass " "either a dict or a font config pattern as string.") self.font_properties = font_properties self.ticks = ticks self.ticklabels = ticklabels self.ticklocation = ticklocation
def __init__(self, parent, handles, labels, loc = None, numpoints = None, # the number of points in the legend line markerscale = None, # the relative size of legend markers vs. original scatterpoints = 3, # TODO: may be an rcParam scatteryoffsets=None, prop = None, # properties for the legend texts # the following dimensions are in axes coords pad = None, # deprecated; use borderpad labelsep = None, # deprecated; use labelspacing handlelen = None, # deprecated; use handlelength handletextsep = None, # deprecated; use handletextpad axespad = None, # deprecated; use borderaxespad # spacing & pad defined as a fraction of the font-size borderpad = None, # the whitespace inside the legend border labelspacing=None, #the vertical space between the legend entries handlelength=None, # the length of the legend handles handleheight=None, # the height of the legend handles handletextpad=None, # the pad between the legend handle and text borderaxespad=None, # the pad between the axes and legend border columnspacing=None, # spacing between columns ncol=1, # number of columns mode=None, # mode for horizontal distribution of columns. None, "expand" fancybox=None, # True use a fancy box, false use a rounded box, none use rc shadow = None, title = None, # set a title for the legend bbox_to_anchor = None, # bbox that the legend will be anchored. bbox_transform = None, # transform for the bbox frameon = None, # draw frame handler_map = None, ): """ - *parent* : the artist that contains the legend - *handles* : a list of artists (lines, patches) to be added to the legend - *labels* : a list of strings to label the legend Optional keyword arguments: ================ ================================================================== Keyword Description ================ ================================================================== loc a location code prop the font property markerscale the relative size of legend markers vs. original numpoints the number of points in the legend for line scatterpoints the number of points in the legend for scatter plot scatteryoffsets a list of yoffsets for scatter symbols in legend frameon if True, draw a frame around the legend. If None, use rc fancybox if True, draw a frame with a round fancybox. If None, use rc shadow if True, draw a shadow behind legend ncol number of columns borderpad the fractional whitespace inside the legend border labelspacing the vertical space between the legend entries handlelength the length of the legend handles handleheight the length of the legend handles handletextpad the pad between the legend handle and text borderaxespad the pad between the axes and legend border columnspacing the spacing between columns title the legend title bbox_to_anchor the bbox that the legend will be anchored. bbox_transform the transform for the bbox. transAxes if None. ================ ================================================================== The pad and spacing parameters are measured in font-size units. E.g., a fontsize of 10 points and a handlelength=5 implies a handlelength of 50 points. Values from rcParams will be used if None. Users can specify any arbitrary location for the legend using the *bbox_to_anchor* keyword argument. bbox_to_anchor can be an instance of BboxBase(or its derivatives) or a tuple of 2 or 4 floats. See :meth:`set_bbox_to_anchor` for more detail. The legend location can be specified by setting *loc* with a tuple of 2 floats, which is interpreted as the lower-left corner of the legend in the normalized axes coordinate. """ from matplotlib.axes import Axes # local import only to avoid circularity from matplotlib.figure import Figure # local import only to avoid circularity Artist.__init__(self) if prop is None: self.prop=FontProperties(size=rcParams["legend.fontsize"]) elif isinstance(prop, dict): self.prop=FontProperties(**prop) if "size" not in prop: self.prop.set_size(rcParams["legend.fontsize"]) else: self.prop=prop self._fontsize = self.prop.get_size_in_points() propnames=['numpoints', 'markerscale', 'shadow', "columnspacing", "scatterpoints", "handleheight"] self.texts = [] self.legendHandles = [] self._legend_title_box = None self._handler_map = handler_map localdict = locals() for name in propnames: if localdict[name] is None: value = rcParams["legend."+name] else: value = localdict[name] setattr(self, name, value) # Take care the deprecated keywords deprecated_kwds = {"pad":"borderpad", "labelsep":"labelspacing", "handlelen":"handlelength", "handletextsep":"handletextpad", "axespad":"borderaxespad"} # convert values of deprecated keywords (ginve in axes coords) # to new vaules in a fraction of the font size # conversion factor bbox = parent.bbox axessize_fontsize = min(bbox.width, bbox.height)/self._fontsize for k, v in deprecated_kwds.iteritems(): # use deprecated value if not None and if their newer # counter part is None. if localdict[k] is not None and localdict[v] is None: warnings.warn("Use '%s' instead of '%s'." % (v, k), DeprecationWarning) setattr(self, v, localdict[k]*axessize_fontsize) continue # Otherwise, use new keywords if localdict[v] is None: setattr(self, v, rcParams["legend."+v]) else: setattr(self, v, localdict[v]) del localdict handles = list(handles) if len(handles)<2: ncol = 1 self._ncol = ncol if self.numpoints <= 0: raise ValueError("numpoints must be > 0; it was %d"% numpoints) # introduce y-offset for handles of the scatter plot if scatteryoffsets is None: self._scatteryoffsets = np.array([3./8., 4./8., 2.5/8.]) else: self._scatteryoffsets = np.asarray(scatteryoffsets) reps = int(self.scatterpoints / len(self._scatteryoffsets)) + 1 self._scatteryoffsets = np.tile(self._scatteryoffsets, reps)[:self.scatterpoints] # _legend_box is an OffsetBox instance that contains all # legend items and will be initialized from _init_legend_box() # method. self._legend_box = None if isinstance(parent,Axes): self.isaxes = True self.set_axes(parent) self.set_figure(parent.figure) elif isinstance(parent,Figure): self.isaxes = False self.set_figure(parent) else: raise TypeError("Legend needs either Axes or Figure as parent") self.parent = parent if loc is None: loc = rcParams["legend.loc"] if not self.isaxes and loc in [0,'best']: loc = 'upper right' if is_string_like(loc): if loc not in self.codes: if self.isaxes: warnings.warn('Unrecognized location "%s". Falling back on "best"; ' 'valid locations are\n\t%s\n' % (loc, '\n\t'.join(self.codes.iterkeys()))) loc = 0 else: warnings.warn('Unrecognized location "%s". Falling back on "upper right"; ' 'valid locations are\n\t%s\n' % (loc, '\n\t'.join(self.codes.iterkeys()))) loc = 1 else: loc = self.codes[loc] if not self.isaxes and loc == 0: warnings.warn('Automatic legend placement (loc="best") not implemented for figure legend. ' 'Falling back on "upper right".') loc = 1 self._mode = mode self.set_bbox_to_anchor(bbox_to_anchor, bbox_transform) # We use FancyBboxPatch to draw a legend frame. The location # and size of the box will be updated during the drawing time. self.legendPatch = FancyBboxPatch( xy=(0.0, 0.0), width=1., height=1., facecolor=rcParams["axes.facecolor"], edgecolor=rcParams["axes.edgecolor"], mutation_scale=self._fontsize, snap=True ) # The width and height of the legendPatch will be set (in the # draw()) to the length that includes the padding. Thus we set # pad=0 here. if fancybox is None: fancybox = rcParams["legend.fancybox"] if fancybox == True: self.legendPatch.set_boxstyle("round",pad=0, rounding_size=0.2) else: self.legendPatch.set_boxstyle("square",pad=0) self._set_artist_props(self.legendPatch) self._drawFrame = frameon if frameon is None: self._drawFrame = rcParams["legend.frameon"] # init with null renderer self._init_legend_box(handles, labels) self._loc = loc self.set_title(title) self._last_fontsize_points = self._fontsize self._draggable = None
def __init__(self, parent, handles, labels, loc=None, numpoints=None, # the number of points in the legend line markerscale=None, # the relative size of legend markers # vs. original markerfirst=True, # controls ordering (left-to-right) of # legend marker and label scatterpoints=None, # number of scatter points scatteryoffsets=None, prop=None, # properties for the legend texts fontsize=None, # keyword to set font size directly labelcolor=None, # keyword to set the text color # spacing & pad defined as a fraction of the font-size borderpad=None, # the whitespace inside the legend border labelspacing=None, # the vertical space between the legend # entries handlelength=None, # the length of the legend handles handleheight=None, # the height of the legend handles handletextpad=None, # the pad between the legend handle # and text borderaxespad=None, # the pad between the axes and legend # border columnspacing=None, # spacing between columns ncol=1, # number of columns mode=None, # mode for horizontal distribution of columns. # None, "expand" fancybox=None, # True use a fancy box, false use a rounded # box, none use rc shadow=None, title=None, # set a title for the legend title_fontsize=None, # the font size for the title framealpha=None, # set frame alpha edgecolor=None, # frame patch edgecolor facecolor=None, # frame patch facecolor bbox_to_anchor=None, # bbox that the legend will be anchored. bbox_transform=None, # transform for the bbox frameon=None, # draw frame handler_map=None, ): """ Parameters ---------- parent : `~matplotlib.axes.Axes` or `.Figure` The artist that contains the legend. handles : list of `.Artist` A list of Artists (lines, patches) to be added to the legend. labels : list of str A list of labels to show next to the artists. The length of handles and labels should be the same. If they are not, they are truncated to the smaller of both lengths. Other Parameters ---------------- %(_legend_kw_doc)s Notes ----- Users can specify any arbitrary location for the legend using the *bbox_to_anchor* keyword argument. *bbox_to_anchor* can be a `.BboxBase` (or derived therefrom) or a tuple of 2 or 4 floats. See `set_bbox_to_anchor` for more detail. The legend location can be specified by setting *loc* with a tuple of 2 floats, which is interpreted as the lower-left corner of the legend in the normalized axes coordinate. """ # local import only to avoid circularity from matplotlib.axes import Axes from matplotlib.figure import Figure Artist.__init__(self) if prop is None: if fontsize is not None: self.prop = FontProperties(size=fontsize) else: self.prop = FontProperties( size=mpl.rcParams["legend.fontsize"]) else: self.prop = FontProperties._from_any(prop) if isinstance(prop, dict) and "size" not in prop: self.prop.set_size(mpl.rcParams["legend.fontsize"]) self._fontsize = self.prop.get_size_in_points() self.texts = [] self.legendHandles = [] self._legend_title_box = None #: A dictionary with the extra handler mappings for this Legend #: instance. self._custom_handler_map = handler_map locals_view = locals() for name in ["numpoints", "markerscale", "shadow", "columnspacing", "scatterpoints", "handleheight", 'borderpad', 'labelspacing', 'handlelength', 'handletextpad', 'borderaxespad']: if locals_view[name] is None: value = mpl.rcParams["legend." + name] else: value = locals_view[name] setattr(self, name, value) del locals_view # trim handles and labels if illegal label... _lab, _hand = [], [] for label, handle in zip(labels, handles): if isinstance(label, str) and label.startswith('_'): cbook._warn_external('The handle {!r} has a label of {!r} ' 'which cannot be automatically added to' ' the legend.'.format(handle, label)) else: _lab.append(label) _hand.append(handle) labels, handles = _lab, _hand handles = list(handles) if len(handles) < 2: ncol = 1 self._ncol = ncol if self.numpoints <= 0: raise ValueError("numpoints must be > 0; it was %d" % numpoints) # introduce y-offset for handles of the scatter plot if scatteryoffsets is None: self._scatteryoffsets = np.array([3. / 8., 4. / 8., 2.5 / 8.]) else: self._scatteryoffsets = np.asarray(scatteryoffsets) reps = self.scatterpoints // len(self._scatteryoffsets) + 1 self._scatteryoffsets = np.tile(self._scatteryoffsets, reps)[:self.scatterpoints] # _legend_box is a VPacker instance that contains all # legend items and will be initialized from _init_legend_box() # method. self._legend_box = None if isinstance(parent, Axes): self.isaxes = True self.axes = parent self.set_figure(parent.figure) elif isinstance(parent, Figure): self.isaxes = False self.set_figure(parent) else: raise TypeError("Legend needs either Axes or Figure as parent") self.parent = parent self._loc_used_default = loc is None if loc is None: loc = mpl.rcParams["legend.loc"] if not self.isaxes and loc in [0, 'best']: loc = 'upper right' if isinstance(loc, str): if loc not in self.codes: raise ValueError( "Unrecognized location {!r}. Valid locations are\n\t{}\n" .format(loc, '\n\t'.join(self.codes))) else: loc = self.codes[loc] if not self.isaxes and loc == 0: raise ValueError( "Automatic legend placement (loc='best') not implemented for " "figure legend.") self._mode = mode self.set_bbox_to_anchor(bbox_to_anchor, bbox_transform) # We use FancyBboxPatch to draw a legend frame. The location # and size of the box will be updated during the drawing time. if facecolor is None: facecolor = mpl.rcParams["legend.facecolor"] if facecolor == 'inherit': facecolor = mpl.rcParams["axes.facecolor"] if edgecolor is None: edgecolor = mpl.rcParams["legend.edgecolor"] if edgecolor == 'inherit': edgecolor = mpl.rcParams["axes.edgecolor"] if fancybox is None: fancybox = mpl.rcParams["legend.fancybox"] self.legendPatch = FancyBboxPatch( xy=(0, 0), width=1, height=1, facecolor=facecolor, edgecolor=edgecolor, # If shadow is used, default to alpha=1 (#8943). alpha=(framealpha if framealpha is not None else 1 if shadow else mpl.rcParams["legend.framealpha"]), # The width and height of the legendPatch will be set (in draw()) # to the length that includes the padding. Thus we set pad=0 here. boxstyle=("round,pad=0,rounding_size=0.2" if fancybox else "square,pad=0"), mutation_scale=self._fontsize, snap=True, visible=(frameon if frameon is not None else mpl.rcParams["legend.frameon"]) ) self._set_artist_props(self.legendPatch) # init with null renderer self._init_legend_box(handles, labels, markerfirst) tmp = self._loc_used_default self._set_loc(loc) self._loc_used_default = tmp # ignore changes done by _set_loc # figure out title fontsize: if title_fontsize is None: title_fontsize = mpl.rcParams['legend.title_fontsize'] tprop = FontProperties(size=title_fontsize) self.set_title(title, prop=tprop) self._draggable = None # set the text color color_getters = { # getter function depends on line or patch 'linecolor': ['get_color', 'get_facecolor'], 'markerfacecolor': ['get_markerfacecolor', 'get_facecolor'], 'mfc': ['get_markerfacecolor', 'get_facecolor'], 'markeredgecolor': ['get_markeredgecolor', 'get_edgecolor'], 'mec': ['get_markeredgecolor', 'get_edgecolor'], } if labelcolor is None: pass elif isinstance(labelcolor, str) and labelcolor in color_getters: getter_names = color_getters[labelcolor] for handle, text in zip(self.legendHandles, self.texts): for getter_name in getter_names: try: color = getattr(handle, getter_name)() text.set_color(color) break except AttributeError: pass elif np.iterable(labelcolor): for text, color in zip(self.texts, itertools.cycle( colors.to_rgba_array(labelcolor))): text.set_color(color) else: raise ValueError("Invalid argument for labelcolor : %s" % str(labelcolor))
def __init__( self, parent, handles, labels, loc=None, numpoints=None, # the number of points in the legend line markerscale=None, # the relative size of legend markers # vs. original markerfirst=True, # controls ordering (left-to-right) of # legend marker and label scatterpoints=None, # number of scatter points scatteryoffsets=None, prop=None, # properties for the legend texts fontsize=None, # keyword to set font size directly # spacing & pad defined as a fraction of the font-size borderpad=None, # the whitespace inside the legend border labelspacing=None, # the vertical space between the legend # entries handlelength=None, # the length of the legend handles handleheight=None, # the height of the legend handles handletextpad=None, # the pad between the legend handle # and text borderaxespad=None, # the pad between the axes and legend # border columnspacing=None, # spacing between columns ncol=1, # number of columns mode=None, # mode for horizontal distribution of columns. # None, "expand" fancybox=None, # True use a fancy box, false use a rounded # box, none use rc shadow=None, title=None, # set a title for the legend framealpha=None, # set frame alpha bbox_to_anchor=None, # bbox that the legend will be anchored. bbox_transform=None, # transform for the bbox frameon=None, # draw frame handler_map=None, ): """ - *parent*: the artist that contains the legend - *handles*: a list of artists (lines, patches) to be added to the legend - *labels*: a list of strings to label the legend Optional keyword arguments: ================ ==================================================== Keyword Description ================ ==================================================== loc a location code prop the font property fontsize the font size (used only if prop is not specified) markerscale the relative size of legend markers vs. original markerfirst If true, place legend marker to left of label If false, place legend marker to right of label numpoints the number of points in the legend for line scatterpoints the number of points in the legend for scatter plot scatteryoffsets a list of yoffsets for scatter symbols in legend frameon if True, draw a frame around the legend. If None, use rc fancybox if True, draw a frame with a round fancybox. If None, use rc shadow if True, draw a shadow behind legend framealpha If not None, alpha channel for the frame. ncol number of columns borderpad the fractional whitespace inside the legend border labelspacing the vertical space between the legend entries handlelength the length of the legend handles handleheight the height of the legend handles handletextpad the pad between the legend handle and text borderaxespad the pad between the axes and legend border columnspacing the spacing between columns title the legend title bbox_to_anchor the bbox that the legend will be anchored. bbox_transform the transform for the bbox. transAxes if None. ================ ==================================================== The pad and spacing parameters are measured in font-size units. e.g., a fontsize of 10 points and a handlelength=5 implies a handlelength of 50 points. Values from rcParams will be used if None. Users can specify any arbitrary location for the legend using the *bbox_to_anchor* keyword argument. bbox_to_anchor can be an instance of BboxBase(or its derivatives) or a tuple of 2 or 4 floats. See :meth:`set_bbox_to_anchor` for more detail. The legend location can be specified by setting *loc* with a tuple of 2 floats, which is interpreted as the lower-left corner of the legend in the normalized axes coordinate. """ # local import only to avoid circularity from matplotlib.axes import Axes from matplotlib.figure import Figure Artist.__init__(self) if prop is None: if fontsize is not None: self.prop = FontProperties(size=fontsize) else: self.prop = FontProperties(size=rcParams["legend.fontsize"]) elif isinstance(prop, dict): self.prop = FontProperties(**prop) if "size" not in prop: self.prop.set_size(rcParams["legend.fontsize"]) else: self.prop = prop self._fontsize = self.prop.get_size_in_points() self.texts = [] self.legendHandles = [] self._legend_title_box = None #: A dictionary with the extra handler mappings for this Legend #: instance. self._custom_handler_map = handler_map locals_view = locals() for name in [ "numpoints", "markerscale", "shadow", "columnspacing", "scatterpoints", "handleheight", 'borderpad', 'labelspacing', 'handlelength', 'handletextpad', 'borderaxespad' ]: if locals_view[name] is None: value = rcParams["legend." + name] else: value = locals_view[name] setattr(self, name, value) del locals_view handles = list(handles) if len(handles) < 2: ncol = 1 self._ncol = ncol if self.numpoints <= 0: raise ValueError("numpoints must be > 0; it was %d" % numpoints) # introduce y-offset for handles of the scatter plot if scatteryoffsets is None: self._scatteryoffsets = np.array([3. / 8., 4. / 8., 2.5 / 8.]) else: self._scatteryoffsets = np.asarray(scatteryoffsets) reps = int(self.scatterpoints / len(self._scatteryoffsets)) + 1 self._scatteryoffsets = np.tile(self._scatteryoffsets, reps)[:self.scatterpoints] # _legend_box is an OffsetBox instance that contains all # legend items and will be initialized from _init_legend_box() # method. self._legend_box = None if isinstance(parent, Axes): self.isaxes = True self.axes = parent self.set_figure(parent.figure) elif isinstance(parent, Figure): self.isaxes = False self.set_figure(parent) else: raise TypeError("Legend needs either Axes or Figure as parent") self.parent = parent if loc is None: loc = rcParams["legend.loc"] if not self.isaxes and loc in [0, 'best']: loc = 'upper right' if is_string_like(loc): if loc not in self.codes: if self.isaxes: warnings.warn('Unrecognized location "%s". Falling back ' 'on "best"; valid locations are\n\t%s\n' % (loc, '\n\t'.join(six.iterkeys(self.codes)))) loc = 0 else: warnings.warn('Unrecognized location "%s". Falling back ' 'on "upper right"; ' 'valid locations are\n\t%s\n' % (loc, '\n\t'.join(six.iterkeys(self.codes)))) loc = 1 else: loc = self.codes[loc] if not self.isaxes and loc == 0: warnings.warn('Automatic legend placement (loc="best") not ' 'implemented for figure legend. ' 'Falling back on "upper right".') loc = 1 self._mode = mode self.set_bbox_to_anchor(bbox_to_anchor, bbox_transform) # We use FancyBboxPatch to draw a legend frame. The location # and size of the box will be updated during the drawing time. self.legendPatch = FancyBboxPatch(xy=(0.0, 0.0), width=1., height=1., facecolor=rcParams["axes.facecolor"], edgecolor=rcParams["axes.edgecolor"], mutation_scale=self._fontsize, snap=True) # The width and height of the legendPatch will be set (in the # draw()) to the length that includes the padding. Thus we set # pad=0 here. if fancybox is None: fancybox = rcParams["legend.fancybox"] if fancybox: self.legendPatch.set_boxstyle("round", pad=0, rounding_size=0.2) else: self.legendPatch.set_boxstyle("square", pad=0) self._set_artist_props(self.legendPatch) self._drawFrame = frameon if frameon is None: self._drawFrame = rcParams["legend.frameon"] # init with null renderer self._init_legend_box(handles, labels, markerfirst) if framealpha is None: self.get_frame().set_alpha(rcParams["legend.framealpha"]) else: self.get_frame().set_alpha(framealpha) self._loc = loc self.set_title(title) self._last_fontsize_points = self._fontsize self._draggable = None
def __init__(self, parent, handles, labels, loc = None, numpoints = None, # the number of points in the legend line markerscale = None, # the relative size of legend markers vs. original scatterpoints = 3, # TODO: may be an rcParam scatteryoffsets=None, prop = None, # properties for the legend texts # the following dimensions are in axes coords pad = None, # deprecated; use borderpad labelsep = None, # deprecated; use labelspacing handlelen = None, # deprecated; use handlelength handletextsep = None, # deprecated; use handletextpad axespad = None, # deprecated; use borderaxespad # spacing & pad defined as a fractionof the font-size borderpad = None, # the whitespace inside the legend border labelspacing=None, #the vertical space between the legend entries handlelength=None, # the length of the legend handles handletextpad=None, # the pad between the legend handle and text borderaxespad=None, # the pad between the axes and legend border columnspacing=None, # spacing between columns ncol=1, # number of columns mode=None, # mode for horizontal distribution of columns. None, "expand" shadow = None, ): """ - *parent* : the artist that contains the legend - *handles* : a list of artists (lines, patches) to add to the legend - *labels* : a list of strings to label the legend Optional keyword arguments: ================ ================================================= Keyword Description ================ ================================================= loc a location code or a tuple of coordinates numpoints the number of points in the legend line prop the font property markerscale the relative size of legend markers vs. original shadow if True, draw a shadow behind legend scatteryoffsets a list of yoffsets for scatter symbols in legend borderpad the fractional whitespace inside the legend border labelspacing the vertical space between the legend entries handlelength the length of the legend handles handletextpad the pad between the legend handle and text borderaxespad the pad between the axes and legend border columnspacing the spacing between columns The dimensions of pad and spacing are given as a fraction of the fontsize. Values from rcParams will be used if None. """ from matplotlib.axes import Axes # local import only to avoid circularity from matplotlib.figure import Figure # local import only to avoid circularity Artist.__init__(self) if prop is None: self.prop=FontProperties(size=rcParams["legend.fontsize"]) else: self.prop=prop self.fontsize = self.prop.get_size_in_points() propnames=['numpoints', 'markerscale', 'shadow', "columnspacing", "scatterpoints"] localdict = locals() for name in propnames: if localdict[name] is None: value = rcParams["legend."+name] else: value = localdict[name] setattr(self, name, value) # Take care the deprecated keywords deprecated_kwds = {"pad":"borderpad", "labelsep":"labelspacing", "handlelen":"handlelength", "handletextsep":"handletextpad", "axespad":"borderaxespad"} # convert values of deprecated keywords (ginve in axes coords) # to new vaules in a fraction of the font size # conversion factor bbox = parent.bbox axessize_fontsize = min(bbox.width, bbox.height)/self.fontsize for k, v in deprecated_kwds.items(): # use deprecated value if not None and if their newer # counter part is None. if localdict[k] is not None and localdict[v] is None: warnings.warn("Use '%s' instead of '%s'." % (v, k), DeprecationWarning) setattr(self, v, localdict[k]*axessize_fontsize) continue # Otherwise, use new keywords if localdict[v] is None: setattr(self, v, rcParams["legend."+v]) else: setattr(self, v, localdict[v]) del localdict self._ncol = ncol if self.numpoints <= 0: raise ValueError("numpoints must be >= 0; it was %d"% numpoints) # introduce y-offset for handles of the scatter plot if scatteryoffsets is None: self._scatteryoffsets = np.array([3./8., 4./8., 2.5/8.]) else: self._scatteryoffsets = np.asarray(scatteryoffsets) reps = int(self.numpoints / len(self._scatteryoffsets)) + 1 self._scatteryoffsets = np.tile(self._scatteryoffsets, reps)[:self.scatterpoints] # _legend_box is an OffsetBox instance that contains all # legend items and will be initialized from _init_legend_box() # method. self._legend_box = None if isinstance(parent,Axes): self.isaxes = True self.set_figure(parent.figure) elif isinstance(parent,Figure): self.isaxes = False self.set_figure(parent) else: raise TypeError("Legend needs either Axes or Figure as parent") self.parent = parent if loc is None: loc = rcParams["legend.loc"] if not self.isaxes and loc in [0,'best']: loc = 'upper right' if is_string_like(loc): if loc not in self.codes: if self.isaxes: warnings.warn('Unrecognized location "%s". Falling back on "best"; ' 'valid locations are\n\t%s\n' % (loc, '\n\t'.join(self.codes.keys()))) loc = 0 else: warnings.warn('Unrecognized location "%s". Falling back on "upper right"; ' 'valid locations are\n\t%s\n' % (loc, '\n\t'.join(self.codes.keys()))) loc = 1 else: loc = self.codes[loc] if not self.isaxes and loc == 0: warnings.warn('Automatic legend placement (loc="best") not implemented for figure legend. ' 'Falling back on "upper right".') loc = 1 self._loc = loc self._mode = mode # We use FancyBboxPatch to draw a legend frame. The location # and size of the box will be updated during the drawing time. self.legendPatch = FancyBboxPatch( xy=(0.0, 0.0), width=1., height=1., facecolor='w', edgecolor='k', mutation_scale=self.fontsize, ) # The width and height of the legendPatch will be set (in the # draw()) to the length that includes the padding. Thus we set # pad=0 here. self.legendPatch.set_boxstyle("round",pad=0, #self.borderpad, rounding_size=0.2) self._set_artist_props(self.legendPatch) self._drawFrame = True # populate the legend_box with legend items. self._init_legend_box(handles, labels) self._legend_box.set_figure(self.figure)