def properties(self): """ return a dictionary mapping property name -> value """ o = self.oorig getters = [name for name in dir(o) if name.startswith('get_') and six.callable(getattr(o, name))] getters.sort() d = dict() for name in getters: func = getattr(o, name) if self.is_alias(func): continue try: with warnings.catch_warnings(): warnings.simplefilter('ignore') val = func() except: continue else: d[name[4:]] = val return d
def get_aliases(self): """ Get a dict mapping *fullname* -> *alias* for each *alias* in the :class:`~matplotlib.artist.ArtistInspector`. e.g., for lines:: {'markerfacecolor': 'mfc', 'linewidth' : 'lw', } """ names = [ name for name in dir(self.o) if (name.startswith("set_") or name.startswith("get_")) and six.callable(getattr(self.o, name)) ] aliases = {} for name in names: func = getattr(self.o, name) if not self.is_alias(func): continue docstring = func.__doc__ fullname = docstring[10:] aliases.setdefault(fullname[4:], {})[name[4:]] = None return aliases
def _get_setters_and_targets(self): """ Get the attribute strings and a full path to where the setter is defined for all setters in an object. """ setters = [] for name in dir(self.o): if not name.startswith("set_"): continue o = getattr(self.o, name) if not six.callable(o): continue if len(inspect.getargspec(o)[0]) < 2: continue func = o if self.is_alias(func): continue source_class = self.o.__module__ + "." + self.o.__name__ for cls in self.o.mro(): if name in cls.__dict__: source_class = cls.__module__ + "." + cls.__name__ break setters.append((name[4:], source_class + "." + name)) return setters
def pick(self, mouseevent): """ call signature:: pick(mouseevent) each child artist will fire a pick event if *mouseevent* is over the artist and the artist has picker set """ # Pick self if self.pickable(): picker = self.get_picker() if six.callable(picker): inside, prop = picker(self, mouseevent) else: inside, prop = self.contains(mouseevent) if inside: self.figure.canvas.pick_event(mouseevent, self, **prop) # Pick children for a in self.get_children(): # make sure the event happened in the same axes ax = getattr(a, "axes", None) if mouseevent.inaxes is None or ax is None or mouseevent.inaxes == ax: # we need to check if mouseevent.inaxes is None # because some objects associated with an axes (e.g., a # tick label) can be outside the bounding box of the # axes and inaxes will be None # also check that ax is None so that it traverse objects # which do no have an axes property but children might a.pick(mouseevent)
def get_window_extent(self, renderer=None): if renderer is None: renderer = self.get_figure()._cachedRenderer if isinstance(self.bbox, BboxBase): return self.bbox elif six.callable(self.bbox): return self.bbox(renderer) else: raise ValueError("unknown type of bbox")
def set_picker(self, p): """Sets the event picker details for the line. ACCEPTS: float distance in points or callable pick function ``fn(artist, event)`` """ if six.callable(p): self._contains = p else: self.pickradius = p self._picker = p
def contains(self, mouseevent): """Test whether the artist contains the mouse event. Returns the truth value and a dictionary of artist specific details of selection, such as which points are contained in the pick radius. See individual artists for details. """ if six.callable(self._contains): return self._contains(self, mouseevent) warnings.warn("'%s' needs 'contains' method" % self.__class__.__name__) return False, {}
def contains(self, mouseevent): """Test whether the mouse event occured within the image.""" if six.callable(self._contains): return self._contains(self, mouseevent) if not self.get_visible(): # or self.get_figure()._renderer is None: return False, {} x, y = mouseevent.x, mouseevent.y inside = self.get_window_extent().contains(x, y) return inside, {}
def contains(self, mouseevent): """Test whether the mouse event occured within the image.""" if six.callable(self._contains): return self._contains(self, mouseevent) xmin, xmax, ymin, ymax = self.get_extent() xdata, ydata = mouseevent.x, mouseevent.y if xdata is not None and ydata is not None: inside = (xdata >= xmin) and (xdata <= xmax) and (ydata >= ymin) and (ydata <= ymax) else: inside = False return inside, {}
def __init__(self, fig, func, frames=None, init_func=None, fargs=None, save_count=None, **kwargs): if fargs: self._args = fargs else: self._args = () self._func = func # Amount of framedata to keep around for saving movies. This is only # used if we don't know how many frames there will be: in the case # of no generator or in the case of a callable. self.save_count = save_count # Set up a function that creates a new iterable when needed. If nothing # is passed in for frames, just use itertools.count, which will just # keep counting from 0. A callable passed in for frames is assumed to # be a generator. An iterable will be used as is, and anything else # will be treated as a number of frames. if frames is None: self._iter_gen = itertools.count elif six.callable(frames): self._iter_gen = frames elif iterable(frames): self._iter_gen = lambda: iter(frames) if hasattr(frames, '__len__'): self.save_count = len(frames) else: self._iter_gen = lambda: xrange(frames).__iter__() self.save_count = frames # If we're passed in and using the default, set it to 100. if self.save_count is None: self.save_count = 100 self._init_func = init_func # Needs to be initialized so the draw functions work without checking self._save_seq = [] TimedAnimation.__init__(self, fig, **kwargs) # Need to reset the saved seq, since right now it will contain data # for a single frame from init, which is not what we want. self._save_seq = []
def contains(self, mouseevent): """Test whether the mouse event occured within the image.""" if six.callable(self._contains): return self._contains(self, mouseevent) xmin, xmax, ymin, ymax = self.get_extent() xdata, ydata = mouseevent.x, mouseevent.y if xdata is not None and ydata is not None: inside = ((xdata >= xmin) and (xdata <= xmax) and (ydata >= ymin) and (ydata <= ymax)) else: inside = False return inside, {}
def revcmap(data): """Can only handle specification *data* in dictionary format.""" data_r = {} for key, val in six.iteritems(data): if six.callable(val): valnew = _reverser(val) # This doesn't work: lambda x: val(1-x) # The same "val" (the first one) is used # each time, so the colors are identical # and the result is shades of gray. else: # Flip x and exchange the y values facing x = 0 and x = 1. valnew = [(1.0 - x, y1, y0) for x, y0, y1 in reversed(val)] data_r[key] = valnew return data_r
def findobj(self, match=None, include_self=True): """ Find artist objects. Recursively find all :class:`~matplotlib.artist.Artist` instances contained in self. *match* can be - None: return all objects contained in artist. - function with signature ``boolean = match(artist)`` used to filter matches - class instance: e.g., Line2D. Only return artists of class type. If *include_self* is True (default), include self in the list to be checked for a match. """ if match is None: # always return True def matchfunc(x): return True elif cbook.issubclass_safe(match, Artist): def matchfunc(x): return isinstance(x, match) elif six.callable(match): matchfunc = match else: raise ValueError('match must be None, a matplotlib.artist.Artist ' 'subclass, or a callable') artists = [] for c in self.get_children(): if matchfunc(c): artists.append(c) artists.extend([ thisc for thisc in c.findobj(matchfunc, include_self=False) if matchfunc(thisc) ]) if include_self and matchfunc(self): artists.append(self) return artists
def findobj(self, match=None, include_self=True): """ Find artist objects. Recursively find all :class:`~matplotlib.artist.Artist` instances contained in self. *match* can be - None: return all objects contained in artist. - function with signature ``boolean = match(artist)`` used to filter matches - class instance: e.g., Line2D. Only return artists of class type. If *include_self* is True (default), include self in the list to be checked for a match. """ if match is None: # always return True def matchfunc(x): return True elif cbook.issubclass_safe(match, Artist): def matchfunc(x): return isinstance(x, match) elif six.callable(match): matchfunc = match else: raise ValueError("match must be None, a matplotlib.artist.Artist " "subclass, or a callable") artists = [] for c in self.get_children(): if matchfunc(c): artists.append(c) artists.extend([thisc for thisc in c.findobj(matchfunc, include_self=False) if matchfunc(thisc)]) if include_self and matchfunc(self): artists.append(self) return artists
def contains(self, mouseevent): """Test whether the mouse event occurred in the table. Returns T/F, {} """ if six.callable(self._contains): return self._contains(self, mouseevent) # TODO: Return index of the cell containing the cursor so that the user # doesn't have to bind to each one individually. if self._cachedRenderer is not None: boxes = [self._cells[pos].get_window_extent(self._cachedRenderer) for pos in six.iterkeys(self._cells) if pos[0] >= 0 and pos[1] >= 0] bbox = Bbox.union(boxes) return bbox.contains(mouseevent.x, mouseevent.y), {} else: return False, {}
def __call__(self, x, pos=None): locator_unit_scale = float(self._locator._get_unit()) fmt = self.defaultfmt # Pick the first scale which is greater than the locator unit. for possible_scale in sorted(self.scaled): if possible_scale >= locator_unit_scale: fmt = self.scaled[possible_scale] break if isinstance(fmt, six.string_types): self._formatter = DateFormatter(fmt, self._tz) result = self._formatter(x, pos) elif six.callable(fmt): result = fmt(x, pos) else: raise TypeError('Unexpected type passed to {!r}.'.formatter(self)) return result
def _update_gc(self, gc, new_gc_dict): """ Update the given GraphicsCollection with the given dictionary of properties. The keys in the dictionary are used to identify the appropriate set_ method on the gc. """ new_gc_dict = new_gc_dict.copy() dashes = new_gc_dict.pop("dashes", None) if dashes: gc.set_dashes(**dashes) for k, v in six.iteritems(new_gc_dict): set_method = getattr(gc, 'set_' + k, None) if set_method is None or not six.callable(set_method): raise AttributeError('Unknown property {0}'.format(k)) set_method(v) return gc
def properties(self): """ return a dictionary mapping property name -> value """ o = self.oorig getters = [name for name in dir(o) if name.startswith("get_") and six.callable(getattr(o, name))] getters.sort() d = dict() for name in getters: func = getattr(o, name) if self.is_alias(func): continue try: val = func() except: continue else: d[name[4:]] = val return d
def wrap(self, fmt, func, level='helpful', always=True): """ return a callable function that wraps func and reports it output through the verbose handler if current verbosity level is higher than level if always is True, the report will occur on every function call; otherwise only on the first time the function is called """ assert six.callable(func) def wrapper(*args, **kwargs): ret = func(*args, **kwargs) if (always or not wrapper._spoke): spoke = self.report(fmt % ret, level) if not wrapper._spoke: wrapper._spoke = spoke return ret wrapper._spoke = False wrapper.__doc__ = func.__doc__ return wrapper
def update(self, props): """ Update the properties of this :class:`Artist` from the dictionary *prop*. """ store = self.eventson self.eventson = False changed = False for k, v in six.iteritems(props): if k in ['axes']: setattr(self, k, v) else: func = getattr(self, 'set_' + k, None) if func is None or not six.callable(func): raise AttributeError('Unknown property %s' % k) func(v) changed = True self.eventson = store if changed: self.pchanged() self.stale = True
def update(self, props): """ Update the properties of this :class:`Artist` from the dictionary *prop*. """ store = self.eventson self.eventson = False changed = False for k, v in six.iteritems(props): if k in ["axes"]: setattr(self, k, v) else: func = getattr(self, "set_" + k, None) if func is None or not six.callable(func): raise AttributeError("Unknown property %s" % k) func(v) changed = True self.eventson = store if changed: self.pchanged() self.stale = True
def findobj(self, match=None): """ Recursively find all :class:`matplotlib.artist.Artist` instances contained in *self*. If *match* is not None, it can be - function with signature ``boolean = match(artist)`` - class instance: e.g., :class:`~matplotlib.lines.Line2D` used to filter matches. """ if match is None: # always return True def matchfunc(x): return True elif issubclass(match, Artist): def matchfunc(x): return isinstance(x, match) elif six.callable(match): matchfunc = func else: raise ValueError('match must be None, an ' 'matplotlib.artist.Artist ' 'subclass, or a callable') artists = [] for c in self.get_children(): if matchfunc(c): artists.append(c) artists.extend([thisc for thisc in c.findobj(matchfunc) if matchfunc(thisc)]) if matchfunc(self): artists.append(self) return artists
def contains(self, mouseevent): """ Test whether the mouse event occured within the image. """ if six.callable(self._contains): return self._contains(self, mouseevent) # TODO: make sure this is consistent with patch and patch # collection on nonlinear transformed coordinates. # TODO: consider returning image coordinates (shouldn't # be too difficult given that the image is rectilinear x, y = mouseevent.xdata, mouseevent.ydata xmin, xmax, ymin, ymax = self.get_extent() if xmin > xmax: xmin, xmax = xmax, xmin if ymin > ymax: ymin, ymax = ymax, ymin if x is not None and y is not None: inside = (x >= xmin) and (x <= xmax) and (y >= ymin) and (y <= ymax) else: inside = False return inside, {}
def properties(self): """ return a dictionary mapping property name -> value """ o = self.oorig getters = [name for name in dir(o) if name.startswith('get_') and six.callable(getattr(o, name))] getters.sort() d = dict() for name in getters: func = getattr(o, name) if self.is_alias(func): continue try: val = func() except: continue else: d[name[4:]] = val return d
def contains(self, mouseevent): """ Test whether the mouse event occured within the image. """ if six.callable(self._contains): return self._contains(self, mouseevent) # TODO: make sure this is consistent with patch and patch # collection on nonlinear transformed coordinates. # TODO: consider returning image coordinates (shouldn't # be too difficult given that the image is rectilinear x, y = mouseevent.xdata, mouseevent.ydata xmin, xmax, ymin, ymax = self.get_extent() if xmin > xmax: xmin, xmax = xmax, xmin if ymin > ymax: ymin, ymax = ymax, ymin if x is not None and y is not None: inside = ((x >= xmin) and (x <= xmax) and (y >= ymin) and (y <= ymax)) else: inside = False return inside, {}
def _update_property(self, k, v): """sorting out how to update property (setter or setattr) Parameters ---------- k : str The name of property to update v : obj The value to assign to the property Returns ------- ret : obj or None If using a `set_*` method return it's return, else None. """ k = k.lower() # white list attributes we want to be able to update through # art.update, art.set, setp if k in {'axes'}: return setattr(self, k, v) else: func = getattr(self, 'set_' + k, None) if func is None or not six.callable(func): raise AttributeError('Unknown property %s' % k) return func(v)
def get_aliases(self): """ Get a dict mapping *fullname* -> *alias* for each *alias* in the :class:`~matplotlib.artist.ArtistInspector`. e.g., for lines:: {'markerfacecolor': 'mfc', 'linewidth' : 'lw', } """ names = [name for name in dir(self.o) if (name.startswith('set_') or name.startswith('get_')) and six.callable(getattr(self.o, name))] aliases = {} for name in names: func = getattr(self.o, name) if not self.is_alias(func): continue docstring = func.__doc__ fullname = docstring[10:] aliases.setdefault(fullname[4:], {})[name[4:]] = None return aliases
def contains(self, mouseevent): """ Test whether the mouse event occurred on the line. The pick radius determines the precision of the location test (usually within five points of the value). Use :meth:`~matplotlib.lines.Line2D.get_pickradius` or :meth:`~matplotlib.lines.Line2D.set_pickradius` to view or modify it. Returns *True* if any values are within the radius along with ``{'ind': pointlist}``, where *pointlist* is the set of points within the radius. TODO: sort returned indices by distance """ if six.callable(self._contains): return self._contains(self, mouseevent) if not is_numlike(self.pickradius): raise ValueError("pick radius should be a distance") # Make sure we have data to plot if self._invalidy or self._invalidx: self.recache() if len(self._xy) == 0: return False, {} # Convert points to pixels transformed_path = self._get_transformed_path() path, affine = transformed_path.get_transformed_path_and_affine() path = affine.transform_path(path) xy = path.vertices xt = xy[:, 0] yt = xy[:, 1] # Convert pick radius from points to pixels if self.figure is None: warnings.warn('no figure set when check if mouse is on line') pixels = self.pickradius else: pixels = self.figure.dpi / 72. * self.pickradius # the math involved in checking for containment (here and inside of # segment_hits) assumes that it is OK to overflow. In case the # application has set the error flags such that an exception is raised # on overflow, we temporarily set the appropriate error flags here and # set them back when we are finished. olderrflags = np.seterr(all='ignore') try: # Check for collision if self._linestyle in ['None', None]: # If no line, return the nearby point(s) d = (xt - mouseevent.x) ** 2 + (yt - mouseevent.y) ** 2 ind, = np.nonzero(np.less_equal(d, pixels ** 2)) else: # If line, return the nearby segment(s) ind = segment_hits(mouseevent.x, mouseevent.y, xt, yt, pixels) finally: np.seterr(**olderrflags) ind += self.ind_offset # Debugging message if False and self._label != '': print("Checking line", self._label, "at", mouseevent.x, mouseevent.y) print('xt', xt) print('yt', yt) #print 'dx,dy', (xt-mouseevent.x)**2., (yt-mouseevent.y)**2. print('ind', ind) # Return the point(s) within radius return len(ind) > 0, dict(ind=ind)
def contains(self, mouseevent): """ Test whether the mouse event occurred on the line. The pick radius determines the precision of the location test (usually within five points of the value). Use :meth:`~matplotlib.lines.Line2D.get_pickradius` or :meth:`~matplotlib.lines.Line2D.set_pickradius` to view or modify it. Returns *True* if any values are within the radius along with ``{'ind': pointlist}``, where *pointlist* is the set of points within the radius. TODO: sort returned indices by distance """ if six.callable(self._contains): return self._contains(self, mouseevent) if not is_numlike(self.pickradius): raise ValueError("pick radius should be a distance") # Make sure we have data to plot if self._invalidy or self._invalidx: self.recache() if len(self._xy) == 0: return False, {} # Convert points to pixels transformed_path = self._get_transformed_path() path, affine = transformed_path.get_transformed_path_and_affine() path = affine.transform_path(path) xy = path.vertices xt = xy[:, 0] yt = xy[:, 1] # Convert pick radius from points to pixels if self.figure is None: warnings.warn('no figure set when check if mouse is on line') pixels = self.pickradius else: pixels = self.figure.dpi / 72. * self.pickradius # the math involved in checking for containment (here and inside of # segment_hits) assumes that it is OK to overflow. In case the # application has set the error flags such that an exception is raised # on overflow, we temporarily set the appropriate error flags here and # set them back when we are finished. olderrflags = np.seterr(all='ignore') try: # Check for collision if self._linestyle in ['None', None]: # If no line, return the nearby point(s) d = (xt - mouseevent.x)**2 + (yt - mouseevent.y)**2 ind, = np.nonzero(np.less_equal(d, pixels**2)) else: # If line, return the nearby segment(s) ind = segment_hits(mouseevent.x, mouseevent.y, xt, yt, pixels) finally: np.seterr(**olderrflags) ind += self.ind_offset # Debugging message if False and self._label != '': print("Checking line", self._label, "at", mouseevent.x, mouseevent.y) print('xt', xt) print('yt', yt) #print 'dx,dy', (xt-mouseevent.x)**2., (yt-mouseevent.y)**2. print('ind', ind) # Return the point(s) within radius return len(ind) > 0, dict(ind=ind)