Exemple #1
0
class BasicGrapher(grapher.BasicGrapher):
    """Documentation string for Basic Grapher

    A simple graphing widget
    By Randy P. and Bart O."""
    def __init__(self, parent=None, **kw):
        self.ax = Figure(figsize=(4.3, 3.0)).gca()
        self.ax2d = self.ax
        self.ax3d = None
        if kw.get("hide"):
            self.canvas = FigureCanvasAgg(self.ax.get_figure())
        else:
            self.canvas = FigureCanvasTkAggRedraw(self, parent)
            tk_widget = self.canvas.get_tk_widget()
            self.quit = tk_widget.quit
            self.bind = tk_widget.bind
            self.unbind = tk_widget.unbind
            self.winfo_rootx = tk_widget.winfo_rootx
            self.winfo_rooty = tk_widget.winfo_rooty
        self.ax.set_autoscale_on(0)
        self.postscript = self.canvas.print_figure
        self.savefig = self.ax.get_figure().savefig

        self.redrawlabels = 0

        callback = self.__optionCallback
        grapher.BasicGrapher.__init__(self, parent, callback, **kw)
        optionDefaults = {}
        optionDefaults["xticks"] = (None, callback)
        optionDefaults["yticks"] = (None, callback)
        optionDefaults["zticks"] = (None, callback)
        optionDefaults["background"] = ("white", callback)
        optionAliases = {}
        optionAliases["bg"] = "background"

        self.addOptions(**optionDefaults)
        self.addAliases(**optionAliases)

        for key in [
                "grid", "decorations", "xlabel", "ylabel", "zlabel",
                "xlabel_fontsize", "ylabel_fontsize", "zlabel_fontsize",
                "minx", "maxx", "miny", "maxy", "minz", "maxz", "width",
                "height", "left_margin", "right_margin", "top_margin",
                "bottom_margin"
        ]:
            self.__optionCallback(key, self.cget(key), [])
        matplotlib.rcParams["axes.edgecolor"] = self.cget("foreground")

    def pack(self, **kw):
        self.canvas.get_tk_widget().pack(kw)

    def update(self):
        if isinstance(self.canvas, FigureCanvasTkAggRedraw):
            self.canvas.get_tk_widget().update()
            FigureCanvasTkAgg.draw(self.canvas)
        else:
            self.canvas.draw()

    def __optionCallback(self, key, value, options):
        if key in [
                "minx", "maxx", "miny", "maxy", "minz", "maxz", "realwidth",
                "realheight", "azimuth", "elevation", "left_margin",
                "right_margin", "top_margin", "bottom_margin"
        ]:
            self.redrawlabels = 1
            if key[:3] in ["min", "max"]:
                minc = self.cget("min" + key[3])
                maxc = self.cget("max" + key[3])
                if minc < maxc:
                    func = None
                    if self.ax is self.ax3d:
                        func = getattr(self.ax, "set_" + key[3] + "lim3d")
                        self._cur_lims = (Axes.get_xlim(self.ax),
                                          Axes.get_ylim(self.ax))
                    elif key[3] != 'z':
                        func = getattr(self.ax, "set_" + key[3] + "lim")
                    if func is not None:
                        func(minc, maxc)
                        tickskey = key[3] + "ticks"
                        ticksval = self.cget(tickskey)
                        if ticksval is not None:
                            self.__optionCallback(tickskey, ticksval, options)
            elif key == "realwidth":
                lm = float(self.cget("left_margin"))
                rm = float(self.cget("right_margin"))
                self.ax.get_figure().subplots_adjust(left=lm / value,
                                                     right=1 - rm / value)
            elif key == "realheight":
                tm = float(self.cget("top_margin"))
                bm = float(self.cget("bottom_margin"))
                top = 1 - tm / value
                bottom = bm / value
                if top > bottom:
                    self.ax.get_figure().subplots_adjust(top=top,
                                                         bottom=bottom)
            elif key == "left_margin":
                fig = self.ax.get_figure()
                width = fig.get_figwidth() * fig.get_dpi()
                fig.subplots_adjust(left=value / width)
            elif key == "right_margin":
                fig = self.ax.get_figure()
                width = fig.get_figwidth() * fig.get_dpi()
                fig.subplots_adjust(right=1 - value / width)
            elif key == "top_margin":
                fig = self.ax.get_figure()
                height = fig.get_figheight() * fig.get_dpi()
                fig.subplots_adjust(top=1 - value / height)
            elif key == "bottom_margin":
                fig = self.ax.get_figure()
                height = fig.get_figheight() * fig.get_dpi()
                fig.subplots_adjust(bottom=value / height)
            elif self.ax is self.ax3d:
                elev = self.cget("elevation")
                azim = self.cget("azimuth")
                if elev is not None or azim is not None:
                    self.ax.view_init(elev, azim)
        elif key == "grid":
            if value in ["yes", True]:
                self.ax.grid(color=self.cget("foreground"))
            else:
                self.ax.grid(False)
        elif key in ["width", "height"]:
            if isinstance(self.canvas, FigureCanvasTkAggRedraw):
                self.canvas.get_tk_widget()[key] = value
            else:
                fig = self.ax.get_figure()
                if key == "width":
                    fig.set_figwidth(float(value) / fig.get_dpi())
                    self._configNoDraw(realwidth=value)
                else:
                    fig.set_figheight(float(value) / fig.get_dpi())
                    self._configNoDraw(realheight=value)
        elif key == "top_title":
            fontsize = self.cget("top_title_fontsize")
            if fontsize is None:
                self.ax.set_title(value)
            else:
                self.ax.set_title(value, fontsize=fontsize)
        elif key == "top_title_fontsize":
            title = self.cget("top_title")
            if title is not None:
                self.ax.set_title(title, fontsize=value)
        elif key in ["background", "bg"]:
            if hasattr(self.ax, 'set_facecolor'):
                # matplotlib >= 2.0
                self.ax.set_facecolor(value)
            else:
                self.ax.set_axis_bgcolor(value)
        elif key in ["foreground", "fg"]:
            matplotlib.rcParams["axes.edgecolor"] = self.cget("foreground")
            self.redrawlabels = 1
            if self.cget("grid") in ["yes", True]:
                self.ax.grid(color=value)
        elif key == "color_list":
            color_list = value.split()
            i = 0
            for d in self.data:
                if d["newsect"] is None or d["newsect"]:
                    i = i + 1
                if d["color"] is None:
                    color = i
                else:
                    color = d["color"]
                d["mpline"].set_color(color_list[color % len(color_list)])
        elif key == "decorations":
            if value:
                self.ax.set_axis_on()
            else:
                self.ax.set_axis_off()
        elif key == "use_symbols":
            self.plotsymbols()
        elif key == "use_labels":
            self.plotlabels()
        elif key in ["xlabel", "ylabel", "zlabel"]:
            if value is None:
                value = ""
            fontsize = self.cget(key + "_fontsize")
            if hasattr(self.ax, "set_" + key):
                func = getattr(self.ax, "set_" + key)
                if fontsize is None:
                    func(value)
                else:
                    func(value, fontsize=fontsize)
        elif key in ["xlabel_fontsize", "ylabel_fontsize", "zlabel_fontsize"]:
            label = self.cget(key[:6])
            if hasattr(self.ax, "set_" + key[:6]):
                func = getattr(self.ax, "set_" + key[:6])
                if value is None:
                    func(label)
                else:
                    func(label, fontsize=value)
        elif key in ["xticks", "yticks", "zticks"]:
            if value is None:
                if self.ax is self.ax3d:
                    axis = getattr(self.ax, "w_" + key[0] + "axis")
                    axis.set_major_locator(AutoLocator())
                elif key == "xticks":
                    self.ax.set_xscale('linear')
                else:
                    self.ax.set_yscale('linear')
            else:
                min = self.cget("min" + key[0])
                max = self.cget("max" + key[0])
                ticks = [
                    min + ((max - min) * i) / float(value - 1)
                    for i in range(value)
                ]
                if self.ax is self.ax3d:
                    axis = getattr(self.ax, "w_" + key[0] + "axis")
                    axis.set_major_locator(FixedLocator(ticks))
                elif key == "xticks":
                    self.ax.set_xticks(ticks)
                elif key == "yticks":
                    self.ax.set_yticks(ticks)

    def _delAllData(self):
        for d in self.data:
            if "mpline" in d:
                self.ax.lines.remove(d["mpline"])
        self.data = []

        # set type for next data
        try:
            zcolumn = self.cget(self.cget("type") + "_z")
        except Tkinter.TclError:  #in regression test
            return
        oldax = self.ax
        if zcolumn is None or Axes3D is None:
            if zcolumn is not None:
                self._configNoDraw({self.cget("type") + "_z": None})
                print("\nmatplotlib 0.98.x does not support 3D plots.")
                print("Plotting only the first two coordinates.")
            if self.ax is self.ax3d:
                # restore zoom mode
                new_zoom_mode = self.zoom_mode
                self.ax = self.ax2d
        else:
            if self.ax3d is None:
                self.ax3d = Axes3D(self.ax.get_figure())
                try:
                    self.ax3d.set_autoscale_on(0)
                except TypeError:  #Matplotlib 1.1 bug
                    self.ax2d.set_autoscale_on(0)
                    self.ax3d.set_autoscalez_on(0)
            if self.ax is self.ax2d:
                # remember zoom mode and disable zoom
                if isinstance(self.canvas, FigureCanvasTkAggRedraw):
                    self.zoom_mode = self.toolbar.mode
                    new_zoom_mode = ''
                self.ax = self.ax3d
        if self.ax is not oldax:
            if (isinstance(self.canvas, FigureCanvasTkAggRedraw)
                    and new_zoom_mode != self.toolbar.mode):
                if "rect" in new_zoom_mode:
                    self.toolbar.zoom()
                elif "pan" in new_zoom_mode:
                    self.toolbar.pan()
                elif "rect" in self.toolbar.mode:
                    self.toolbar.zoom()
                elif "pan" in self.toolbar.mode:
                    self.toolbar.pan()
            #copy settings from 3d to 2d or vice versa
            for key in ("grid", "decorations", "xlabel", "ylabel", "zlabel",
                        "xticks", "yticks", "zticks", "minx", "maxx", "miny",
                        "maxy", "minz", "maxz", "azimuth", "elevation",
                        "top_title", "background"):
                self.__optionCallback(key, self.cget(key), [])

    def _delData(self, index):
        if "mpline" in data[index]:
            self.ax.lines.remove(data[index]["mpline"])
        del self.data[index]

    def clear(self):
        if len(self.ax.get_figure().axes) > 0:
            self.ax.get_figure().delaxes(self.ax.get_figure().axes[0])

    def draw(self):
        if self.redrawlabels:
            self.plotlabels()
        if len(self.ax.get_figure().axes) == 0:
            self.ax.get_figure().add_axes(self.ax)
        if isinstance(self.canvas, FigureCanvasTkAggRedraw):
            FigureCanvasTkAgg.draw(self.canvas)
        else:
            self.canvas.draw()

    def plot(self):
        color_list = self.cget("color_list").split()

        # data
        line_width = self.cget("line_width")
        dashes = list(map(float, self.cget("dashes")))
        i = -1
        for d in self.data:
            if d["newsect"] is None or d["newsect"]:
                i = i + 1
            curve = "curve:%d" % (i, )
            if self.ax is self.ax2d:
                v = [d["x"], d["y"]]
            else:
                v = [d["x"], d["y"], d["z"]]
            if d["color"] is None:
                color = i
            else:
                color = d["color"]
            kw = {'color': color_list[color % len(color_list)]}
            if len(v[0]) == 1:
                # If we only have one point we draw a small circle or a pixel
                if self.cget("type") == "solution":
                    marker = 'o'
                else:
                    marker = ','
                v.append(marker)
                #tags=("data_point:%d"%(0,),curve,"data")
            else:
                stable = d["stable"]
                #tags=(curve,"data")
                kw['lw'] = line_width
                if stable is not None and not stable:
                    kw.update({'ls': '--', 'dashes': dashes})
            if self.ax is self.ax2d:
                self.ax.plot(*v, **kw)
            else:
                self.ax.plot3D(*v, **kw)
            d["mpline"] = self.ax.lines[-1]
        if len(self.ax.get_figure().axes) == 0:
            self.ax.get_figure().add_axes(self.ax)

    def __setitem__(self, key, value):
        self.configure(**{key: value})

    def __getitem__(self, key):
        return self.cget(key)