예제 #1
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)
예제 #2
0

if __name__ == '__main__':
    ncf = netcdf_file('KTLX_20100510_22Z.nc')
    data = ncf.variables['Reflectivity']
    lats = ncf.variables['lat']
    lons = ncf.variables['lon']
    stormcells = storm_loader('polygons.shp')

    win = tk.Tk()

    fig = Figure()
    canvas = FigureCanvas(fig, master=win)
    ax = fig.add_subplot(1, 1, 1)
    raddisp = RadarDisplay(ax, lats, lons)
    raddisp.update_display(data[0])
    fig.colorbar(raddisp.im)
    polycolls = Stormcells(ax, stormcells)
    linecoll = Tracks(ax)

    # Turn on the first frame's polygons
    polycolls.toggle_polygons(0, True)
    ax.autoscale(True)

    ctrl_sys = ControlSys(fig, raddisp, data, polycolls, linecoll, stormcells)

    win.wm_title("Embedding with Tk")
    canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
    canvas.show()
    tk.mainloop()
예제 #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()
예제 #4
0
if __name__ == '__main__':
    ncf = netcdf_file('KTLX_20100510_22Z.nc')
    data = ncf.variables['Reflectivity']
    lats = ncf.variables['lat']
    lons = ncf.variables['lon']
    stormcells = storm_loader('polygons.shp')

    win = tk.Tk()

    fig = Figure()
    canvas = FigureCanvas(fig, master=win)
    ax = fig.add_subplot(1, 1, 1)
    raddisp = RadarDisplay(ax, lats, lons)
    raddisp.update_display(data[0])
    fig.colorbar(raddisp.im)
    polycolls = Stormcells(ax, stormcells)
    linecoll = Tracks(ax)

    # Turn on the first frame's polygons
    polycolls.toggle_polygons(0, True)
    ax.autoscale(True)

    ctrl_sys = ControlSys(fig, raddisp, data, polycolls, linecoll, stormcells)

    win.wm_title("Embedding with Tk")
    canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
    canvas.show()
    tk.mainloop()