ValueErrors in working tkinter gui app - python

I have gotten my first gui app to a functional point where I can start using it. Everything works fine except I get traceback ValueErrors could not convert string to float when I enter data into the entries. I am getting other errors too, that I don't understand. Any insight on how I can make this app error free would be greatly appreciated.
Here is a copy of the console after entering some numbers into the entries and changing the combobox
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1532, in __call__
return self.func(*args)
File "C:\Users\timewarnerIP-server\Desktop\Hillside_production_Calculator.py",
line 370, in <lambda>
self.cycletimes[num].trace('w', lambda x,y,z: proj(num))
File "C:\Users\timewarnerIP-server\Desktop\Hillside_production_Calculator.py",
line 346, in proj
case = float(self.current_case_vars[tab].get())
ValueError: could not convert string to float:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1532, in __call__
return self.func(*args)
File "C:\Users\timewarnerIP-server\Desktop\Hillside_production_Calculator.py",
line 377, in <lambda>
self.moldvars[num].trace("w", lambda x, y, z: cyclecnt(num))
File "C:\Users\timewarnerIP-server\Desktop\Hillside_production_Calculator.py",
line 301, in cyclecnt
cyclecount = int(self.cycle_count_vars[tab].get())
ValueError: invalid literal for int() with base 10: ''
#
from Tkinter import *
from ttk import *
import time
class supervisorcalc:
def __init__(self, master):
#####notebook tabs#####
self.notebook = Notebook(master)
self.lines = {}
for i in range(10, 20):
self.lines[i] = Frame(self.notebook)
self.notebook.add(self.lines[i], text="Line" + str(i))
self.notebook.grid(row=0,column=0)
###end notebook tabs###
moldoptions = [1, 1, 2, 3, 4]
###widget dictionaries###
### cycle time ###
###cycle time labels###
self.ctlabels = {}
for i in range(10, 20):
self.ctlabels[i] = Label(self.lines[i], text = "Cycle Time:")
###cycle time variables###
self.cycletimes = {}
for i in range(10,20):
self.cycletimes[i] = StringVar()
###cycle time entries###
self.cycle_time_entries = {}
for i in range(10,20):
self.cycle_time_entries[i] = Entry(self.lines[i], textvariable=self.cycletimes[i])
###molds###
###mold combo box variables###
self.moldvars = {}
for i in range(10,20):
self.moldvars[i] = IntVar()
###molds labels###
self.heads_labels = {}
for i in range(10,20):
self.heads_labels[i] = Label(self.lines[i], text = "# of Molds:")
###molds combo box###
self.head_combo_boxes = {}
for i in range(10,20):
self.head_combo_boxes[i] = OptionMenu(self.lines[i], self.moldvars[i], *moldoptions)
###cycle count###
###cycle count labels###
self.cycle_count_labels = {}
for i in range(10,20):
self.cycle_count_labels[i] = Label(self.lines[i], text = "Cycle Count:")
###cycle count variables###
self.cycle_count_vars = {}
for i in range(10,20):
self.cycle_count_vars[i] = StringVar()
###cycle count entries###
self.cycle_count_entries = {}
for i in range(10,20):
self.cycle_count_entries[i] = Entry(self.lines[i], textvariable=self.cycle_count_vars[i])
### units per case###
### units per case labels###
self.units_per_case_labels = {}
for i in range(10,20):
self.units_per_case_labels[i] = Label(self.lines[i], text = "Units/Case:")
### units per case variables#
self.units_per_case_vars = {}
for i in range(10,20):
self.units_per_case_vars[i] = StringVar()
### units per case entries###
self.units_per_case_entries = {}
for i in range(10,20):
self.units_per_case_entries[i] = Entry(self.lines[i], textvariable=self.units_per_case_vars[i])
### current case ###
### current case labels ###
self.current_case_labels = {}
for i in range(10, 20):
self.current_case_labels[i] = Label(self.lines[i], text = "Current Case #:")
### current case variables ###
self.current_case_vars = {}
for i in range(10,20):
self.current_case_vars[i] = StringVar()
### current case entries ###
self.current_case_entries = {}
for i in range(10, 20):
self.current_case_entries[i] = Entry(self.lines[i], textvariable=self.current_case_vars [i])
### current time ###
### current time labels###
self.current_time_labels = {}
for i in range (10, 20):
self.current_time_labels[i] = Label(self.lines[i], text = "Current Time:")
### clock labels ###
self.clocks = {}
for i in range (10, 20):
self.clocks[i] = Label(self.lines[i])
### future time ###
### future time extra frame###
self.future_frames = {}
for i in range (10, 20):
self.future_frames[i] = Frame(self.lines[i])
### future labels ###
self.future_labels = {}
for i in range (10, 20):
self.future_labels[i] = Label(self.lines[i], text = "Future Projections time:")
### future hour variables ###
self.future_hours_vars = {}
for i in range (10, 20):
self.future_hours_vars[i] = StringVar()
### future hour entries ###
self.future_hour_entries = {}
for i in range (10, 20):
self.future_hour_entries[i] = Entry(self.future_frames[i], width=2, textvariable=self.future_hours_vars[i])
### future time colon###
self.future_time_colon = {}
for i in range(10, 20):
self.future_time_colon[i] = Label(self.future_frames[i], text = ":")
### future minutes variables###
self.future_minutes_vars = {}
for i in range(10,20):
self.future_minutes_vars[i] = StringVar()
### future minutes entries###
self.future_minutes = {}
for i in range(10,20):
self.future_minutes[i] = Entry(self.future_frames[i], width=2, textvariable=self.future_minutes_vars[i])
### cycle total ###
### cycle total labels ###
self.total_cycles_labels = {}
for i in range(10, 20):
self.total_cycles_labels[i] = Label(self.lines[i], text = 'Cycle Total:')
### total cycles variables ###
self.total_cycles_vars = {}
for i in range(10,20):
self.total_cycles_vars[i] = StringVar()
### total cycles display###
self.total_cycles_disp = {}
for i in range(10, 20):
self.total_cycles_disp[i] = Label(self.lines[i], foreground = 'green', background = 'black', text = "00000", textvariable = self.total_cycles_vars[i])
### current production ###
### current production labels ###
self.current_production_labels = {}
for i in range(10, 20):
self.current_production_labels[i] = Label(self.lines[i], text = 'Current Production:')
### current production variables ###
self.current_production_vars = {}
for i in range(10, 20):
self.current_production_vars[i] = StringVar()
### current production ###
self.current_production_disp = {}
for i in range(10, 20):
self.current_production_disp[i] = Label(self.lines[i], foreground = 'green', background = 'black', textvariable=self.current_production_vars[i])
### projected production ###
### projected production labels###
self.projected_production_labels = {}
for i in range(10, 20):
self.projected_production_labels[i] = Label(self.lines[i], text = 'Projected Production:')
### projected production variables ###
self.projected_production_vars = {}
for i in range(10, 20):
self.projected_production_vars[i] = StringVar()
### projected production display ###
self.projected_production_disp = {}
for i in range(10,20):
self.projected_production_disp[i] = Label(self.lines[i], foreground = 'green', background = 'black', textvariable=self.projected_production_vars[i])
### lost units ###
### lost units labels ###
self.lost_units_labels = {}
for i in range(10, 20):
self.lost_units_labels[i] = Label(self.lines[i], text = 'Lost units:')
### lost units variables ###
self.lost_units_vars = {}
for i in range(10, 20):
self.lost_units_vars[i] = StringVar()
### lost units display ###
self.lost_units_displays = {}
for i in range(10, 20):
self.lost_units_displays[i] = Label(self.lines[i], foreground = 'green', background = 'black', textvariable=self.lost_units_vars[i])
### projected lost units ###
### projectd lost units labels ###
self.projected_lost_units_labels = {}
for i in range(10, 20 ):
self.projected_lost_units_labels[i] = Label(self.lines[i], text = 'Projected Lost units:')
### projected lost unit variables ###
self.projected_lost_units_vars = {}
for i in range(10, 20):
self.projected_lost_units_vars[i] = StringVar()
### projected lost ###
self.projected_lost_units_displays = {}
for i in range(10, 20):
self.projected_lost_units_displays[i] = Label(self.lines[i], foreground = 'green', background = 'black', textvariable=self.projected_lost_units_vars[i])
### efficiency ###
### efficiency labels ###
self.current_efficiency_labels = {}
for i in range(10,20):
self.current_efficiency_labels[i] = Label(self.lines[i], text = 'Current efficiency %:')
### efficiency variables ###
self.current_efficiency_vars = {}
for i in range(10, 20):
self.current_efficiency_vars[i] = StringVar()
### efficiency displays ###
self.current_efficiency_displays = {}
for i in range(10, 20):
self.current_efficiency_displays[i] = Label(self.lines[i], foreground = 'green', background = 'black', textvariable=self.current_efficiency_vars[i])
### future case ###
### future case labels ###
self.future_case_projection_labels = {}
for i in range(10, 20):
self.future_case_projection_labels[i] = Label(self.lines[i], text = 'Future case # projection:')
### future case variables ###
self.future_case_projection_vars = {}
for i in range(10, 20):
self.future_case_projection_vars[i] = StringVar()
### future case displays ###
self.future_case_projection_disp = {}
for i in range(10, 20):
self.future_case_projection_disp[i] = Label(self.lines[i], foreground = 'green', background = 'black', textvariable=self.future_case_projection_vars[i])
### projected efficiency ###
### projected efficiency labels ###
self.projected_efficiency_labels = {}
for i in range(10, 20):
self.projected_efficiency_labels[i] = Label(self.lines[i], text = "Efficiency Projection:")
### projected efficiency variables ###
self.projected_efficiency_vars = {}
for i in range(10, 20):
self.projected_efficiency_vars[i] = StringVar()
### projected efficiency entries ###
self.projected_efficiency_entries = {}
for i in range(10, 20):
self.projected_efficiency_entries[i] = Entry(self.lines[i], textvariable=self.projected_efficiency_vars[i])
###functions###
def cyclecnt(tab, *args):
cyclecount = int(self.cycle_count_vars[tab].get())
molds = self.moldvars[tab].get()
cyccount = cyclecount * molds
self.total_cycles_vars[tab].set(cyccount)
return
def currentproduction(tab, *args):
item = int(self.units_per_case_vars[tab].get())
case = int(self.current_case_vars [tab].get())
currprod = item * case
self.current_production_vars[tab].set(currprod)
return
def lostunits(tab, *args):
cycle = int(self.total_cycles_vars[tab].get())
prod = int(self.current_production_vars[tab].get())
self.lost_units_vars[tab].set(cycle - prod)
return
def efficiency(tab, *args):
lost = float(self.lost_units_vars[tab].get())
prod = float(self.current_production_vars[tab].get())
self.current_efficiency_vars[tab].set((lost/prod)*100)
return
def getSec(x):
l = x.split(':')
return int(l[0]) * 3600 + int(l[1]) * 60 + int(l[2])
def future_time_seconds(tab, *args):
hrs = self.future_hours_vars[tab].get()
mins = self.future_minutes_vars[tab].get()
return (int(hrs) * 3600) + (int(mins) * 60)
def time_difference_seconds(tab, *args):
fseconds = future_time_seconds(tab)
s = time.strftime('%I:%M:%S')
cursecs = getSec(s)
return fseconds - cursecs
def proj(tab, *args):
ctime = float(self.cycletimes[tab].get())
prod = float(self.current_production_vars[tab].get())
loss = float(self.lost_units_vars[tab].get())
case = float(self.current_case_vars[tab].get())
molds = float(self.moldvars[tab].get())
item = float(self.units_per_case_vars[tab].get())
seconds = time_difference_seconds(tab)
pcycle = ((molds / ctime) * seconds)
projeff = float(self.projected_efficiency_vars[tab].get()) / float(100)
pproduction = pcycle - (pcycle * projeff)
self.projected_production_vars[tab].set(prod + pproduction)
projloss = loss + pcycle * projeff
self.projected_lost_units_vars[tab].set(projloss)
fcase = case + (pproduction / float(item))
self.future_case_projection_vars[tab].set(fcase)
### widget fuction ###
def widg_on_panes(self, num):
### cycle time ###
self.ctlabels[num].grid(row=2, column=0)
self.cycletimes[num].trace('w', lambda x,y,z: proj(num))
self.cycle_time_entries[num].grid(row=2,column=1)
### molds ###
self.moldvars[num].set(moldoptions[0])
self.heads_labels[num].grid(row=3, column=0)
self.head_combo_boxes[num].grid(row=3,column=1)
self.moldvars[num].trace("w", lambda x, y, z: cyclecnt(num))
### cycle count ###
self.cycle_count_labels[num].grid(row=4, column=0)
self.cycle_count_vars[num].trace("w", lambda x, y, z: cyclecnt(num))
self.cycle_count_entries[num].grid(row=4,column=1)
### units per case ###
self.units_per_case_labels[num].grid(row=5, column=0)
self.units_per_case_entries[num].grid(row=5,column=1)
self.units_per_case_vars[num].trace("w", lambda x, y, z: currentproduction(num))
### current case ###
self.current_case_labels[num].grid(row=6, column=0)
self.current_case_entries[num].grid(row=6,column=1)
self.current_case_vars[num].trace("w", lambda x, y, z: currentproduction(num))
### clock ###
self.current_time_labels[num].grid(row=7, column=0, sticky='W')
self.clocks[num].grid(row=7,column=1, sticky='w')
#### future time ###
self.future_frames[num].grid(row=8, column=1)
self.future_labels[num].grid(row=8, column=0, sticky='w')
self.future_hours_vars[num].trace('w', lambda x, y, z: proj(num))
self.future_hour_entries[num].grid(row=0, column=0)
self.future_time_colon[num].grid(row=0, column=1)
self.future_minutes_vars[num].trace('w', lambda x, y, z: proj(num))
self.future_minutes[num].grid(row=0, column=2)
### total cycle display ###
self.total_cycles_labels[num].grid(row=2, column=2)
self.total_cycles_vars[num].set("00000")
self.total_cycles_vars[num].trace('w', lambda x, y, z: lostunits(num))
self.total_cycles_disp[num].grid(row=2, column=3)
### current production ###
self.current_production_labels[num].grid(row=3, column=2)
self.current_production_vars[num].set('00000')
self.current_production_vars[num].trace('w', lambda x, y, z: lostunits(num))
self.current_production_vars[num].trace('w', lambda x, y, z: efficiency(num))
self.current_production_disp[num].grid(row=3, column=3)
### projected production ###
self.projected_production_labels[num].grid(row=4, column=2)
self.projected_production_vars[num].set('00000')
self.projected_production_disp[num].grid(row=4, column=3)
### lost units ###
self.lost_units_labels[num].grid(row=5, column=2)
self.lost_units_vars[num].set("0000")
self.lost_units_vars[num].trace('w', lambda x, y, z: efficiency(num))
self.lost_units_displays[num].grid(row=5, column=3)
### projected lost uniots ###c
self.projected_lost_units_labels[num].grid(row=6, column=2)
self.projected_lost_units_vars[num].set("0000")
self.projected_lost_units_displays[num].grid(row=6, column=3)
### current efficiency ###
self.current_efficiency_labels[num].grid(row=7, column=2)
self.current_efficiency_vars[num].set("00.00")
self.current_efficiency_displays[num].grid(row=7, column=3)
### future case ###
self.future_case_projection_labels[num].grid(row=8, column=2)
self.future_case_projection_vars[num].set("000.0")
self.future_case_projection_disp[num].grid(row=8, column=3)
### projected efficiency ###
self.projected_efficiency_labels[num].grid(row=9, column=2)
self.projected_efficiency_vars[num].set(0.00)
self.projected_efficiency_vars[num].trace('w', lambda x, y, z: proj(num))
self.projected_efficiency_entries[num].grid(row=9,column=3)
for num in range(10,20):
widg_on_panes(self, num)
def tick():
s = time.strftime('%I:%M:%S')
if s != self.clocks[10]:
for i in range(10, 20):
self.clocks[i].configure(text=s)
self.notebook.after(200, tick)
tick()
root = Tk()
root.wm_title("Hillside Plastics Production Calculator")
calc = supervisorcalc(root)
mainloop()

Your tracebak contains two errors.
In this case
line 301, in cyclecnt
cyclecount = int(self.cycle_count_vars[tab].get())
ValueError: invalid literal for int() with base 10: ''
you trying to convert empty string to integer. In this case you could use following approach
s = self.cycle_count_vars[tab].get()
cyclecount = int(s) if s else 0
or more general approach
try:
cyclecount = int(self.cycle_count_vars[tab].get())
except ValueError as e:
cyclecount = 0 # or some other default value
This error
line 346, in proj
case = float(self.current_case_vars[tab].get())
ValueError: could not convert string to float:
means, that string variable self.current_case_vars[tab].get() doesn't contains valid float data. This situation can also be handled with try/except block.

Related

Windows serial port timing issue or bad code? [Python]

I am writing an application for a digital lab balance that connects over serial. To build the application I set up a COM port bridge and wrote a program to simulate the balance on my machine (the balance was in use). I will show you the most recent version of the balance simulation program:
import serial, random, time
s = serial.Serial('COM2')
#Initially we will just push a random float
#After the data the scale sends a carraige return + line feed
def pushData():
data = f'{round(random.uniform(10, 100), 2)}\r\n'.encode()
print(f'Sending Data: {data}')
s.write(data)
try:
while True:
pushData()
time.sleep(10)
except:
print('Something went wrong.')
This code along with my balance application works as expected on my machine. But when I try to use my balance program with the actual device it does not get all the serial data if it even works at all. I am wondering if I need some kind of multi-threading, if its a timing issue or something. I know the balance works because I can monitor the COM port.
I will post my most recent balance program here:
# !/usr/bin/python3
################ Imports
import serial, pyperclip
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from datetime import datetime, time
from tkinter import *
################ Declarations
GUI = Tk()
s = serial.Serial('COM5', timeout=1)
wgtList = [0,0,0,0,0]
wgtDict = {'Lab':[],
'Weight':[]}
newL = '\r\n'
tareWgt = 0
newWgt = 0 #Trying to get past program not working when no data is pushed
################ Functions
def thisAfter():
"""Updates scale feed and updates the scale feed."""
try:
global newWgt
newWgt = float(s.readline().decode().rstrip('\r\n')) - tareWgt
except ValueError:
#print('ValueError thisAfter(): NO DATA OR COULD NOT CONVERT SERIAL DATA TO FLOAT')
print('ValueError thisAfter(): '+ str(newWgt))
print('wgtList: '+ str(wgtList))
wgtList.append(newWgt)
if newWgt not in wgtList[0:5]:
text.insert(INSERT,str(newWgt)+newL)
if len(wgtList) > 5:
del wgtList[0]
GUI.after(50, thisAfter)
text.see(END)
def labCallback():
"""Saves data to file, iterates the entry field."""
num = labEntry.get()
csvStr = datetime.today().strftime("%Y/%m/%d") + ',' + datetime.now().strftime("%H:%M:%S") + ',' + num + ',' + str(wgtList[-1]) + ',' + var1.get() + ',' + str(tareWgt) + newL
with open('data.csv', 'a+', newline = '') as file:
if file.readline() == None:
file.write('Date, Time, Lab, Weight, Type' + newL)
file.write(csvStr)
#print(csvStr) #Just checking
labEntry.delete(0,END)
labEntry.insert(0, int(num) + 1)
csvArr = csvStr.split(',')
wgtDict['Lab'].append(int(csvArr[2]))
wgtDict['Weight'].append(float(csvArr[3]))
text2.insert(INSERT, ',\t'.join(csvArr))
text2.see(END)
#print(str(wgtDict)+'\n')
def tareCallback():
global tareWgt
tareWgt = wgtList[-1]
print(tareWgt)
text3.insert(INSERT,newL+str(tareWgt))
text3.see(END)
def copyData():
global newWgt
pyperclip.copy(newWgt)
def close():
s.close()
def start():
global s
try:
s = serial.Serial('COM5', timeout=1)
thisAfter()
except:
print('Serial port closed')
################ Frames/Panes
frame1 = LabelFrame(GUI, text = 'Lab Label + Entry Field')
frame1.pack(side = TOP)
frame6 = LabelFrame(frame1, text = 'Tare')
frame6.pack(side = BOTTOM)
frame2 = LabelFrame(GUI, text = 'Scale Feed')
frame2.pack(side = BOTTOM)
frame3 = LabelFrame(GUI, text = 'Saved Feed')
frame3.pack(side = BOTTOM)
frame4 = LabelFrame(GUI, text = 'Plot')
frame4.pack(side = TOP)
frame5 = LabelFrame(frame1, text = 'Type Select')
frame5.pack(side = BOTTOM)
################ Lab Label + Entry Field + Type Select
labLabel = Label(frame1, bd = 5, text = 'Lab#')
labLabel.pack(side = LEFT)
tareLabel = Label(frame6, bd = 5, text = 'Tare')
tareLabel.pack(side = LEFT)
text3 = Text(frame6, height = 1, width = 20)
text3.pack(side = RIGHT)
closeButton = Button(frame1, text = 'Close', command = close)
closeButton.pack(side = RIGHT)
startButton = Button(frame1, text = 'Start', command = start)
startButton.pack(side = RIGHT)
tareButton = Button(frame1, text = 'Tare', command = tareCallback)
tareButton.pack(side = RIGHT)
undoButton = Button(frame1, text = 'Undo')
undoButton.pack(side = RIGHT)
labButton = Button(frame1, text = 'Save', command = labCallback)
labButton.pack(side = RIGHT)
copyButton = Button(frame1, text = 'Copy', command = copyData)
copyButton.pack(side = RIGHT)
labEntry = Entry(frame1)
labEntry.pack(side = RIGHT)
var1 = StringVar()
r1 = Radiobutton(frame5, text = 'pH', variable= var1, value = 'pH')
r1.pack(anchor = 's')
r2 = Radiobutton(frame5, text = 'pH-Tray', variable= var1, value = 'pH-Tray')
r2.pack(anchor = 's')
r3 = Radiobutton(frame5, text = 'Mehlich', variable= var1, value = 'Mehlich')
r3.pack(anchor = 's')
r4 = Radiobutton(frame5, text = 'Nitrate', variable= var1, value = 'Nitrate')
r4.pack(anchor = 's')
r5 = Radiobutton(frame5, text = 'Excel', variable= var1, value = 'Excel')
r5.pack(anchor = 's')
r6 = Radiobutton(frame5, text = 'Excel-Tray', variable= var1, value = 'Excel-Tray', state=DISABLED)
r6.pack(anchor = 's')
r1.select()
r2.deselect()
r3.deselect()
r4.deselect()
r5.deselect()
r6.deselect()
################ Scale Feed
scrollbar = Scrollbar(frame2)
scrollbar.pack(side = RIGHT, fill = Y)
text = Text(frame2, yscrollcommand = scrollbar.set, height = 10)
text.pack()
text.bind('<ButtonPress>', lambda e: 'break')
scrollbar.config(command = text.yview)
#thisAfter()
################ Saved Feed
scrollbar = Scrollbar(frame3)
scrollbar.pack(side = RIGHT, fill = Y)
text2 = Text(frame3, yscrollcommand = scrollbar.set, height = 10)
text2.pack()
scrollbar.config(command = text.yview)
################ Plot
f = plt.Figure(dpi=50, figsize=(13, 4))
plt.xkcd()
a = f.add_subplot(111)
def animate(i):
xL = wgtDict['Lab']
yL = wgtDict['Weight']
a.clear()
a.plot(xL, yL)
canvas = FigureCanvasTkAgg(f, frame4)
canvas.get_tk_widget().pack(side = LEFT, fill = BOTH)
ani = animation.FuncAnimation(f, animate, interval=1000)
# This is some kind of 'while true' loop fyi
GUI.mainloop()

Embedding matplotlib in tkinter GUI

Trying to embed matplotlib in tkinter GUI, however I get the error:
TypeError: init() got multiple values for argument 'master'
Could you tell me please how to handle it?
Here's the code:
interface - tkinter GUI
visualizer - selv updating graph that uses function live_plotter from pylive_mod file
interface:
# -*- coding: utf-8 -*-
"""
Created on Tue Oct 6 10:24:35 2020
#author: Dar0
"""
from tkinter import * #import tkinter module
from visualizer import main #import module 'visualizer' that shows the graph in real time
class Application(Frame):
''' Interface for visualizing graphs, indicators and text-box. '''
def __init__(self, master):
super(Application, self).__init__(master)
self.grid()
self.create_widgets()
def create_widgets(self):
# Label of the 1st graph
Label(self,
text='Hook Load / Elevator Height / Depth vs Time'
).grid(row = 0, column = 0, sticky = W)
# Graph 1 - Hook Load / Elevator Height / Depth vs Time
# button that displays the plot
plot_button = Button(self,
master = root,
command = main,
height = 2,
width = 10,
text = "Plot").grid(row = 1, column = 0, sticky = W)
# place the button
# in main window
# Label of the 2nd graph
Label(self,
text = 'Hook Load / Elevator Height vs Time'
).grid(row = 2, column = 0, sticky = W)
# Graph 2 - Hook Load / Elevator Height vs Time
#Label of the 3rd graph
Label(self,
text = 'Hook Load vs Time'
).grid(row = 4, column = 0, sticky = W)
#Graph 3 - Hook Load vs Time
#Label of the 1st indicator
Label(self,
text = '1st performance indicator'
).grid(row = 0, column = 1, sticky = W)
#1st performance indicator
#Label of 2nd performance indicator
Label(self,
text = '2nd performance indicator'
).grid(row = 2, column = 1, sticky = W)
#2nd performance indicator
#Label of 3rd performance indicator
Label(self,
text = '3rd performance indicator'
).grid(row = 4, column = 1, sticky = W)
#Text-box showing comments based on received data
self.text_box = Text(self, width = 50, height = 10, wrap = WORD)
self.text_box.grid(row = 6, column = 0, columnspan = 1)
self.text_box.delete(0.0, END)
self.text_box.insert(0.0, 'My message will be here.')
#Main part
root = Tk()
root.title('WiTSML Visualizer by Dar0')
app = Application(root)
root.mainloop()
visualizer:
#WiTSML visualizer
#Created by Dariusz Krol
#import matplotlib
#matplotlib.use('TkAgg')
#from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
#from matplotlib.figure import Figure
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import random
class Visualizer(object):
""" Includes all the methods needed to show streamed data. """
def __init__(self):
self.file_path = 'C:/Anaconda/_my_files/witsml_reader/modified_witsml.csv' #Defines which file is streamed
self.datetime_mod = []
self.bpos_mod = []
self.woh_mod = []
self.torq_mod = []
self.spp_mod = []
self.depth_mod = []
self.flow_in_mod = []
self.rpm_mod = []
def open_file(self):
self.df = pd.read_csv(self.file_path, low_memory = False, nrows = 300000) #Opens the STREAMED file (already modified so that data convert is not required)
self.df = self.df.drop(0)
self.df = pd.DataFrame(self.df)
return self.df
def convert_dataframe(self):
self.df = self.df.values.T.tolist() #Do transposition of the dataframe and convert to list
#Columns are as following:
# - DATETIME
# - BPOS
# - WOH
# - TORQ
# - SPP
# - DEPTH
# - FLOW_IN
# - RPM
self.datetime_value = self.df[0]
self.bpos_value = self.df[1]
self.woh_value = self.df[2]
self.torq_value = self.df[3]
self.spp_value = self.df[4]
self.depth_value = self.df[5]
self.flow_in_value = self.df[5]
self.rpm_value = self.df[7]
return self.datetime_value, self.bpos_value, self.woh_value, self.torq_value, self.spp_value, self.depth_value, self.flow_in_value, self.rpm_value
#print(self.bpos_value)
def deliver_values(self, no_dp, columns):
''' Method gets no_dp amount of data points from the original file. '''
self.no_dp = no_dp #defines how many data points will be presented in the graph
val_dict = {
'datetime': [self.datetime_value, self.datetime_mod],
'bpos': [self.bpos_value, self.bpos_mod],
'woh': [self.woh_value, self.woh_mod],
'torq': [self.torq_value, self.torq_mod],
'spp': [self.spp_value, self.spp_mod],
'depth': [self.depth_value, self.depth_mod],
'flow_in': [self.flow_in_value, self.flow_in_mod],
'rpm': [self.rpm_value, self.rpm_mod]
}
for item in columns:
if self.no_dp > len(val_dict[item][0]):
dp_range = len(val_dict[item][0])
else:
dp_range = self.no_dp
for i in range(dp_range):
val_dict[item][1].append(val_dict[item][0][i])
return self.datetime_mod, self.bpos_mod, self.woh_mod, self.torq_mod, self.spp_mod, self.depth_mod, self.flow_in_mod, self.rpm_mod
def show_graph2(self):
from pylive_mod import live_plotter
self.open_file()
self.convert_dataframe()
self.deliver_values(no_dp = 100000, columns = ['datetime', 'depth', 'bpos', 'woh'])
fst_p = 0
size = 300 # density of points in the graph (100 by default)
x_vec = self.datetime_mod[fst_p:size]
y_vec = self.depth_mod[fst_p:size]
y2_vec = self.bpos_mod[fst_p:size]
y3_vec = self.woh_mod[fst_p:size]
line1 = []
line2 = []
line3 = []
for i in range(self.no_dp):
#print(self.datetime_mod[i:6+i])
#print('Ostatni element y_vec: ', y_vec[-1])
#print(x_vec)
x_vec[-1] = self.datetime_mod[size+i]
y_vec[-1] = self.depth_mod[size+i]
y2_vec[-1] = self.bpos_mod[size+i]
y3_vec[-1] = self.woh_mod[size+i]
line1, line2, line3 = live_plotter(x_vec, y_vec, y2_vec, y3_vec, line1, line2, line3)
x_vec = np.append(x_vec[1:], 0.0)
y_vec = np.append(y_vec[1:], 0.0)
y2_vec = np.append(y2_vec[1:], 0.0)
y3_vec = np.append(y3_vec[1:], 0.0)
def main():
Graph = Visualizer()
Graph.open_file() #Opens the streamed file
Graph.convert_dataframe() #Converts dataframe to readable format
Graph.show_graph2()
#Show us the graph
#main()
pylive_mod (live_plotter):
def live_plotter(x_data, y1_data, y2_data, y3_data, line1, line2, line3, identifier='',pause_time=1):
if line1 == [] and line2 == [] and line3 == []:
# this is the call to matplotlib that allows dynamic plotting
plt.ion()
#fig = Figure(figsize = (5, 4), dpi = 100)
#host = fig.add_subplot()
fig, host = plt.subplots()
fig.set_figheight(7) #adjust figure's height
fig.set_figwidth(14) #adjust figure's width
fig.subplots_adjust(0.15)
#Line1
#line1 = host
ln1 = host
ln2 = host.twinx()
ln3 = host.twinx()
ln2.spines['right'].set_position(('axes', 1.))
ln3.spines['right'].set_position(('axes', 1.12))
make_patch_spines_invisible(ln2)
make_patch_spines_invisible(ln3)
ln2.spines['right'].set_visible(True)
ln3.spines['right'].set_visible(True)
ln1.set_xlabel('Date & Time') #main x axis
ln1.set_ylabel('Depth') #left y axis
ln2.set_ylabel('Elevator Height')
ln3.set_ylabel('Weight on Hook')
#
x_formatter = FixedFormatter([x_data])
x_locator = FixedLocator([x_data[5]])
ln1.xaxis.set_major_formatter(x_formatter)
ln1.xaxis.set_major_locator(x_locator)
#
ln1.locator_params(nbins = 5, axis = 'y')
ln1.tick_params(axis='x', rotation=90) #rotates x ticks 90 degrees down
ln2.axes.set_ylim(0, 30)
ln3.axes.set_ylim(200, 250)
line1, = ln1.plot(x_data, y1_data, color = 'black', linestyle = 'solid', alpha=0.8, label = 'Depth')
line2, = ln2.plot(x_data, y2_data, color = 'blue', linestyle = 'dashed', alpha=0.8, label = 'Elevator Height')
line3, = ln3.plot(x_data, y3_data, color = 'red', linestyle = 'solid', alpha=0.8, label = 'Weight on Hook')
# ----- embedding -----
canvas = FigureCanvasTkAgg(fig, master = root)
canvas.draw()
# placing the canvas on the Tkinter window
canvas.get_tk_widget().pack()
# creating the Matplotlib toolbar
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
# placing the toolbar on the Tkinter window
canvas.get_tk_widget().pack()
#----- -----
plt.title('WiTSML Visualizer')
fig.tight_layout() #the graphs is not clipped on sides
#Shows legend
lines = [line1, line2, line3]
host.legend(lines, [l.get_label() for l in lines], loc = 'lower left')
#Shows grid
plt.grid(True)
#Shows the whole graph
plt.show()
# after the figure, axis, and line are created, we only need to update the y-data
mod_x_data = convert_x_data(x_data, 10)
line1.axes.set_xticklabels(mod_x_data)
line1.set_ydata(y1_data)
line2.set_ydata(y2_data)
line3.set_ydata(y3_data)
#Debugging
#rint('plt.lim: ', ln2.axes.get_ylim())
# adjust limits if new data goes beyond bounds
# limit for line 1
if np.min(y1_data)<=line1.axes.get_ylim()[0] or np.max(y1_data)>=line1.axes.get_ylim()[1]:
plt.ylim(0, 10)
line1.axes.set_ylim([np.min(y1_data)-np.std(y1_data),np.max(y1_data)+np.std(y1_data)])
# limit for line 2
if np.min(y2_data)<=line2.axes.get_ylim()[0] or np.max(y2_data)>=line2.axes.get_ylim()[1]:
plt.ylim([np.min(y2_data)-np.std(y2_data),np.max(y2_data)+np.std(y2_data)])
#plt.ylim(0, 25)
# limit for line 3
if np.min(y3_data)<=line3.axes.get_ylim()[0] or np.max(y3_data)>=line3.axes.get_ylim()[1]:
plt.ylim([np.min(y3_data)-np.std(y3_data),np.max(y3_data)+np.std(y3_data)])
#plt.ylim(0, 25)
# Adds lines to the legend
#host.legend(lines, [l.get_label() for l in lines])
# this pauses the data so the figure/axis can catch up - the amount of pause can be altered above
plt.pause(pause_time)
# return line so we can update it again in the next iteration
return line1, line2, line3

Python Tkinter & matplotlib - RuntimeError

Okay so I wrote this code...
#!/usr/bin/env
import sys
import time
import subprocess
from Tkinter import *
import numpy
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib
import matplotlib.pyplot as plt
import threading
CDatei = subprocess.Popen("/home/pi/meinc++/Spi")
print("Hallo")
i = 0
x = 0
def GetValue():
with open("/home/pi/meinc++/BeispielDatei.txt","r") as Datei:
for line in Datei:
time.sleep(0.01)
return line
def WithoutNull(input):
ReturnValue = input
while ReturnValue is None:
ReturnValue = GetValue()
return ReturnValue
def UebergabeWert():
while x == 0:
WholeString = WithoutNull(GetValue())
StringVar, DatumVar = WholeString.strip().split(' - ')
IntStringVar = [int(v) for v in StringVar.split()]
return IntStringVar, DatumVar
def MinutenWert():
Maximum = 0
Minimum = 0
i = 0
LaengeArray = 0
Multiplikator = 10000
ArrayValue = [-999999]*Multiplikator
AlteZeit = time.time()
while 1:
CompleteValue, Trash = UebergabeWert()
ArrayValue[i] = CompleteValue[0]
i = i + 1
ArrayFilter = filter(lambda c: c != -999999,ArrayValue)
ArraySumme = numpy.sum(ArrayFilter)
LaengeArray = len(ArrayFilter)
Mittelwert = ArraySumme/LaengeArray
ArraySortierung = sorted(ArrayFilter)
Maximum = ArraySortierung[LaengeArray-1]
Minimum = ArraySortierung[0]
NeueZeit = time.time()
if NeueZeit-AlteZeit >= 60:
AlteZeit = time.time()
ArrayValue[i:Multiplikator] = [-999999]*(Multiplikator-i)
i = 0
yield Mittelwert
yield Maximum
yield Minimum
yield LaengeArray
yield ArrayFilter
def UebergabeTkinter():
while 1:
Mittelwert = next(MinutenWertYield)
Maximum = next(MinutenWertYield)
Minimum = next(MinutenWertYield)
LaengeArray = next(MinutenWertYield)
ArrayFilter = next(MinutenWertYield)
CompleteValue, DatumVar = UebergabeWert()
Variable1.set(CompleteValue[0])
Variable2.set(CompleteValue[1])
Variable3.set(CompleteValue[2])
Variable4.set(CompleteValue[3])
VariableMittelwert.set(Mittelwert)
VariableMaximum.set(Maximum)
VariableMinimum.set(Minimum)
t = threading.Thread(target = Grafik)
t.start()
root.update()
def Grafik():
GrafikAnfang = time.time()
Array = 0
ArrayGrafik = [0]*20
GrafikEnde = 1
while 1:
CompleteValue, DatumVar = UebergabeWert()
ArrayGrafik[Array] = CompleteValue[0]
LaengeArrayGrafik = len(ArrayGrafik)
fig = Figure(figsize = (3, 3))
axis = fig.add_subplot(111)
axis.legend()
axis.grid()
canvas = FigureCanvasTkAgg(fig, master = root)
canvas.get_tk_widget().grid(row=10,column=0,rowspan=2,columnspan=2)
LinienBreite = numpy.linspace(1,LaengeArrayGrafik,LaengeArrayGrafik)
axis.plot(LinienBreite,ArrayGrafik,'b-')
axis.set_xticks(LinienBreite)
DatumArray = [DatumVar]
axis.set_xticklabels(DatumArray)
canvas.draw()
fig.clear()
print Array
if GrafikEnde-GrafikAnfang < 600:
Array = Array + 1
GrafikEnde = time.time()
if GrafikEnde-GrafikAnfang >= 600:
del ArrayGrafik[0]
def Exit():
root.destroy()
return
try:
MinutenWertYield = MinutenWert()
root = Tk()
Leiste = Menu(root)
root.config(menu = Leiste)
DateiMenu = Menu(Leiste)
Leiste.add_cascade(label = "datei", menu = DateiMenu)
DateiMenu.add_command(label = "Exit", command = Exit)
EditMenu = Menu(Leiste)
Leiste.add_cascade(label = "edit", menu = EditMenu)
Variable1 = IntVar()
Variable2 = IntVar()
Variable3 = IntVar()
Variable4 = IntVar()
VariableMittelwert = IntVar()
VariableMaximum = IntVar()
VariableMinimum = IntVar()
Ausgang = 0
for column in range(0,8,2):
String1 = "Ausgang "
String1 += `Ausgang`
Ausgang = Ausgang + 1
Label(text = String1).grid(row=0,column=column)
Ausgang = 0
for column in range(0,8,2):
String1 = "Der Wert von "
String2 = " ist: "
String1 += `Ausgang`
Ausgang = Ausgang + 1
String3 = String1+String2
Label(text = String3).grid(row=2,column=column)
Label(text = "Der Mittelwert ist: ").grid(row=4,column=0)
Label(text = "Das Maximum ist: ").grid(row=5,column=0)
Label(text = "Das Mimimum ist: ").grid(row=6,column=0)
Label1 = Label(root, textvariable = Variable1)
Label1.grid(row = 2, column = 1)
Label2 = Label(root, textvariable = Variable2)
Label2.grid(row = 2, column = 3)
Label3 = Label(root, textvariable = Variable3)
Label3.grid(row = 2, column = 5)
Label4 = Label(root, textvariable = Variable4)
Label4.grid(row = 2, column = 7)
LabelMittelwert = Label(root, textvariable = VariableMittelwert)
LabelMittelwert.grid(row = 4, column = 1)
LabelMaximum = Label(root, textvariable = VariableMaximum)
LabelMaximum.grid(row = 5, column = 1)
LabelMinimum = Label(root, textvariable = VariableMinimum)
LabelMinimum.grid(row = 6, column = 1)
UebergabeTkinter()
print "Hallo"
root.mainloop()
except KeyboardInterrupt:
CDatei.kill()
root.quit()
root.destroy()
and when i run it, it says "RuntimeError: main thread is not in the main loop".
Short explanation of the code: It's a code to read out sensor data from a text file -
GetValue().
If the Data is Null it'll read out again - WithoutNull().
The Data is then splitted into data and timestamp (cause it has the format val1, val2, val3, val4, time) - UebergabeWert.
Then the maxima, minima and average of the data will be measured - MinutenWert()
After this, the values are set as labels and go their way into Tkinter - UebergabeTkinter()
The Tkinter build is mainly in Try:
What I wanted to do there, is to implement a graph to Tkinter, but because of the fast changing values it got tremendously slow so i decided to put the graph build in a thread and run it parallel to Tkinter. Unfortunately, it doesn't seem to work and I don't know why
Any suggestions?

Looping a function using after() method

I designed a GUI to plot a graph from the text file. However, the plots will not update when I added new points into the text file. I tried using the after() method to keep looping my function to plot the graph but it fails to work. It would not update my plots and it would not even print out 'Updating...' as shown in the code. Would like to know what went wrong and is there a better way to update my plots? Thanks.
class Timer:
def __init__(self, parent):
self.parent = parent
self.time1 = " "
self.time_label = Label(topFrame, text=self.time1, font = "Helvetica 12 bold")
self.time_label.grid(row = 1, column = 1)
self.random_lbl = Label(topFrame, text="Virtual Microgrid", font = "Helvetica 16 bold italic")
self.random_lbl.grid(row = 0, column = 1)
self.random_lbl = Label(topFrame, text="GRAPHS", font = "Helvetica 12 bold" )
self.random_lbl.grid(row = 2, column = 5)
self.update_clock()
def update_clock(self):
self.time2 = time.strftime("%H:%M:%S")
self.time1 = self.time2
self.time_label.config(text=self.time1)
self.parent.after(200, self.update_clock)
def update(self):
self.animate()
print("Updating.....")
self.parent.after(1, self.update)
def animate():
graph_data = open('example.txt', 'r').read()
lines = graph_data.split('\n')
xs = []
ys = []
for line in lines:
if len(line) > 1:
x,y = line.split(',')
xs.append(x)
ys.append(y)
graph_data = open('example1.txt', 'r').read()
lines = graph_data.split('\n')
xs1 = []
ys1 = []
for line in lines:
if len(line) > 1:
x,y = line.split(',')
xs1.append(x)
ys1.append(y)
graph_data = open('example2.txt', 'r').read()
lines = graph_data.split('\n')
xs2 = []
ys2 = []
for line in lines:
if len(line) > 1:
x,y = line.split(',')
xs2.append(x)
ys2.append(y)
graph_data = open('example3.txt', 'r').read()
lines = graph_data.split('\n')
xs3 = []
ys3 = []
for line in lines:
if len(line) > 1:
x,y = line.split(',')
xs3.append(x)
ys3.append(y)
graph_data = open('example4.txt', 'r').read()
lines = graph_data.split('\n')
xs4 = []
ys4 = []
for line in lines:
if len(line) > 1:
x,y = line.split(',')
xs4.append(x)
ys4.append(y)
fig = Figure(figsize=(13,3.25))
a = fig.add_subplot(111)
a.plot(xs,ys,color='red')
a.plot(xs1,ys1,color='blue')
a.plot(xs4,ys4,color='black')
a.set_title ("SOURCE", fontsize=8)
a.set_ylabel("Voltage/V", fontsize=8)
a.set_xlabel("Time/s", fontsize=8)
a.grid()
fig5 = Figure(figsize=(13,3.25))
f = fig5.add_subplot(111)
f.plot(xs2,ys2,color='red')
f.plot(xs3,ys3,color='blue')
f.set_title ("LOAD", fontsize=8)
f.set_ylabel("Voltage/V", fontsize=8)
f.set_xlabel("Time/s", fontsize=8)
f.grid()
canvas = FigureCanvasTkAgg(fig, master=rightFrame)
canvas.get_tk_widget().grid(row = 2, column = 1, sticky = "nswe")
canvas.draw()
canvas5 = FigureCanvasTkAgg(fig5, master=rightFrame)
canvas5.get_tk_widget().grid(row = 3, column = 1, sticky = "nswe")
canvas5.draw()
I suggest that you close the file every time after you get all the data.
Look at following
Is close() necessary when using iterator on a Python file object

Real time plotting of serial data with python and tkinter

I have been working for some time to find a way to graph incoming data from an arduino with a Python GUI. I was able to accomplish this using the Matplotlib animation function to read in 6 different variables and plot 4 of them 2 on one subplot 2 on another subplot. This was able to be done fast enough that it was graphing real time (20 samples per second).
I now need to modify the system to read in 12 different variables at the same time of which 8 are graphed. 4 on one sub plot 4 on another at the same rate of 20 samples per second. I haven't been able to get this to work and have tried a few different things and done a lot of research but can't seem to figure out how to do it with my limited knowledge of python. Im not very familiar with multiprocessing or multithreading but they seem to be the way that people are able to speed up the graphing process. I know that the matplotlib animated function itself is threaded so I'm not sure how much the threading would help with that or if there's a way to read in one thread and update the graph in another. I'm operating at the highest baudrate that the arduino supports 250000. I also was able to find an example where someone was able to get a very high speed plot in this post but havent been able to modify to work for my use: What is the best real time plotting widget for wxPython?
the data is received from the arduino like this:
integer.integer.integer|integer.integer.integer|integer.integer.integer|integer.integer.integer
where the pipe represents a new actuator (what each variable im sending is coming from)
I'm fairly new to python so sorry if this isnt so pythonic but here are two examples I have:
This is a gui using the animation function:
import Tkinter
import serial
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib import pyplot as plt
import matplotlib.animation as animation
from collections import deque
import random
class App:
def __init__(self, master):
self.arduinoData = serial.Serial('com5', 250000)#115200)
frame = Tkinter.Frame(master)
self.running = False
self.ani = None
self.start = Tkinter.LabelFrame(frame, text="Start", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10)
self.start.grid(row=0, column=0, padx=20, pady=20)
self.run = Tkinter.Button(self.start, text="RUN", bd=10, height=5, width=10, command=self.getData)
self.run.grid(row=0, column=0, padx=5, pady=5)
self.stop_frame = Tkinter.LabelFrame(frame, text="STOP", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10 )
self.stop_frame.grid(row=0, column=1, padx=20, pady=20)
self.stop = Tkinter.Button(self.stop_frame, text="STOP", bd=10, height=5, width=10, command=self.stopTest)
self.stop.grid(row=0, column=0, padx=5, pady=5)
self.fig = plt.Figure()
self.ax1 = self.fig.add_subplot(211)
self.line0, = self.ax1.plot([], [], lw=2)
self.line1, = self.ax1.plot([], [], lw=2)
self.line2, = self.ax1.plot([], [], lw=2)
self.line3, = self.ax1.plot([], [], lw=2)
self.ax2 = self.fig.add_subplot(212)
self.line4, = self.ax2.plot([], [], lw=2)
self.line5, = self.ax2.plot([], [], lw=2)
self.line6, = self.ax2.plot([], [], lw=2)
self.line7, = self.ax2.plot([], [], lw=2)
self.canvas = FigureCanvasTkAgg(self.fig,master=master)
self.canvas.show()
self.canvas.get_tk_widget().grid(row=0, column=4, padx=20, pady=20)
frame.grid(row=0, column=0, padx=20, pady=20)
def getData(self):
if self.ani is None:
self.k = 0
self.arduinoData.flushInput()
self.arduinoData.write("<L>")
return self.start()
else:
self.arduinoData.write("<L>")
self.arduinoData.flushInput()
self.ani.event_source.start()
self.running = not self.running
def stopTest(self):
self.arduinoData.write("<H>")
if self.running:
self.ani.event_source.stop()
self.running = not self.running
def resetTest(self):
self.k = 0
self.xdata = []
self.pressure1 = []
self.displacement1 = []
self.cycle1 = []
self.pressure2 = []
self.displacement2 = []
self.cycle2 = []
self.pressure3 = []
self.displacement3 = []
self.cycle3 = []
self.pressure4 = []
self.displacement4 = []
self.cycle4 = []
self.line1.set_data(self.xdata, self.ydata1)
self.line2.set_data(self.xdata, self.ydata2)
self.ax1.set_ylim(0,1)
self.ax1.set_xlim(0,1)
self.ax2.set_ylim(0,1)
self.ax2.set_xlim(0,1)
def start(self):
self.xdata = []
self.pressure1 = []
self.displacement1 = []
self.cycle1 = []
self.pressure2 = []
self.displacement2 = []
self.cycle2 = []
self.pressure3 = []
self.displacement3 = []
self.cycle3 = []
self.pressure4 = []
self.displacement4 = []
self.cycle4 = []
self.k = 0
self.arduinoData.flushInput()
self.ani = animation.FuncAnimation(
self.fig,
self.update_graph,
interval=1,
repeat=True)
self.arduinoData.write("<L>")
self.running = True
self.ani._start()
def update_graph(self, i):
self.xdata.append(self.k)
while (self.arduinoData.inWaiting()==0):
pass
x = self.arduinoData.readline()
strip_data = x.strip()
split_data = x.split("|")
actuator1 = split_data[0].split(".")
actuator2 = split_data[1].split(".")
actuator3 = split_data[2].split(".")
actuator4 = split_data[3].split(".")
self.pressure1.append(int(actuator1[0]))
self.displacement1.append(int(actuator1[1]))
self.cycle1 = int(actuator1[2])
self.pressure2.append(int(actuator2[0]))
self.displacement2.append(int(actuator2[1]))
self.cycle2 = int(actuator2[2])
self.pressure3.append(int(actuator3[0]))
self.displacement3.append(int(actuator3[1]))
self.cycle3 = int(actuator3[2])
self.pressure4.append(int(actuator4[0]))
self.displacement4.append(int(actuator4[1]))
self.cycle4 = int(actuator4[2])
self.line0.set_data(self.xdata, self.pressure1)
self.line1.set_data(self.xdata, self.pressure2)
self.line2.set_data(self.xdata, self.pressure3)
self.line3.set_data(self.xdata, self.pressure4)
self.line4.set_data(self.xdata, self.displacement1)
self.line5.set_data(self.xdata, self.displacement2)
self.line6.set_data(self.xdata, self.displacement3)
self.line7.set_data(self.xdata, self.displacement4)
if self.k < 49:
self.ax1.set_ylim(min(self.pressure1)-1, max(self.pressure3) + 1)
self.ax1.set_xlim(0, self.k+1)
self.ax2.set_ylim(min(self.displacement1)-1, max(self.displacement3) + 1)
self.ax2.set_xlim(0, self.k+1)
elif self.k >= 49:
self.ax1.set_ylim(min(self.pressure1[self.k-49:self.k])-1, max(self.pressure3[self.k-49:self.k]) + 1)
self.ax1.set_xlim(self.xdata[self.k-49], self.xdata[self.k-1])
self.ax2.set_ylim(min(self.displacement1[self.k-49:self.k])-1, max(self.displacement3[self.k-49:self.k]) + 1)
self.ax2.set_xlim(self.xdata[self.k-49], self.xdata[self.k-1])
self.k += 1
root = Tkinter.Tk()
app = App(root)
root.mainloop()
This is a gui that prints to the monitor:
import Tkinter
import serial
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib import pyplot as plt
import matplotlib.animation as animation
import time
class App:
def __init__(self, master):
self.arduinoData = serial.Serial('com5', 250000, timeout=0)
frame = Tkinter.Frame(master)
self.go = 0
self.start = Tkinter.LabelFrame(frame, text="Start", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10)
self.start.grid(row=0, column=0, padx=20, pady=20)
self.run = Tkinter.Button(self.start, text="RUN", bd=10, height=5, width=10, command=self.getData)
self.run.grid(row=0, column=0, padx=5, pady=5)
self.stop_frame = Tkinter.LabelFrame(frame, text="STOP", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10 )
self.stop_frame.grid(row=0, column=1, padx=20, pady=20)
self.stop = Tkinter.Button(self.stop_frame, text="STOP", bd=10, height=5, width=10, command=self.stopTest)
self.stop.grid(row=0, column=0, padx=5, pady=5)
self.fig = plt.Figure()
self.ax1 = self.fig.add_subplot(211)
self.line0, = self.ax1.plot([], [], lw=2)
self.line1, = self.ax1.plot([], [], lw=2)
self.line2, = self.ax1.plot([], [], lw=2)
self.line3, = self.ax1.plot([], [], lw=2)
self.ax2 = self.fig.add_subplot(212)
self.line4, = self.ax2.plot([], [], lw=2)
self.line5, = self.ax2.plot([], [], lw=2)
self.line6, = self.ax2.plot([], [], lw=2)
self.line7, = self.ax2.plot([], [], lw=2)
self.canvas = FigureCanvasTkAgg(self.fig,master=master)
self.canvas.show()
self.canvas.get_tk_widget().grid(row=0, column=4, padx=20, pady=20)
frame.grid(row=0, column=0, padx=20, pady=20)
def getData(self):
self.k = 0
self.xdata = []
self.pressure1 = []
self.displacement1 = []
self.cycle1 = []
self.pressure2 = []
self.displacement2 = []
self.cycle2 = []
self.pressure3 = []
self.displacement3 = []
self.cycle3 = []
self.pressure4 = []
self.displacement4 = []
self.cycle4 = []
self.arduinoData.flushInput()
self.go = 1
self.readData()
def readData(self):
if self.go == 1:
self.xdata.append(self.k)
while (self.arduinoData.inWaiting()==0):
pass
x = self.arduinoData.readline()
strip_data = x.strip()
split_data = x.split("|")
actuator1 = split_data[0].split(".")
actuator2 = split_data[1].split(".")
actuator3 = split_data[2].split(".")
actuator4 = split_data[3].split(".")
self.pressure1.append(int(actuator1[0]))
self.displacement1.append(int(actuator1[1]))
self.cycle1 = int(actuator1[2])
self.pressure2.append(int(actuator2[0]))
self.displacement2.append(int(actuator2[1]))
self.cycle2 = int(actuator2[2])
self.pressure3.append(int(actuator3[0]))
self.displacement3.append(int(actuator3[1]))
self.cycle3 = int(actuator3[2])
self.pressure4.append(int(actuator4[0]))
self.displacement4.append(int(actuator4[1]))
self.cycle4 = int(actuator4[2])
self.printData()
root.after(0, self.readData)
def printData(self):
print str(self.pressure1[self.k-1]) + " " +
str(self.displacement1[self.k-1]) + " " + str(self.cycle1) + " " +
str(self.pressure2[self.k-1]) + " " + str(self.displacement2[self.k-
1]) + " " + str(self.cycle2) + " " + str(self.pressure3[self.k-1]) +
" " + str(self.displacement3[self.k-1]) + " " + str(self.cycle3) + "
" + str(self.pressure4[self.k-1]) + " " +
str(self.displacement4[self.k-1]) + " " + str(self.cycle4)
def stopTest(self):
self.arduinoData.write("<H>")
self.go = 0
def resetTest(self):
self.k = 0
self.xdata = []
self.pressure1 = []
self.displacement1 = []
self.cycle1 = []
self.pressure2 = []
self.displacement2 = []
self.cycle2 = []
self.pressure3 = []
self.displacement3 = []
self.cycle3 = []
self.pressure4 = []
self.displacement4 = []
self.cycle4 = []
self.line1.set_data(self.xdata, self.ydata1)
self.line2.set_data(self.xdata, self.ydata2)
self.ax1.set_ylim(0,1)
self.ax1.set_xlim(0,1)
self.ax2.set_ylim(0,1)
self.ax2.set_xlim(0,1)
def start(self):
self.xdata = []
self.pressure1 = []
self.displacement1 = []
self.cycle1 = []
self.pressure2 = []
self.displacement2 = []
self.cycle2 = []
self.pressure3 = []
self.displacement3 = []
self.cycle3 = []
self.pressure4 = []
self.displacement4 = []
self.cycle4 = []
self.k = 0
self.arduinoData.write("<L>")
root = Tkinter.Tk()
app = App(root)
root.mainloop()
and here is an example arduino code:
int analog0 = 0;
int analog1 = 1;
int analog2 = 2;
int sensor0;
int sensor1;
int sensor2;
String pot0;
String pot1;
String Force;
int pot0holder;
int pot1holder;
String Forceholder;
unsigned long i = 0;
String Is;
int val = 0;
boolean Sensordata = false;
int cycles;
const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;
unsigned long CurrentMillis = 0;
unsigned long PrintMillis = 0;
int PrintValMillis = 50;
unsigned long SensorMillis = 0;
int SensorValMillis = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(250000);
}
void loop()
{
CurrentMillis = millis();
recvWithStartEndMarkers();
commands();
sensordata();
}
void sensordata()
{
if (CurrentMillis - SensorMillis >= SensorValMillis)
{
sensor0 = analogRead(analog0);
pot0holder = sensor0;
sensor1 = analogRead(analog1);
pot1holder = sensor1;
i += 1;
String potcolumn = String(pot0holder) + "." + String(pot1holder) + "." + String(i) + "|" + String(int(pot0holder)+30) + "." + String(int(pot1holder)+30) + "." + String(i) + "|" + String(int(pot0holder)+60) + "." + String(int(pot1holder)+60) + "." + String(i) + "|" + String(int(pot0holder)+90) + "." + String(int(pot1holder)+90) + "." + String(i);
Serial.println(potcolumn);
SensorMillis += SensorValMillis;
}
}
void recvWithStartEndMarkers()
{
static boolean recvInProgress = false; //creates variable visible to only one function with boolean
static byte ndx = 0;
char startMarker = '<'; //sets begin condition
char endMarker = '>'; //sets end condition
char rc; //sets variable type to char
while (Serial.available() > 0 && newData == false) {
rc = Serial.read(); //sets rc equal to serial value
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
void commands()
{
if (newData == true)
{
if (receivedChars[0] == 'T')
{
PrintValMillis = atoi(&receivedChars[1]); //atoi -> Converting strings to integer
}
else if (receivedChars[0] == 'S')
{
cycles = atoi(&receivedChars[1]);
i = 0;
}
else if (receivedChars[0] == 'L')
{
val = atoi(&receivedChars[1]);
i = 0;
}
}
newData = false;
}
Thanks in advance for any help or advice any one has.
So your reading process takes most of the time. I would put the reading in a separate task and do the evaluation/splitting of the data in the main (drawing)-process. Unfortunately, I am not a tkinter user, so I have written this without any special gui-framework. But I think you can adapt this to your needs.
That would look like that:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import multiprocessing as mp
import time
# global variables
fig = plt.figure(1)
# first sub-plot
ax1 = fig.add_subplot(211)
line1, = ax1.plot([], [], lw=2)
ax1.grid()
xdata1, ydata1 = [], []
# second sub-plot
ax2 = fig.add_subplot(212)
line2, = ax2.plot([], [], lw=2)
ax2.grid()
xdata2, ydata2 = [], []
# the multiprocessing queue
q = mp.Queue()
# data generator in separate process
# here would be your arduino data reader
def dataGen(output):
for x in range(50):
output.put((x, np.sin(x)))
# update first subplot
def update1(data):
# update the data
t, y = data
xdata1.append(t)
ydata1.append(y)
xmin, xmax = ax1.get_xlim()
ymin, ymax = ax1.get_ylim()
if t >= xmax:
ax1.set_xlim(xmin, 2*xmax)
if y >= ymax:
ax1.set_ylim(ymin, 2*ymax)
if y <= ymin:
ax1.set_ylim(2*ymin, ymax)
line1.set_data(xdata1, ydata1)
return line1,
# update second subplot
def update2(data):
# update the data
t, y = data
xdata2.append(t)
ydata2.append(y)
xmin, xmax = ax2.get_xlim()
ymin, ymax = ax2.get_ylim()
if t >= xmax:
ax2.set_xlim(xmin, 2*xmax)
if y >= ymax:
ax2.set_ylim(ymin, 2*ymax)
if y <= ymin:
ax2.set_ylim(2*ymin, ymax)
line2.set_data(xdata2, ydata2)
return line2,
# called at each drawing frame
def run(data):
# get data from queue, which is filled in separate process, blocks until
# data is available
data = q.get(block=True, timeout=.5)
# put here your variable separation
data1 = (2*data[0], 3*data[1])
data2 = (data[0], data[1])
#provide the data to the plots
a = update1(data1)
b = update2(data2)
fig.canvas.draw()
return a+b
if __name__ == "__main__":
# count of reader processes
n_proc = 1
# setup workers
pool = [mp.Process(target=dataGen, args=(q,)) for x in range(n_proc)]
for p in pool:
p.daemon = True
p.start()
# wait a few sec for the process to become alive
time.sleep(3)
# start your drawing
ani = animation.FuncAnimation(fig, run, frames=60, blit=True, interval=10,
repeat=False)
plt.show()
print('done')
My question is very similar with yours.
I need to get data from a profi-bus network every 80ms, and I want the data to be plotted while sampling.
I used multiprocessing to solve the problem.The Pipe was used for communication between two processes.
When the Plotter gets data from Collector, and it is going to plot something, the Plotter will send a message to the Collector. and then the Collector will stop sending the data and put the data into a list.
when plotter done its job, it tells the collector that 'now you can send data', the collector then send the data and clear the list.
import time
import numpy as np
from matplotlib import pyplot as plt
import multiprocessing
from multiprocessing import Process, Pipe
from random import random
class DataGennerator(object):
"""docstring for DataGennerator"""
def __init__(self, data_pipe):
super(DataGennerator, self).__init__()
print('Data Gennerator Init...')
self.data_buffer = []
self.t = 0
self.start_time = 0
self.data_pipe = data_pipe
self.plot_inprogess = False
self.data_ready = False
def run(self):
self.start_time = time.time()
for i in range(0, 400):
self.loop_cycle()
print('Total Time:', time.time()-self.start_time)
print('Run completion......')
def loop_cycle(self):
self.t = time.time()-self.start_time
new_data = [time.time()-self.start_time, np.sin(self.t), np.cos(2*self.t), np.cos(self.t*4), random()]
self.send_data(new_data)
time.sleep(0.08)
def send_data(self, new_data):
if self.plot_inprogess or not self.data_ready:
self.data_buffer.append(new_data)
self.data_ready = True
# Wait 1ms to read plotter's msg
if self.data_pipe.poll(0.0001):
self.plot_inprogess = self.data_pipe.recv()
else:
self.data_pipe.send(self.data_buffer)
self.data_buffer = []
self.data_ready = False
# Function to collect data by using DataGennerator
def get_data(data_pipe):
dg = DataGennerator(data_pipe)
dg.run()
data_pipe.send('EXIT')
print('>>> Finished')
# use plotter_pipe to communicate with data collector
# and when get data from the collector, updata the figure
def updata_plot(plotter_pipe, plot_inprogess=True):
plot_inprogess = True
fig, ax = plt.subplots(nrows=4, ncols=1, figsize=(6,8), sharex=True)
fig.set_tight_layout(True)
styles = ['rs-', 'gs-', 'bs-', 'ro-', 'go-', 'bo-']*10
lines = []
for index, name in enumerate(['sin(t)', 'cos(t)', 'cos(2t)', 'random']):
line, = ax[index].plot([],[], styles[index],label=name, markersize=4, markerfacecolor='w')
ax[index].set_ylabel(name, color=styles[index][0], fontweight='bold')
lines.append(line)
ax[-1].set_xlabel('Time /s')
fig.align_ylabels(ax)
plt.ion()
plt.show(block=False)
plt.draw()
# Read the 1st data package and convert it to Numpy Array
data_array = np.array(plotter_pipe.recv())
while True:
try:
# Read data_buffer sent by Data Collector
data_buffer = plotter_pipe.recv() #[ [data1], [data2]...]
# If the DataCollector says EXIT, then break the while loop
if data_buffer == 'EXIT': break
# Raise a flag to indicate that Plot is in progress
plotter_pipe.send(True)
# Append data_buffer to Data Array
data_array = np.append(data_array, np.array(data_buffer), axis=0)
for i in range(0, 4):
lines[i].set_xdata(data_array[:,0])
lines[i].set_ydata(data_array[:,i+1])
ax[i].relim()
ax[i].autoscale_view()
fig.canvas.draw()
plt.pause(0.001)
# Tell data collector that Plot has been finished
plotter_pipe.send(False)
except Exception as e:
raise e
finally:
pass
print('>>> Stop receiving data')
data_content = '\n'.join([', '.join(map(str,data_line)) for data_line in data_array])
with open('data.txt', 'w', encoding='UTF-8') as f:
f.write('time, xx, yy, zz, bb\n')
f.writelines(data_content)
plt.show(block=True)
if __name__ == '__main__':
plot_inprogess = True
data_pipe, plotter_pipe = multiprocessing.Pipe(True)
P1 = Process(target=get_data , args=(data_pipe,))
P2 = Process(target=updata_plot, args=(plotter_pipe,))
P1.start()
P2.start()
P1.join()
P2.join()

Categories

Resources