Matplotlib绘制过多的刻度标签,错误地绘制数据

时间:2020-07-08 12:48:29

标签: python matplotlib tkinter

因此,我正在构建一个tkinter GUI程序,其中一个页面上具有matplotlib图。用户可以从各种弹出窗口中添加,删除和修改图形上的轨迹。

到目前为止,我一直在使用draw()对象上的FigureCanvasTkAgg方法来更改图形。我在其他几篇文章中也读到过,这会重绘 entire 图,并使渲染非常缓慢。另外,在我的特定情况下,它在轴上绘制了一个 lot 刻度标签,似乎在源中的每个点上都绘制了一个刻度标签,因此,除了花很长时间之外,它还使该图绝对不可读。它还不能正确绘制数据。

我偶然发现一些帖子建议不要使用draw方法,因为它会重新绘制整个图形,但这并不能真正解释为什么绘制了如此多的刻度标签,或者为什么未按预期绘制数据。我已经研究过使用动画,但是我不确定这是我所需要的,因为图形不必仅在用户更改时不断更新。

我正在使用Python 3.7.2和matplotlib 3.1.1。我正在绘制的数据是光谱数据,只有大约4000个点。我还用很小的数据集(10-15点)对其进行了测试,但这似乎没有发生。我也尝试过使用axis.locator_params(nbins=10)设置刻度标签,但是并不能阻止所有这些标签的绘制。

任何想法都在这里发生了什么,如何预防呢?这是它产生的图形以及代码的相关部分。对不起,如果我什么都没有。我是SO的新手,但是我还是一个相对缺乏经验的程序员。

进攻图: enter image description here

class App(tk.Tk): ###The controller of all pages, & control of operations
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        self.dfs = {}  #contains dataframes loaded from csv/made by the user
        self.spectra = {} #contains spectrum objects
        self.plots = {} #contains Figure objects. Each figure can have exactly one axis
        
        for F in (HomePage, SpectraPage, GraphPage, MakeSpectrumPage):
            frame = F(container, self)
            self.frames[F] = frame
            
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(HomePage)

    def show_frame(self, cont):
        self.frames[cont].tkraise()

    def load(self, filename):
        df = pd.read_csv(filename, header=None)
        if any(df.iloc[0].apply(lambda x: isinstance(x, str))):
            df = df[1:].reset_index(drop=True).rename(columns=df.iloc[0])
        else:
            names=[]
            for i in range(len(df.columns)):
                names.append("w%i" %i)
            df.columns = names
        self.dfs[filename] = df
        self.frames[MakeSpectrumPage].makeFileList()
            
    def get_dfs(self):
        return self.dfs

    def get_spectra(self):
        return self.spectra

    def get_plots(self):
        return self.plots

    def make_spectrum(self, name, df, x, y):
        spectrum = Spectrum(name, df, x, y)
        self.spectra[name] = spectrum
        self.frames[SpectraPage].insertItems()

    def make_plot(self, name):
        fig = Figure(dpi=100)
        fig.suptitle(name)
        axis = fig.add_subplot(111, xlim=(4000, 500), ylim=(0,1))
        axis.locator_params(nbins=10)
        self.plots[name] = fig
        
    def graph(self, axis, spectrum, **kwargs): #plot spectrum obj
        axis.plot(spectrum.xdata, spectrum.ydata, label=spectrum.name, **kwargs)
class GraphPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller=controller
        
        self.grid_columnconfigure(0,weight=1)
        
        self.controller.make_plot('Plot 1')
        self.showFigure(self.controller.get_plots()['Plot 1'])
        self.makeGraphTray()

                
    def showFigure(self, fig):
        self.canvas = FigureCanvasTkAgg(fig, self)
        self.canvas.draw()
        self.canvas._tkcanvas.grid(row=1, column=1, rowspan=2, columnspan=2)
        self.makeToolbar()

    def makeToolbar(self):
        self.toolbar_frame = tk.Frame(self)
        self.toolbar_frame.grid(row=3,column=1, columnspan=2)
        
        self.toolbar = NavigationToolbar2Tk(self.canvas, self.toolbar_frame)
        self.toolbar.update()

    def makeGraphTray(self):
        #make container for graph/trace modification buttons
        self.graphTray = tk.Frame(self, width=50)
        self.graphTray.grid(row=1, column=3, sticky='nsew')

        addTraceButton = ttk.Button(self.graphTray, text="Add Trace", command=lambda:self.raisePopup(NewTracePopup))
        addTraceButton.grid(row=0, column=0, sticky='nsew')

    def raisePopup(self, Popup):
        popup = Popup(self)
class Spectrum: #Objects of this class are two-column structures.
    def __init__(self, name, sourcedf, x, y):
        self.xdata = sourcedf[x]
        self.ydata = sourcedf[y]
        self.df = pd.concat([self.xdata, self.ydata], axis=1)
        self.name = name
class ConditionalPopup(tk.Toplevel):
    #parent class of OK/Cancel popups where OK is disabled until all fields are filled
    def __init__(self, master, title, **kwargs):#@param **kwargs the Variables traced by the widgets in the popup

        if all(isinstance(kwarg, tk.Variable) for kwarg in kwargs.values()):
            super().__init__(master)
            self.__dict__.update(kwargs)
            self.master = master

            self.vars = kwargs #dictionary of kwargs
            
            self.wm_title(title)

            self.widgetFrame = tk.Frame(self)
            self.widgetFrame.grid(row=0, column=0)

            self.traceVars()
            self.makeWidgets(self.widgetFrame)
            self.placeWidgets()
            
        else: raise TypeError
       
    def traceVars(self):
        for var in self.vars.values():
            var.trace('w', self.activateOK)

    def activateOK(self, *args):
        if all(self.vars[key].get() for (key, value) in self.vars.items()):
            self.okButton.configure(state='normal')
        else:
            self.okButton.configure(state='disabled')

    def makeWidgets(self, frame):
        self.okButton = ttk.Button(self, text="OK", state='disabled', command=self.okPressed)
        self.cancelButton = ttk.Button(self, text="Cancel", command=self.destroy) 
        
    def placeWidgets(self):
        self.okButton.grid(row=1, column=0, padx=2.5, pady=10, sticky='e')
        self.cancelButton.grid(row=1, column=1, padx=2.5, pady=10, sticky='w')

    def okPressed(self, *args):
        self.destroy()
class NewTracePopup(ConditionalPopup):
    #a popup that enables adding a trace to a chosen plot
    def __init__(self, master):
        super().__init__(master, "Add trace to plot",
                         plotVar=tk.StringVar(),
                         spectrumVar=tk.StringVar(),
                         colorVar=tk.StringVar(),
                         linewidthVar=tk.StringVar())


    def activateOK(self, *args):
        if self.linewidthVar.get().isdecimal():
            super().activateOK(*args)

    def makeWidgets(self, frame):
        self.plotLabel = tk.Label(frame, text="Plot:")
        self.plotCombobox = ttk.Combobox(frame, state='readonly', values=list(self.master.controller.get_plots().keys()), textvariable=self.plotVar)

        self.spectrumLabel = tk.Label(frame, text="Spectrum:")
        self.spectrumCombobox = ttk.Combobox(frame, state='readonly', values=list(self.master.controller.get_spectra().keys()), textvariable=self.spectrumVar)

        self.cLabel = tk.Label(frame, text="Colour:")
        self.cCombobox = ttk.Combobox(frame, state='readonly', values=list(mcolors.BASE_COLORS)+list(mcolors.TABLEAU_COLORS), textvariable=self.colorVar)

        self.mLabel = tk.Label(frame, text="Line width:")
        self.mEntry = ttk.Entry(frame, textvariable=self.linewidthVar)

        super().makeWidgets(frame)
        
    def placeWidgets(self):
        self.plotLabel.grid(row=0, column=0, padx=10, pady=10, sticky='e')
        self.plotCombobox.grid(row=0, column=1, padx=10, pady=10, sticky='w')

        self.spectrumLabel.grid(row=1, column=0, padx=10, pady=10, sticky='e')
        self.spectrumCombobox.grid(row=1, column=1, padx=10, pady=10, sticky='w')

        self.cLabel.grid(row=2, column=0, padx=10, pady=10, sticky='e')
        self.cCombobox.grid(row=2, column=1, padx=10, pady=10, sticky='w')

        self.mLabel.grid(row=3, column=0, padx=10, pady=10, sticky='e')
        self.mEntry.grid(row=3, column=1, padx=10, pady=10, sticky='w')

        super().placeWidgets() 

    def okPressed(self, *args):
           self.master.controller.graph(self.master.controller.get_plots()[self.plotVar.get()].axes[0],
                                            self.master.controller.get_spectra()[self.spectrumVar.get()],
                                            color=self.colorVar.get(),
                                            linewidth=float(self.linewidthVar.get()))
            self.master.canvas.draw()
            super().okPressed()

0 个答案:

没有答案