예제 #1
0
class GraphFrame(AppWidget):
    def __init__(self, parent, controller, config, dbvar=None, wd=14, ht=7.5):
        self.widget_name = "graphframe"

        self.lines_list = []
        self.bars_list = []
        self.event_polygon_list = []
        self.prime_graph_pack = None
        self.secondary_graph_pack = None

        super().__init__(parent, controller, config, dbvar=None)

        self.my_figure = Figure(figsize=(wd, ht), dpi=85)
        self.my_legend = self.my_figure.legend()

        self.axis_prime = self.my_figure.add_subplot(1, 1, 1)
        #        self.axis_prime.set_title("No Query Selected")

        self.axis_secondary = self.my_figure.add_subplot(
            111, sharex=self.axis_prime, frameon=False)
        self.axis_secondary.xaxis.set_visible(False)
        self.axis_secondary.yaxis.set_label_position("right")
        self.axis_secondary.yaxis.tick_right()

        self.canvas = FigureCanvas(self.my_figure, self)
        self.canvas.draw()
        #
        #        self.canvas.manager.toolbar.add_tool('zoom', 'foo')

        #        self.toolbar = NavigationToolbar2TkAgg(self.canvas, self)
        #        self.toolbar.update()
        self.canvas._tkcanvas.pack()

    def update_annot(self, hover_obj, ind, kind="line"):
        text = "DEFAULT"
        if kind == "line":
            x, y = hover_obj.get_data()
            coords = (x[ind["ind"][0]], y[ind["ind"][0]])
            yshort = '%.2f' % coords[1]
            self.annot.xy = coords
            text = "{}\n{},{}".format(hover_obj.get_label(), coords[0], yshort)
            self.annot.set_text(text)
            self.annot.get_bbox_patch().set_alpha(0.4)
        elif kind == "bar":
            coords = hover_obj.get_xy()
            ynew = coords[1] + hover_obj.get_height()
            self.annot.xy = coords[0] + hover_obj.get_width() / 2, ynew
            text = "{}-{}".format(
                self.axis_prime.get_xticklabels()[ind].get_text(), ynew)
            self.annot.set_text(text)
            self.annot.get_bbox_patch().set_alpha(0.4)

    def hover(self, event):
        vis = self.annot.get_visible()
        if str(event.inaxes) == str(self.axis_prime):
            for line2d in self.lines_list:
                cont, ind = line2d.contains(event)
                if cont:
                    self.update_annot(line2d, ind)
                    self.annot.set_visible(True)
                    self.canvas.draw_idle()
                    return
            for index, rec in enumerate(self.bars_list):
                cont, ind = rec.contains(event)
                if cont:
                    self.update_annot(rec, index, kind="bar")
                    self.annot.set_visible(True)
                    self.canvas.draw_idle()
                    return

        if vis:
            self.annot.set_visible(False)
            self.canvas.draw_idle()

    def update_graph(self, gr_pk):
        #        PRETTYPRINT(gr_pk)
        """
        {'axis': 'left',
         'breakdown_colors': ['firebrick',
                              'dodgerblue',
                              'seagreen',
                              'darkorchid',
                              'gray',
                              'yellow',
                              'salmon',
                              'deeppink'],
         'color': '#a38bb6',
         'end': datetime.date(2018, 4, 1),
         'event_dates': [('04/29 Sale', '20180429', '20180429'),
                         ('05/01-05/06 Event', '20180501', '20180506'),
                         ('05/01-05/06 Event', '20180517', '20180520')],
         'force_y': (True, 0, 4),
         'gtype': 'date_series',
         'line_labels': ['PC', '모바일', 'm_PC', 'm_모바일'],
         'linestyles': '-',
         'met': 'Order Size',
         'start': datetime.date(2018, 3, 18),
         'str_x': 'Date (Average of 7-Day Periods)',
         'str_y': 'Order Size (Average)',
         'title': 'Average of Order Size (Exclude Cancelled Items) By Gen. Platform',
         'x_data': [datetime.date(2018, 3, 18),
                    datetime.date(2018, 3, 25),
                    datetime.date(2018, 4, 1)],
         'y_data': [[3.371877804372405, 3.330132851297275, 3.3963963963963963],
                    [2.5645786328057234, 2.5824528794692228, 2.647798742138365],
                    [3.6697965620085644, 3.371877804372405, 3.433628318584071],
                    [2.5361031401007033, 2.5645786328057234, 2.6683168316831685]]}
        """
        #       CLEAN UP AND RESET
        self.log("Update graph call.")

        self.clear_graph()

        # DETERMINE TARGET AXIS
        if gr_pk["axis"] == "left":
            target_axis = self.axis_prime

        elif gr_pk["axis"] == "right":
            target_axis = self.axis_secondary

        self.axis_prime.xaxis.set_visible(True)
        self.axis_prime.yaxis.set_visible(True)
        self.axis_prime.grid(b=True, which="major")

        self.prime_graph_pack = gr_pk
        other_pack = self.secondary_graph_pack
        self.log("target_axis: {} => self.axis_prime".format(gr_pk["axis"]))

        #       TITLING
        if not other_pack:
            target_axis.set_title(gr_pk["title"])
            target_axis.xaxis.set_label_text(gr_pk["str_x"])
        elif other_pack:
            new_title = "{} vs. {}".format(self.prime_graph_pack["title"],
                                           self.secondary_graph_pack["title"])
            target_axis.set_title(new_title)

        target_axis.yaxis.set_label_text(gr_pk["str_y"])

        #
        ##       GRAPH PRP
        gr_pk_colors = [gr_pk["color"]] + gr_pk["breakdown_colors"]
        #        PRETTYPRINT(gr_pk_colors)
        start = gr_pk["start"]
        end = gr_pk["end"]
        color_c = 0
        if gr_pk["gtype"] == "date_series":
            for x in range(0, len(gr_pk["y_data"])):
                try:
                    gr_pk_colors[x]
                except IndexError:
                    color_to_use = gr_pk_colors[x - 10]
                else:
                    color_to_use = gr_pk_colors[x]

                if "m_" in gr_pk["line_labels"][x]:
                    linewidth = 0.75
                else:
                    linewidth = 1.45
                self.lines_list.append(
                    target_axis.plot_date(gr_pk["x_data"],
                                          gr_pk["y_data"][x],
                                          color=color_to_use,
                                          ls=gr_pk["linestyles"],
                                          lw=linewidth,
                                          label=gr_pk["line_labels"][x])[0])
                #                print(self.line)
                color_c += 1

            target_axis.set_xlim(gr_pk["x_data"][0], gr_pk["x_data"][-1])

        elif gr_pk["gtype"] == "string-bar" or gr_pk["gtype"] == "bar":
            self.bars_list = target_axis.bar(
                gr_pk["x_data"],
                gr_pk["y_data"][0],
                color=gr_pk_colors[color_c]).patches
            color_c += 1
        elif gr_pk["gtype"] == "pie":
            self.axis_prime.pie(gr_pk["y_data"][0], labels=gr_pk["x_data"])
#
#       POST PLOTTING FORMATTING
        if not gr_pk["gtype"] == "pie":
            # Y-AXIS FORMATTING
            if gr_pk["force_y"][0]:
                target_axis.set_ylim(bottom=gr_pk["force_y"][1],
                                     top=gr_pk["force_y"][2])
            elif not gr_pk["force_y"][0]:
                if target_axis.get_ylim()[1] >= 1000:
                    target_axis.get_yaxis().set_major_formatter(
                        ticker.FuncFormatter(lambda x, p: format(int(x), ',')))
                if target_axis.get_ylim()[0] <= 0:
                    target_axis.set_ylim(bottom=0)

            for tick in target_axis.get_xticklabels():
                tick.set_fontsize(8)
                tick.set_rotation(30)

            # EVENT HIGHLIGHTS
            if gr_pk["str_x"] == "Date":
                #                event_colors = self.get_cfg_val("event_colors").split("-")
                invDisToAxFrac = self.axis_prime.transAxes.inverted()
                axis_left_lim = matplotlib.dates.num2date(
                    self.axis_prime.get_xlim()[0]).date()
                for e_index, event_tuple in enumerate(gr_pk["event_dates"]):
                    name_str = event_tuple[0]
                    start_str = event_tuple[1]
                    end_str = event_tuple[2]

                    self.log("{} -> {}".format(start_str, end_str))
                    start_date = datetime.date(int(start_str[0:4]),
                                               int(start_str[4:6]),
                                               int(start_str[6:8]))
                    end_date = datetime.date(int(end_str[0:4]),
                                             int(end_str[4:6]),
                                             int(end_str[6:8]))
                    axis_left_lim = matplotlib.dates.num2date(
                        self.axis_prime.get_xlim()[0]).date()
                    #                    if start_date < axis_left_lim:
                    #                        start_date = axis_left_lim
                    event_polygon = self.axis_prime.axvspan(start_date,
                                                            end_date,
                                                            alpha=0.08,
                                                            color="red",
                                                            lw=7,
                                                            linestyle=(115,
                                                                       (20,
                                                                        2)))
                    self.event_polygon_list.append(event_polygon)

                    left_top = event_polygon.get_verts()[1]
                    right_top = event_polygon.get_verts()[2]
                    # from display to axis decimal-fraction
                    ax_left_top = invDisToAxFrac.transform(left_top)
                    ax_right_top = invDisToAxFrac.transform(right_top)

                    final_left_top = list(ax_left_top)
                    if ax_left_top[0] <= 0:
                        if ax_right_top[0] < 0:
                            continue
                        else:
                            final_left_top[0] = 0
                    elif ax_left_top[0] >= 1:
                        self.log("Too far in future, skipping.")
                        continue
                    self.log("LEFT: {} -> {} -> {}".format(
                        left_top, ax_left_top, final_left_top))
                    self.log("RIGHT: {} -> {}".format(right_top, ax_right_top))
                    stagger_y = 0.95 - (0.10 * e_index)
                    self.axis_prime.text(final_left_top[0] + 0.01,
                                         stagger_y,
                                         s=name_str,
                                         horizontalalignment="left",
                                         transform=self.axis_prime.transAxes,
                                         fontproperties=propF)
#
#    #       GENERAL FORMATTING

        self.my_legend = self.axis_prime.legend(
            ncol=2,
            fontsize="x-small",
            #                borderaxespad=-0.1,
            markerscale=0.6,
            framealpha=0.85,
            prop=propF)
        #
        self.canvas.draw()
        #
        self.annot = self.axis_prime.annotate("",
                                              xy=(0, 0),
                                              xytext=(-20, 20),
                                              textcoords="offset points",
                                              bbox=dict(boxstyle="round",
                                                        fc="w"),
                                              arrowprops=dict(arrowstyle="->"),
                                              fontproperties=propF)
        self.annot.set_visible(False)
        self.canvas.mpl_connect("motion_notify_event", self.hover)

        self.log("Completed Graphing.")

    def clear_graph(self, axis="both"):
        try:
            self.my_legend.remove()
        except BaseException:
            self.bug(
                "My legend doesn't exist yet. Likely first time calling _update_plot()"
            )

        self.lines_list = []
        self.bars_list = []
        self.event_polygon_list = []

        if axis == "both":
            self.axis_prime.cla()
            self.axis_prime.yaxis.set_visible(False)
            self.axis_prime.grid(b=False)

            self.axis_secondary.cla()

            self.axis_secondary.yaxis.set_visible(False)
예제 #2
0
class PageThree(tk.Frame):
    """Frame showing Data View and chop capabilities
    """

    def __init__(self, parent, controller, **kwargs):
        tk.Frame.__init__(self, parent) # call class parent

        """ Initialize data members """
        self.DA = DA
        self.isSafeToUpdate = False
        self.numViews = 2
        self.deactList = list()

        self.DVconfig = controller.DVconfig

        """ Create label for frame """
        #label = tk.Label(self, text="Data View", font=LARGE_FONT)
        #label.pack(pady=10,padx=10)

        """ Create button to go back to other frame """
        #button1 = ttk.Button(self, text="Back to Home",
        #                    command=lambda: controller.show_frame(StartPage))
        #button1.pack()

        """ Add menu item to load data """
        filemenu = controller.filemenu
        filemenu.insert_command(index=1,label="Load", command=self.load)

        self.addMainFigure()    # Add main figure area to frame
        self.addDataWindow()    # Add widgets for setting data window
        self.addDataView()      # Add widgets for setting data view
        self.addChop()          # Add chop button
        self.addStat()          # Add stat button

    def addDeactivateList(self, listLike) :
        """ Keep a list of deactivate-able widgets """
        if isinstance(listLike, list) or isinstance(listLike, tuple) :
            for item in listLike :
                self.deactList.append(item)
        else :
            self.deactList.append(listLike)

    def deactivateWidgets(self) :
        for widget in self.deactList :
            widget.configure(state='disabled')

    def activateWidgets(self) :
        if not self.DA.isLoaded :
            return DataNotLoaded()
        for widget in self.deactList :
            widget.configure(state='normal')

    def addDataView(self) :
        """ Add widgets that control the view """
        self.viewList = list(('No Data','No Data'))

        """ Add View Widget Sub-Frames """
        self.dataViewSubFrameList = list()              # list of "subframes"
        for frameNum in range(0,self.numViews) :
            subFrame = viewWidgetGroupFrame(self, label="Data View "+str(frameNum))
            subFrame.setEventHandler(self.viewChangeTrace)
            subFrame.pack()
            self.dataViewSubFrameList.append(subFrame)

        """ Data View Index Selection """
        self.altIdxSel = tk.StringVar(self)
        self.altIdxSel.set("No data") # default value
        """
        self.altIdxSelW = tk.OptionMenu(self, self.altIdxSel, "No Data" )
        self.altIdxSelW.configure(state="disabled")
        self.altIdxSelW.pack()
        self.altIdxSel.trace('w', self.viewChangeTrace) # set up event
        self.addDeactivateList(self.altIdxSelW)
        """

    def addDataWindow(self) :
        """ Data Window Size Widget """
        self.dataWindowSizeWidgetLabel = tk.Label(self, text='View Size')
        self.dataWindowSizeWidgetLabel.pack()
        self.dataWindowSizeWidget = tk.Scale(self, from_=1, to=10, resolution=1,
                orient="horizontal")
        self.dataWindowSizeWidget.bind("<ButtonRelease-1>", self.updateEvent)
        self.dataWindowSizeWidget.bind("<Button1-Motion>", self.updateEvent)
        self.dataWindowSizeWidget.pack(fill=tk.X,expand=1)
        """ Data Window Start Widget """
        self.dataWindowStartWidgetLabel = tk.Label(self, text='View Start')
        self.dataWindowStartWidgetLabel.pack()
        self.dataWindowStartWidget = tk.Scale(self, from_=0, to=10, resolution=1,
                orient="horizontal")
        self.dataWindowStartWidget.bind("<ButtonRelease-1>", self.updateEvent)
        self.dataWindowStartWidget.bind("<Button1-Motion>", self.updateEvent)
        self.dataWindowStartWidget.pack(fill=tk.X,expand=1)

    def addMainFigure(self) :
        """ Add main figure area """
        self.fig = plt.figure(figsize=(5,4), dpi=100)
        self.ax = self.fig.add_subplot(111)
        self.ax.set_title('No data')
        self.fig.canvas.draw()

        self.canvas = FigureCanvas(self.fig, self)
        """ Set up callback from canvas draw events, i.e. pan/zoom """
        #self.cid1 = self.fig.canvas.mpl_connect('draw_event', self.updateFromCavas)
        #self.cid1 = self.fig.canvas.mpl_connect('button_release_event', self.updateFromCavas)
        #TODO animation
        self.canvas.draw()
        self.canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)

        self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

    def addChop(self) :
        chopBW = tk.Button(self, text="Chop", command=self.doChop)
        chopBW.pack()
        self.chopButtonW = chopBW

    def addStat(self) :
        statBW = tk.Button(self, text="Stats", command=self.doStat)
        statBW.pack()
        self.statButtonW = statBW

    def postLoad(self) :
        """ Things to run after loading a new DataAnalyser object.  """
        debug("postLoad: get current view from DA...")
        viewList = self.DA.getView()                    # retrieve the default view after load
        debug("postLoad: get labels from DA...")
        self.updateLabels()                             # get new data types from data loaded
        self.setAltIndex('index')
        self.setView(viewList)                          # configure GUI to reflect new data
        self.isSafeToUpdate = True
        debug("postLoad: isSafeToUpdate:"+str(self.isSafeToUpdate))
        """ now, set the window """
        #TODO use data values instead of index values
        limitDict=self.DA.getIndexLimits()
        maxSize, minVal = ( limitDict['max'] , limitDict['min'] )
        #print( "DEBUG: postLoad: maxSize: "+str(maxSize) )
        #print( "DEBUG: postLoad: minValue: "+str(minVal) )
        self.setWindow( minVal=minVal, start=0,
                        maxSize=maxSize, size=int(maxSize/2)) # reset the GUI window
        self.updateEvent(None)      # update GUI

    def setWindow(self, minVal=0, start=0, maxSize=10, size=10) :
        """ set the GUI values that correspond to the window """
        debug("DEBUG: setWindow: %s, start: %s, maxSize: %s, size: %s"
                ,minVal, start, maxSize, size )
        self.dataWindowSizeWidget.config(from_=1, to=maxSize-start+1)
        self.dataWindowSizeWidget.set(size)
        self.dataWindowStartWidget.config(from_=minVal, to=maxSize-size+1)
        self.dataWindowStartWidget.set(start)

    def load(self, *args, **kwargs) :
        """ catch all load method
        Currently, the only implemented mode is CSV file data.
        """
        self.isSafeToUpdate = False
        name = filedialog.askopenfilename()
        self.loadFileData(path=name, *args, **kwargs)

    def loadFileData(self, path=None, *args, **kwargs) :
        """ Show a dialog to select a file and load it.  """
        if path is None:
            raise TypeError("loadFileData: path option is required")
        print("Got filename:" +path)
        loadData(path, *args, **kwargs)
        self.postLoad()

    def updateLabels(self) :
        """ Update labels from the DataAnalyser object
        Call whenever DA is loaded/changed.
        """
        #print("DEBUG: updateLabels: isSafeToUpdate:", self.isSafeToUpdate)
        if not self.DA.isLoaded :
            return DataNotLoaded()
        newLabels = DA.getLabels()
        #debug("DEBUG: got label list from DA: "+str(newLabels))
        for viewSubFrame in self.dataViewSubFrameList:
            viewSubFrame.setOptionsList(newLabels)

        """ re-enable widgets """
        self.activateWidgets()

    def updateFromCavas(self, event) :
        """ Called when view is changed using figure canvas area. """
        """ Get the figure axis limits """
        figMinX, figMaxX = self.ax.get_xlim()
        debug('Got interval from MPL axis:'+str((figMinX,figMaxX)))
        """ Set the current window to match """
        #TODO

    def viewChangeTrace(self, *args):
        """View is changed, make proper updates downward."""
        debug("viewChange: isSafeToUpdate:"+str(self.isSafeToUpdate))
        if not self.isSafeToUpdate :
            #print("DEBUG: viewChangeTrace: not safe, returning")
            return
        """Do other updates"""
        self.updateEvent(None)

    def setView(self, viewList) :
        """ Set the GUI representation of the current data view
        Takes a "view" object and sets the GUI so that it matches.
        """
        self.isSafeToUpdate = False
        self.viewList = viewList
        for view,subFrame in zip(viewList,self.dataViewSubFrameList) :
            debug("DataViewApp: setView: "+str(view))
            subFrame.disable()
            subFrame.setView(view)
            subFrame.enable()

    def setAltIndex(self, newIdx):
        """ Set the GUI presentation of alt index """
        self.isSafeToUpdate = False
        self.altIdxSel.set(newIdx)

    def updateEvent(self, event):
        """ Change/Update data view when user requests a change.
        Call this whenever the user makes a change to view values.
        """
        debug("updateEvent: called, event:"+str(event))
        if not self.DA.isLoaded :
            return DataNotLoaded()
        DA = self.DA

        """ Set window from interface settings """
        newWinSize = self.dataWindowSizeWidget.get()
        newWinStart = self.dataWindowStartWidget.get()
        limitDict=self.DA.getIndexLimits()
        debug("DEBUG: updateEvent: got limits: "+str(limitDict))
        maxSize, minVal = ( limitDict['max'] , limitDict['min'] )
        self.setWindow( minVal=minVal, start=newWinStart,
                        maxSize=maxSize, size=newWinSize )

        """ Set views from interface settings """
        newViewList = list()
        for subFrame in self.dataViewSubFrameList :
            newView = subFrame.getView()
            debug("updateEvent: newView: "+str(newView))
            if newView is not None :
                """If view frame returns None, don't add to list."""
                newViewList.append(newView)

        """ set index """
        try :
            pass
            #DA.setAltIndexColumn(self.altIdxSel.get())
            #TODO
        except Exception as e:
            warn('updateEvent: Failed to set altnernate index, ignoring selection')
            print(e)
        else :
            """ just leave it set to index """
            pass

        DA.setView( viewList=newViewList, windowStart=newWinStart, windowSize=newWinSize,
                windowType='index' )

        """Redraw the plot"""
        dfList = self.DA.getViewData()
        #print("DEBUG: updateEvent: got updated data:", df.colums.tolist())
        ax = self.ax
        ax.clear()
        xlabelList, ylabelList = list(), list()
        for df in dfList :
            """draw all df data as x,y data"""
            (xlabel, ylabel) = df.columns.tolist()
            ax.plot(df[xlabel].values, df[ylabel].values, 'o-')
            """store labels"""
            xlabelList.append(xlabel)
            ylabelList.append(ylabel)

        """Set labels"""
        newXlabel, newYlabel = str(), str()
        xlabelOverride = self.DVconfig.get('xlabel')
        ylabelOverride = self.DVconfig.get('ylabel')
        """Remember, configer doesn't hold native objects"""
        debug("Plotting: xlabelOverride: %s" % xlabelOverride)
        debug("Plotting: xlabelOverride eq None: %s" % (xlabelOverride == None))
        if (xlabelOverride == None) or (ylabelOverride == None) :
            """Write the labels for all data"""
            debug("Plotting: Label overrides OFF")
            sep = "\n"
            newXlabel = sep.join( xlabelList )
            newYlabel = sep.join( ylabelList )
            debug("new xlabel: %s" % newXlabel)
        else :
            """the labels"""
            debug("Plotting: Label overrides ON")
            newXlabel = xlabelOverride
            newYlabel = ylabelOverride
        ax.set_xlabel(newXlabel)
        ax.set_ylabel(newYlabel)
        self.fig.canvas.draw()

        """ Show Statistics """
        #self.showStats()

    def showStats(self):
        """ Get and report statsistics for the current view """
        quantiles = self.DVconfig.get('statQuantiles')
        statsList = self.DA.getStats( quantiles )
        dirpath = self.DVconfig.get('saveCDFDir')
        prefix = self.DVconfig.get('statFilePrefix')
        for statDF  in statsList :
            fmt = self.DVconfig.get('statFileFmt')
            cols = ','.join(map(str,statDF.columns))
            start,end = self.DA.getStartEnd()
            filename = prefix + "_{},{}-{}".format(cols,start,end) + fmt
            pathname = os.path.join( dirpath , filename )
            statDF.to_csv(pathname)
        for stats in statsList:
            print("Data View Statistics:")
            print(stats)

    def doChop(self) :
        self.saveViewPlot()
        directory=pathlib.PurePath(os.path.curdir)
        chopConf = self.DVconfig.get('chopOpts')
        debug('chopConf:'+str(chopConf))
        debug('dict(chopConf):'+str(dict(chopConf)))
        self.DA.chop(dirpath=directory, **dict(chopConf))

    def saveViewPlot(self) :
        fig = self.fig                                              # Get figure
        start,end = self.DA.getStartEnd()                           # Get view range
        dirpath = self.DVconfig.get('savePlotDir')
        prefix = self.DVconfig.get('savePlotPrefix')
        viewList = self.DA.getView()
        viewStr = ','.join(map(lambda x: ','.join(map(str,x)) if isinstance(x,tuple) else str(x), viewList))
        filename = prefix + "_{vl},{start}-{end}".format(
                start=start,end=end, vl=viewStr
                ) + ".pdf"
        pathname = os.path.join( dirpath , filename )
        fig.savefig(pathname)                                       # Save plot

    def doStat(self) :
        """ Do actions for "stats" button
        """
        # First, show stats on STDOUT
        self.showStats()
        # Then, save the current view plot
        self.saveViewPlot()
        # Next, make a CDF plot for all the visible data
        num_bins = self.DVconfig.get('saveCDFbins')
        cdfInfoLst = self.DA.getCDFall(num_bins=num_bins)                        # get CDF info from DA
        prefix     = self.DVconfig.get('saveCDFprefix')
        dirpath    = self.DVconfig.get('saveCDFDir')
        for cdfInfoT in cdfInfoLst :
            i = cdfInfoLst.index(cdfInfoT)
            label, cdf, counts, bin_edges = cdfInfoT
            start,end = self.DA.getStartEnd()
            filename = prefix +"_{},{}-{},{}.pdf".format(label,start,end,i)
            pathname = os.path.join( dirpath , filename )
            fig = plt.figure()                                  # mk new fig
            plt.plot(bin_edges[1:], cdf/cdf[-1])
            plt.xlabel("{} values".format(label))
            plt.ylabel("Normalized Cumulative Sum (CDF)".format())
            fig.savefig(pathname)
예제 #3
0
class CanvasForGraphs:
    def __init__(self,
                 root,
                 frame,
                 master_class,
                 figure,
                 axis_id=None,
                 poppedout_id=None,
                 direction="x"):

        # Save the variables
        self.root = root
        self.frame = frame
        self.master_class = master_class
        self.figure = figure
        self.axis_id = axis_id
        self.poppedout_id = poppedout_id
        self.direction = direction

        # Create the frame, canvas and toolbar
        self.initiate_frameGraph()

        # Make the canvas available to the master class so we can draw_idle() it
        if poppedout_id == None:
            self.master_class.Canvas[axis_id] = self.Canvas
        if poppedout_id != None: self.root.canvasPoppedOut.append(self.Canvas)

    #----------- Frame ----------
    def initiate_frameGraph(self):

        # Configure frame that holds the canvas
        tk.Grid.rowconfigure(self.frame, 0, weight=1)
        tk.Grid.columnconfigure(self.frame, 0, weight=1)

        # Create frame for graph elements
        self.frame_canvas = ttk.Frame(self.frame)
        self.frame_canvas.grid(row=0,
                               column=0,
                               padx=(0, 0),
                               pady=(0, 0),
                               stick='NSEW')

        # Configure the frame that holds the figure and toolbar
        if self.direction == "x":
            tk.Grid.rowconfigure(self.frame_canvas, 0, weight=1)
            tk.Grid.rowconfigure(self.frame_canvas, 1, weight=0)
            tk.Grid.columnconfigure(self.frame_canvas, 0, weight=1)
        if self.direction == "y":
            tk.Grid.columnconfigure(self.frame_canvas, 0, weight=0)
            tk.Grid.columnconfigure(self.frame_canvas, 1, weight=1)
            tk.Grid.rowconfigure(self.frame_canvas, 0, weight=1)

        # Add the canvas and the toolbar
        self.initiate_canvas()
        self.initiate_toolbar()

    #----------- Canvas -----------
    def initiate_canvas(self):

        # Add the figure to a Canvas
        self.Canvas = FigureCanvas(self.figure, self.frame_canvas)
        self.Canvas.get_tk_widget().configure(background=self.root.color['bg'])
        self.figure.patch.set_facecolor(self.root.color['bg'])
        self.Canvas.draw()
        self.widget = self.Canvas.get_tk_widget()
        if self.direction == "x":
            self.widget.grid(row=0, column=0, stick='NSEW')
        if self.direction == "y":
            self.widget.grid(row=0, column=1, stick='NSEW')

    #----------- Toolbar -----------
    def initiate_toolbar(self):

        # Add a toolbar to the canvas
        self.toolbar = CustomToolbar(self.root, self.Canvas, self.frame_canvas,
                                     self.master_class, self.axis_id,
                                     self.poppedout_id, self.direction)
        self.toolbar.config(background=self.root.color['bg'])
        self.toolbar.update()