import matplotlib import matplotlib.pyplot as plt %matplotlib inline from collections import OrderedDict class Line2DController(object): arg_pos = ['xdata', 'ydata', 'linewidth', 'linestyle', 'color', 'marker', 'markersize', 'markeredgewidth', 'markeredgecolor', 'markerfacecolor', 'markerfacecoloralt', 'fillstyle', 'antialiased', 'dash_capstyle', 'solid_capstyle', 'dash_joinstyle', 'pickradius', 'drawstyle', 'markevery'] defaults = dict( linewidth=None, linestyle=None, color=None, marker=None, markersize=None, markeredgewidth=None, markeredgecolor=None, markerfacecolor=None, markerfacecoloralt=u'none', fillstyle=u'full', antialiased=None, dash_capstyle=None, solid_capstyle=None, dash_joinstyle=None, solid_joinstyle=None, pickradius=5, drawstyle=None, markevery=None ) def __init__(self, ax, *args, **kwargs): for key, val in self.get_args_mapping(args).items(): setattr(self, key, val) for key, val in kwargs.items(): if not hasattr(self, key): setattr(self, key, val) for key, val in self.defaults.items(): if not hasattr(self, key): # make sure it wasn't set already setattr(self, key, val) self.ax = ax self.line = matplotlib.lines.Line2D(*args, **kwargs) ax.add_line(self.line) ax.relim() ax.autoscale_view() def redraw(self): kwargs = self.get_attributes() self.ax.lines.remove(self.line) self.line = matplotlib.lines.Line2D(**kwargs) self.ax.add_line(self.line) ax.relim() ax.autoscale_view() def get_args_mapping(self, args): d = {} for iii, arg in enumerate(args): d[self.arg_pos[iii]] = arg return d def get_attributes(self): d = {} for key in self.defaults: d[key] = getattr(self, key) d['xdata'] = self.xdata d['ydata'] = self.ydata return d def __setitem__(self, key, val): if key not in set.union(set(self.arg_pos), set(self.defaults)): raise Exception("don't do that...") else: setattr(self, key, val) self.redraw() def to_json(self): d = self.get_attributes() return d fig, ax = plt.subplots() lc1 = Line2DController(ax, [1,2,3], [2,1,2]) lc2 = Line2DController(ax, **lc1.to_json()) # obviously, we need to work out the axes reference... # this behavior is key, we want to be able to just set attributes with the controller # this will allow simple eventual instantiation with `**kwargs` lc1['color'] = 'r' lc1['xdata'] = [2, 3, 4] lc1['ydata'] = [10, 3, 6] lc1['marker'] = 'o' lc1['markeredgewidth'] = 10 lc1['linewidth'] = 10 fig lc1.to_json() lc2.to_json()