7

I have posted a fair amount of code here and it's at the bottom of this post. The code opens a tkinter GUI with various buttons and fields etc. It also displays a graph at the very bottom using matplotlib. I understand that this isn't the best library to use but I have no idea how the others work with tkinter. So I would ideally like to stick with matplotlib for the time being.

For the chart I want each of the data points be a vertical lines from the [x, y] coordinate down to [x, 0]. The obvious answer is to use a bar chart with bar thinknesses of 1, I've tried this but the plotting speed is a lot slower than that of a scatter plot.

What I have been trying to figure out is whether it is possible to just use the scatter plot method used here with vertical lines draw to y=0. Is this possible?

Or should I scrap trying to use matplotlib and use pandas or PyQtGraph. If this is the case are there any tutorials that with show how this is done? I've tried to find some but have had no luck.

Any help would be much appreciated. I'm using pyzo package that uses python 3.3.

enter image description here

import numpy from decimal import * import tkinter as tk import numpy as np from tkinter import * from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.figure import Figure from tkinter import ttk import tkinter.scrolledtext as tkst import spectrum_plot_2 as specplot import sequencer as seq class Plot: def __init__(self, master, data): self.x = np.array(data.spectrum[0]) self.y = np.array(data.spectrum[1]) # Create a container self.frame = tk.Frame(master) self.fig = Figure() self.ax = self.fig.add_subplot(111) self.line = self.ax.plot(self.x, self.y, '|') self.canvas = FigureCanvasTkAgg(self.fig,master=master) # self.canvas.show() self.canvas.get_tk_widget().pack(side='top', fill='both', expand=1) self.frame.pack() def update(self, data): """Updates the plot with new data""" self.x = np.array(data.spectrum[0]) self.y = np.array(data.spectrum[1]) self.line[0].set_xdata(self.x) self.line[0].set_ydata(self.y) self.canvas.show() self.frame.pack() class Spectrum: """(Spectrum, String, Decimal, int) -> None Import a spectrum from a text file """ def __init__(self, file, precision = 4, charge_state = None, sensetivity = 50, name='Unknown'): self.precision = precision self.name = name self.file = file self.charge_state = charge_state self.spectrum = self.load_spec(file, precision) def load_spec(self, file, precision): """(Spectrum, String) -> list manipulate spectrum file and return a list of lists: list[0] = [mz] list[1] = [intensity] """ raw_spectrum = numpy.loadtxt(file) # assign the spectrum to a dictionary intensity = ['%.0f' % elem for elem in raw_spectrum[:,1]] mz = ['%.4f' % elem for elem in raw_spectrum[:,0]] spectrum = [mz, intensity] for i in spectrum: for j, elem in enumerate(i): i[j] = round(Decimal(elem), precision) j = 0 return [mz, intensity] class View(ttk.Frame): """Main GUI class""" def __init__(self, master = None): self.WIDTH = 450 self.HEIGHT = 500 self.spectrum = seq.Spectrum(r'C:\MyPyProgs\Sequencer\data\s1c4b1.txt') self.spectra = {} self.spectra_names = [] self.filenames = [] ############################### ### User editable variables ### self.precision = IntVar(value=4, name='precision') self.sensitivity = IntVar(value = 50, name='sensitivity') ### User editable variables ### ############################### # Set up the main window ttk.Frame.__init__(self, master, borderwidth=5, width=self.WIDTH, height=self.WIDTH) self.master.resizable(FALSE, FALSE) self.grid(column=0, row=0, sticky=(N, S, E, W)) self.columnconfigure(0, weight=1) # Create the upper control frame self.control_frame = ttk.Frame(self, width=self.WIDTH // 2, height=300, relief='sunken') self.control_label = ttk.Label(self.control_frame, text="Controls", font='arial', justify='center') # Precision controls definitions self.precision_label = ttk.Label(self.control_frame, text="Precision: ") self.precision_entry = ttk.Entry(self.control_frame, textvariable=self.precision) self.precision_help_button = ttk.Button(self.control_frame, text="Help") # Sensitivity controls definitions self.sensitivity_label = ttk.Label(self.control_frame, text="Sensitivity") self.sensitivity_entry = ttk.Entry(self.control_frame, textvariable=self.sensitivity) self.sensitivity_reload = ttk.Button(self.control_frame, text="Reload") self.sensitivity_help_button = ttk.Button(self.control_frame, text="Help") self.analyse_known_button = ttk.Button(self.control_frame, text="Analyse From Known") self.control_frame.grid(row=0, column=1, sticky=(N, E, S)) self.control_label.grid(column=0, row=0, columnspan=4, sticky=(N), pady=5, padx=self.WIDTH // 5) ### Grid layouts ### # Precision controls grid self.precision_label.grid(column=0, row=1, padx=2) self.precision_entry.grid(column=1, row=1, padx=2) self.precision_help_button.grid(column=3, row=1, padx=2) # Sensitivity controls grid self.sensitivity_label.grid(column=0, row=2, padx=2) self.sensitivity_entry.grid(column=1, row=2, padx=2) self.sensitivity_reload.grid(column=2, row=2, padx=2) self.sensitivity_help_button.grid(column=3, row=2, padx=2) self.analyse_known_button.grid(column=1, row=3, columnspan=2) ### Output frame using ScrolledText ### self.output_frame = ttk.Frame(self, relief='sunken') self.output_frame.grid(row=0, column=0) self.output = tkst.ScrolledText(self.output_frame, width=45, height=20, wrap=WORD) self.output.grid(row=0, column=0, sticky=(N, S, E, W)) self.output.see(END) self.output.insert(END, "Welcome, before you start make sure that the backbone and sugar structures are correct. To analyse your spectra follow the steps below: \n 1. Type the known sequence into the text box from 5' to 3' and click assign. \n 2. Load your spectra in order of charge, File -> Open Spectra... . \n 3. Finally click the Analyse From Known button. \n") self.output['state']='disabled' ### Creates a sunken frame to get the sequence and choose loaded spectra ### self.input_frame = ttk.Frame(self, relief='sunken', borderwidth=5, width=self.winfo_width()) self.input_frame.grid(row=1, column=0, columnspan=2, sticky=(E, W)) self.spec_label = ttk.Label(self.input_frame, text="Spectrum:") self.selected_spec = StringVar() self.spec_select = ttk.Combobox(self.input_frame, values=self.spectra_names) self.spec_label.grid(row=0, column=6, padx=10) self.spec_select.grid(row=0, column=7) seq_entry_label = ttk.Label(self.input_frame, text="Sequence: ") label_5p = ttk.Label(self.input_frame, text="5'-") self.sequence_entry = ttk.Entry(self.input_frame, width=40) label_3p = ttk.Label(self.input_frame, text="-3'") assign_seq = ttk.Button(self.input_frame, text="Calculate", command=lambda : self.assign(self.sequence_entry)) seq_entry_label.grid(row=0, column=0) label_5p.grid(row=0, column=1) self.sequence_entry.grid(row=0, column=2) label_3p.grid(row=0, column=3) assign_seq.grid(row=0, column=4) ### Creates a sunken frame to plot the current spectrum ### self.spec_frame = ttk.Frame(self, relief='sunken', borderwidth=1, width=self.winfo_width(), height=250) self.spec_frame.grid(row=2, column=0, columnspan=2, sticky=(S, E, W)) self.plot = specplot.Plot(self.spec_frame, self.spectrum) precision = 4 charge = -1 file = r'C:\MyPyProgs\sequencer\data\s1c4b1.txt' spectrum = Spectrum(file, precision, charge) if __name__ == "__main__": root = Tk() root.title("Sequencer_help") view = View(root) root.mainloop() print("End") 
1
  • 1
    also, the gui code is irrelevant here. you should trim your examples to down to the bare minimum code needed to produce the problem. Commented Jan 17, 2014 at 17:59

2 Answers 2

22

In addition to @mgilson's suggestion of vlines (which does what you want but requires that you specify the bottom location), you should also have a look at stem.

For example:

import matplotlib.pyplot as plt import numpy as np x, y = np.random.random((2, 20)) fig, ax = plt.subplots() ax.stem(x, y) plt.show() 

enter image description here

Or to leave out the dots:

import matplotlib.pyplot as plt import numpy as np x, y = np.random.random((2, 20)) fig, ax = plt.subplots() ax.stem(x, y, markerfmt=' ') plt.show() 

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I will try this out! This looks to be exactly what I'm after
Hi Joe, this method was pretty good, the plots looked exactly right. The only down side was the plotting speed. Unfortunately it makes the program feel quite clunky. Thanks for the reply
12

To me, it looks like you want the vlines method rather than the plot method.

5 Comments

ooooo -- i didn't know about that method!
@PaulH -- I knew immediately how I would do it in gnuplot (with impulses). Then I just did a quick google search for how to reproduce gnuplot's impulses in matplotlib -- This was what came up :-).
Hi mgilson, thanks for this reply. I Have implemented this into my program and it works perfectly! Exactly what I needed. The plotting speed is very high so I can switch between plots very easily in my gui. Thanks
vlines is much faster (74ms ) than stem (1100ms)
This is not an answer to the question. Show your answer with code.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.