Updating Axis In Matplotlib Based on Dynamic Values - python

I am working on a project in which I read in values from a text file that dynamically updates with two values separated by a space. These values are taken put into a list and then both plotted with each being a point on the y-axis and time being on the x-axis. In the first set of code provided below I am able to take in the values and plot them, then save that plot as a png. However, the plot does not seem to update the time values as more data comes in. But the graph does reflect the changes in the values.
# -*- coding: utf-8 -*-
"""
Created on Mon Jul 25 11:23:14 2016
#author: aruth3
"""
import matplotlib.pyplot as plt
import sys
import time
import datetime
class reader():
"""Reads in a comma seperated txt file and stores the two strings in two variables"""
def __init__(self, file_path):
"""Initialize Reader Class"""
self.file_path = file_path
# Read File store in f -- Change the file to your file path
def read_file(self):
"""Reads in opens file, then stores it into file_string as a string"""
f = open(self.file_path)
# Read f, stores string in x
self.file_string = f.read()
def split_string(self):
"""Splits file_string into two variables and then prints them"""
# Splits string into two variables
try:
self.val1, self.val2 = self.file_string.split(' ', 1)
except ValueError:
print('Must Have Two Values Seperated By a Space in the .txt!!')
sys.exit('Terminating Program -- Contact Austin')
#print(val1) # This is where you could store each into a column on the mysql server
#print(val2)
def getVal1(self):
return self.val1
def getVal2(self):
return self.val2
read = reader('testFile.txt')
run = True
tempList = []
humList = []
numList = [] # Represents 2 Secs
my_xticks = []
i = 0
while(run):
plt.ion()
read.read_file()
read.split_string()
tempList.append(read.getVal1())
humList.append(read.getVal2())
numList.append(i)
i = i + 1
my_xticks.append(datetime.datetime.now().strftime('%I:%M'))
plt.ylim(0,125)
plt.xticks(numList,my_xticks)
plt.locator_params(axis='x',nbins=4)
plt.plot(numList,tempList, 'r', numList, humList, 'k')
plt.savefig('plot.png')
time.sleep(10) # Runs every 2 seconds
The testFile.txt has two values 100 90 and can be updated on the fly and change in the graph. But as time goes on you will notice (if you run the code) that the times are not updating.
To remedy the time not updating issue I figure that modifying the lists using pop would allow the first value to leave and then another value when it loops back around. This worked as far as the time updating was concerned, however this ended up messing up the graph:
Link To Bad Graph Image
Code:
# -*- coding: utf-8 -*-
"""
Created on Tue Aug 2 09:42:16 2016
#author: aruth3
"""
# -*- coding: utf-8 -*-
"""
Created on Mon Jul 25 11:23:14 2016
#author:
"""
import matplotlib.pyplot as plt
import sys
import time
import datetime
class reader():
"""Reads in a comma seperated txt file and stores the two strings in two variables"""
def __init__(self, file_path):
"""Initialize Reader Class"""
self.file_path = file_path
# Read File store in f -- Change the file to your file path
def read_file(self):
"""Reads in opens file, then stores it into file_string as a string"""
f = open(self.file_path)
# Read f, stores string in x
self.file_string = f.read()
def split_string(self):
"""Splits file_string into two variables and then prints them"""
# Splits string into two variables
try:
self.val1, self.val2 = self.file_string.split(' ', 1)
except ValueError:
print('Must Have Two Values Seperated By a Space in the .txt!!')
sys.exit('Terminating Program -- Contact')
#print(val1) # This is where you could store each into a column on the mysql server
#print(val2)
def getVal1(self):
return self.val1
def getVal2(self):
return self.val2
read = reader('testFile.txt')
run = True
tempList = []
humList = []
numList = [] # Represents 2 Secs
my_xticks = []
i = 0
n = 0 # DEBUG
while(run):
plt.ion()
read.read_file()
read.split_string()
if n == 4:
my_xticks.pop(0)
tempList.pop(0)
humList.pop(0)
numList = [0,1,2]
i = 3
n = 3
tempList.append(read.getVal1())
humList.append(read.getVal2())
numList.append(i)
i = i + 1
my_xticks.append(datetime.datetime.now().strftime('%I:%M:%S')) # Added seconds for debug
plt.ylim(0,125)
plt.xticks(numList,my_xticks)
plt.locator_params(axis='x',nbins=4)
plt.plot(numList,tempList, 'r', numList, humList, 'k')
plt.savefig('plot.png')
time.sleep(10) # Runs every 2 seconds
n = n + 1
print(n) # DEBUG
print(numList)# DEBUG
print('-------')# DEBUG
print(my_xticks)# DEBUG
print('-------')# DEBUG
print(tempList)# DEBUG
print('-------')# DEBUG
print(humList)# DEBUG
So my question is how can I create a graph that when new values come in it kicks out the first value in the list, thus updating the time, but also provides an accurate graph of the data without the glitching?
The pop off the list seems like a good idea but I am not sure why it is messing up the graph?
Thanks!

This question may be more appropriate at https://codereview.stackexchange.com/
Pseudo Code
plotData = []
for (1 to desired size)
plotData[i] = 0
while data
update time
plotData.push(data with time)
plotData.popTop(oldest data)
Draw plotData
end while

Related

How do I use a csv data as variables to apply it for a formula?

I'm trying to use data from a csv file ( https://www.kaggle.com/jingbinxu/sample-of-car-data ). I only need the horsepower and weight columns as variables for the equation: ( 1/4 mile et = 6.290 * (weight/hp) ** .33 ), but it won't apply it. I don't know if the storage is working or I shouldn't do it as a class. When I run the program it doesn't show any errors, but it doesn't show results either. Then I got to plot the results, but I don't think it's even calculating and storing results. Any help is appreciated. Thanks in advance.
Here's the current code i have:
import numpy as np
class car_race_analysis():
def __init__(self, filename):
import numpy as np
self.data = np.genfromtxt(filename,delimiter= ',', skip_header = 1 )
def race_stats(self,w,h):
#cars in data
cars = np.unique(self.data[:,0])
#storage for output
race_times = []
#for each car
for car in cars:
#mask
mask = self.data[:,0] == car
#get data
w = self.data[mask,12]
h = self.data[mask,18]
#apply formula
qrtr_mile = 6.290 * ( w / h ) ** .33
race_times.append(qrtr_mile)
#new atribute
self.race_times = np.array(race_times)
print(race_times)
def trend_plotter(self):
import matlib.pyplot as plt
#inputs
self.race_stats
cars = np.unique(self.data[:,0])
#plot
plt.plot(cars,self.race_times)
plt.xlabel("Car")
plt.ylabel("1/4 Mile Time")
plt.savefig("trend_plot.png")
filename = 'car_data.csv'
Two problems:
I think you meant matplotlib instead of matlib. Make sure you install it pip3 install matplotlib --user and edit your code accordingly.
Your previous code wasn't working because you weren't instantiating a class or running any methods. The only "work" your program did was to define the class and then set a filename variable.
To solve #2, replace your filename=... line with the code below.
Here's what it does:
It checks to see if the file is being run directly (i.e. from command prompt such as python3 <your_file_name>.py. If this class is being imported and used from a different python file, this code would not be executed. More reading: https://www.geeksforgeeks.org/what-does-the-if-name-main-do/
We instantiate a instance of your class and supply the filename variable since that it was your class' __init__ method expects.
We invoke the trend_plotter method on the instance of the class.
if __name__ == '__main__':
filename = 'car_data.csv'
car_analysis = car_race_analysis(filename)
car_analysis.trend_plotter()
Even with those changes, your program will not work because it has other errors. I made a guess at fixing it, which I've pasted below, but I strongly encourage you do diff my changes to understand what I altered to be sure it does what you want.
import numpy as np
import matplotlib.pyplot as plt
class car_race_analysis():
race_times = []
cars = []
def __init__(self, filename):
import numpy as np
self.data = np.genfromtxt(filename, delimiter=',', skip_header=1)
def race_stats(self, w, h):
#cars in data
self.cars = np.unique(self.data[:, 0])
# storage for output
self.race_times = []
# for each car
for car in self.cars:
# mask
mask = self.data[:, 0] == car
# get data
w = self.data[mask, 12]
h = self.data[mask, 18]
# apply formula
qrtr_mile = 6.290 * (w / h) ** .33
self.race_times.append(qrtr_mile)
# new atribute
self.race_times = np.array(self.race_times)
def trend_plotter(self):
# inputs
self.race_stats(len(self.cars), len(self.race_times))
# plot
plt.plot(self.cars, self.race_times)
plt.xlabel("Car")
plt.ylabel("1/4 Mile Time")
plt.savefig("trend_plot.png")
plt.show()
if __name__ == '__main__':
filename = 'car_data.csv'
car_analysis = car_race_analysis(filename)
car_analysis.trend_plotter()

Python only prints to one cell in a csv

I am trying to make a print button for a GUI I am making. Right now when I click the print button it will store all the data to one cell for each variable I am trying to print. Right now I am trying to print the time, rpms, torque, and horsepower. It will give me each of those in their own separate cell, but it will not start a new row. With in this cell the format is: [1,2,3,4,5,...]. The brackets are in the cells as well. I would like for them to be separated into rows that way the user of the GUI can take the data for post processing. What I have mostly found on this matter is people are trying to get words into different cells and I know that characters act differently than numbers, pr that people want the values to be in a single cell, not the opposite like in my case.
What I have right now is that the print button will print a file with a unique time stamp. That way the users can keep this data for safe keeping.
Thank You in advance!
"""
SCSU DYNO GUI PROGRAM
created 11/10/2017
"""
import sys
import time
from time import gmtime, localtime, strftime
import csv
import numpy as np
import warnings
import serial
import serial.tools.list_ports
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QThread,QTimer, pyqtSignal
from PyQt5.QtWidgets import QMessageBox,QWidget, QApplication,QHBoxLayout
from PyQt5.QtGui import QColor
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
import random
from DynoTest1 import Ui_DynoTest1
__author__ = 'Matt Munn'
pg.setConfigOption('background', None)
pg.setConfigOption('foreground', 'k')
class GetData(QThread):
dataChanged = pyqtSignal(float, float, float, float, float, float, float, float)
#Distance = 0.5 #This is dependent on the lever arm.
def __init__(self, parent=None):
QThread.__init__(self, parent)
arduino_ports = [ # automatically searches for an Arduino and selects the port it's on
p.device
for p in serial.tools.list_ports.comports()
if 'Arduino' in p.description
]
if not arduino_ports:
raise IOError("No Arduino found - is it plugged in? If so, restart computer.")
if len(arduino_ports) > 1:
warnings.warn('Multiple Arduinos found - using the first')
self.Arduino = serial.Serial(arduino_ports[0], 9600, timeout=1)
def __del__(self): # part of the standard format of a QThread
self.wait()
def run(self): # also a required QThread function, the working part
self.Arduino.close()
self.Arduino.open()
self.Arduino.flush()
self.Arduino.reset_input_buffer()
start_time = time.time()
Distance = 1 #This is dependent on the lever arm.
Max_RPM = 0
Max_Horsepower = 0
Max_Torque = 0
#This is what does the work to get the data from the arduino and then converts it to the other needed values.
while True:
while self.Arduino.inWaiting() == 0:
pass
try:
data = self.Arduino.readline()
dataarray = data.decode().rstrip().split(',')
self.Arduino.reset_input_buffer()
Force = round(float(dataarray[0]), 3)
RPM = round(float(dataarray[1]), 0)
if Max_RPM < RPM:
Max_RPM = RPM
Torque = round(Force * Distance, 2)
if Max_Torque < Torque:
Max_Torque = Torque
Horsepower = round(Torque * RPM / 5252, 2)
if Max_Horsepower < Horsepower:
Max_Horsepower = Horsepower
Run_Time = round(time.time() - start_time, 1)
print(Force, 'Grams', ",", RPM, 'RPMs', ",", Torque, "ft-lbs", ",", Horsepower, "hp", Run_Time,
"Time Elasped")
self.dataChanged.emit(Force, RPM, Max_RPM, Torque, Max_Torque, Horsepower, Max_Horsepower, Run_Time)
except (KeyboardInterrupt, SystemExit, IndexError, ValueError):
pass
class GUI(QWidget, Ui_DynoTest1):
def __init__(self, parent=None, border = None):
# This is what is used to make the graph.
QWidget.__init__(self, parent)
self.setupUi(self)
self.thread = GetData(self)
self.thread.dataChanged.connect(self.onDataChanged)
self.thread.start()
self.rpm = []
self.torque = []
self.horse_power = []
self.time = []
self.counter = 0
layout = QHBoxLayout()
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.plot.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
self.graphicsView.setLayout(layout)
self.p1 = self.plot.plotItem
self.p1.setLabels(left='Torque (ft-lbs)', bottom= 'Time (sec)')
self.TorqueCurve = self.p1.plot()
self.TorqueCurve.setPen(pg.mkPen(QColor(0,0,0), width=2.5))
self.p2 = pg.ViewBox()
self.HorsePowerCurve = pg.PlotCurveItem()
self.HorsePowerCurve.setPen(pg.mkPen(QColor(0, 0, 255), width=2.5))
self.p2.addItem(self.HorsePowerCurve)
self.p1.scene().addItem(self.p2)
self.p1.showAxis('right')
self.p1.getAxis('right').setLabel('HorsePower', color='#0000ff')
self.p1.getAxis('right').linkToView(self.p2)
self.p1.vb.sigResized.connect(self.updateViews)
#This is where the buttons will be set up at.
self.pushButton_4.clicked.connect(self.Print_Out)
def Print_Out(self):
#This gives a unique time stamp for each file made.
outputFileName = "DynoData_#.csv"
outputFileName = outputFileName.replace("#", strftime("%Y-%m-%d_%H %M %S", localtime()))
with open(outputFileName, 'w',newline='') as outfile:
outfileWrite = csv.writer(outfile, delimiter=',')
#test = self.torque
#test2 = self.torque , self.rpm
outfileWrite.writerow([self.torque,self.horse_power,self.rpm,self.time])
def updateViews(self):
self.p2.setGeometry(self.p1.vb.sceneBoundingRect())
self.p2.linkedViewChanged(self.p1.vb, self.p2.XAxis)
def onDataChanged(self, Force, RPM, Max_RPM, Torque, Max_Torque, Horsepower, Max_Horsepower, Run_Time):
#These tell the program to display the values to the LCDs
self.lcdNumber.display(Max_RPM)
self.lcdNumber_2.display(Max_Torque)
self.lcdNumber_3.display(Max_Horsepower)
self.lcdNumber_4.display(RPM)
self.lcdNumber_5.display(Torque)
self.lcdNumber_6.display(Horsepower)
self.lcdNumber_7.display(Run_Time)
if self.counter < 50:
self.torque.append(Torque)
self.horse_power.append(Horsepower)
self.time.append(Run_Time)
self.rpm.append(RPM)
else:
self.torque = self.torque[1:] + [Torque]
self.horse_power = self.horse_power[1:] + [HorsePower]
self.time = self.time[1:] + [Run_Time]
self.rpm = self.rpm[1:] + [RPM]
self.HorsePowerCurve.setData(self.time, self.horse_power)
self.TorqueCurve.setData(np.array(self.time), self.torque)
self.updateViews()
#This is part of a standard closing script
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
Dyno = GUI()
Dyno.show()
sys.exit(app.exec_())
Since your data is in lists, you need to form rows of each instance of data items. One way is to transpose the lists with zip:
>>> hp = [1,2,3]
>>> rpm = [4,5,6]
>>> time = [7,8,9]
>>> for row in zip(hp,rpm,time):
... print(row)
...
(1, 4, 7)
(2, 5, 8)
(3, 6, 9)
Note how the first item in each list is printed, then the second, etc. You can use this to get your data into rows. Here's a standalone example:
import csv
class Test:
def __init__(self):
self.torque = [10,20,30]
self.horse_power = [100,200,300]
self.rpm = [1000,2000,3000]
self.time = [1,2,3]
def print(self):
with open('test.csv','w',newline='') as outfile:
outfileWrite = csv.writer(outfile)
outfileWrite.writerow('Torque HP RPM Time'.split())
outfileWrite.writerows(zip(self.torque,self.horse_power,self.rpm,self.time))
t = Test()
t.print()
Note writerows (plural). That expects a list of lists. writerow (singular) expects a single list and is used for a header. Output file is:
Torque,HP,RPM,Time
10,100,1000,1
20,200,2000,2
30,300,3000,3
First, calling a definition print in python is not recommended at all. Unless you do want to over-ride python 'print'. 'print_to_csv' for example.
As for the csv, you need to group your data into lists of [torque, horsepower, rpm, time] so your it will look like something like this,
data_lists = [
[torque(0), horsepower(0), rpm(0), time(0)],
[torque(1), horsepower(1), rpm(1), time(1)],
...
[torque(n), horsepower(n), rpm(n), time(n)]
]
then you will loop through this data list and print your rows one by one like so,
for d in data_datalist:
outfileWrite.writerow([d[0],d[1],d[2],d[3])
of course, many ways to structure your data, thats just an example.
Hope this helps.

Python data will not input into CSV file

I am working on a project for my shop that would allow me to track dimensions for my statistical process analysis. I have a part with 2 dimensions that I will measure 5 samples for. The dimension are OAL (Over All Length) and a Barb Diameter. I got Python and tKinter to create the window and put all the data into the correct place, but it will not export to the CSV file. It keeps telling me that the name is not defined, but the variable does exist and if I use a print command, the correct value comes up in the shell. So I know the variable exists I'm not sure if it's because I'm using tKinter or not. Any help would be appreciated.
import time
from tkinter import *
import threading
import csv
import datetime
def gui():
root = Tk()
root.title("Troy Screw Products")
titleLabel = Label(root,text="Inspection Worksheet")
partNumLabel = Label(root,text="Part #68800")
now = datetime.datetime.now()
typeLabel = ["Barb Dia","Barb Dia","OAL","Knurl","Threads","Chamfer","OD","OD","OD"]
dimLabel = [".356",".333",".437",".376","n/a",".258",".337",".321",".305"]
tolLabel = [".354/.358",".331/.335",".433/.441",".374/.378","1/4-20",".252/.263",".335/.339",".319/.323",".303/.307"]
observations = ["Obs 1","Obs 2","Obs 3","Obs 4","Obs 5"]
cd1Obs = []
Label(text="Inspection Worksheet").grid(row=0,column=0)
Label(text="Part #68800").grid(row=1,column=0)
r=0
for c in typeLabel:
Label(text=c,relief=RIDGE,width=15).grid(row=2,column=r)
r=r+1
r=0
for c in dimLabel:
Label(text=c,relief=RIDGE,width=15).grid(row=3,column=r)
r=r+1
r=0
for c in tolLabel:
Label(text=c,relief=RIDGE,width=15).grid(row=4,column=r)
r=r+1
r=0
for c in tolLabel:
Checkbutton(width=15).grid(row=5,column=r)
r=r+1
Label(text="").grid(row=6,column=1)
Label(text="").grid(row=7,column=1)
Label(text="OAL").grid(row=8,column=2)
Label(text="Barb Dia").grid(row=8,column=6)
r=9
for c in observations:
Label(text=c,width=15).grid(row=r,column=1)
Label(text=c,width=15).grid(row=r,column=5)
r=r+1
dimOneOb1=StringVar()
dimOneOb2=StringVar()
dimOneOb3=StringVar()
dimOneOb4=StringVar()
dimOneOb5=StringVar()
dimTwoOb1=StringVar()
dimTwoOb2=StringVar()
dimTwoOb3=StringVar()
dimTwoOb4=StringVar()
dimTwoOb5=StringVar()
Entry(textvariable=dimOneOb1).grid(row=9,column=2)
Entry(textvariable=dimOneOb2).grid(row=10,column=2)
Entry(textvariable=dimOneOb3).grid(row=11,column=2)
Entry(textvariable=dimOneOb4).grid(row=12,column=2)
Entry(textvariable=dimOneOb5).grid(row=13,column=2)
Entry(textvariable=dimTwoOb1).grid(row=9,column=6)
Entry(textvariable=dimTwoOb2).grid(row=10,column=6)
Entry(textvariable=dimTwoOb3).grid(row=11,column=6)
Entry(textvariable=dimTwoOb4).grid(row=12,column=6)
Entry(textvariable=dimTwoOb5).grid(row=13,column=6)
def submitEntry():
groupOal1=dimOneOb1.get()
groupOal2=dimOneOb2.get()
groupOal3=dimOneOb3.get()
groupOal4=dimOneOb4.get()
groupOal5=dimOneOb5.get()
groupBarb1=dimTwoOb1.get()
groupBarb2=dimTwoOb2.get()
groupBarb3=dimTwoOb3.get()
groupBarb4=dimTwoOb4.get()
groupBarb5=dimTwoOb5.get()
writeCsv()
Button(text="Submit",command=submitEntry).grid(row=14,column=7)
def writeCsv():
with open("CD 68800 OAL.csv", "a") as cdOal: #open file and give file variable name; r=read, w=write, a=append
cdOalWriter = csv.writer(cdOal) #Give writer a variable name
cdOalWriter.writerow([now.strftime("%Y-%m-%d %H:%M"),groupOal1,groupOal2,groupOal3,groupOal4,groupOal5])
csOal.close()
root.mainloop()
op1 = threading.Thread(target = gui)
op1.start()
Simply pass those variables in the method, writeCsv(). Because the groupOas are local to the submitEntry() function, its called function, writeCsv, does not see such objects. Also, below uses the argument unpack idiom, * of list of objects (I comment out the more verbose lines):
def submitEntry():
groupOal1=dimOneOb1.get()
groupOal2=dimOneOb2.get()
groupOal3=dimOneOb3.get()
groupOal4=dimOneOb4.get()
groupOal5=dimOneOb5.get()
group0as = [groupOal1,groupOal2,groupOal3,groupOal4,groupOal5]
groupBarb1=dimTwoOb1.get()
groupBarb2=dimTwoOb2.get()
groupBarb3=dimTwoOb3.get()
groupBarb4=dimTwoOb4.get()
groupBarb5=dimTwoOb5.get()
writeCsv(*group0as)
# writeCsv(groupOal1,groupOal2,groupOal3,groupOal4,groupOal5)
def writeCsv(a, b, c, d, e):
with open("CD 68800 OAL.csv", "a") as cdOal:
cdOalWriter = csv.writer(cdOal)
cdOalWriter.writerow([now.strftime("%Y-%m-%d %H:%M"), a, b, c, d, e])
csOal.close()

How to update HTML block in IPython

This is related to another question I posted, but is more specific (and hopefully gets more specific answers).
I am trying to display png images on an IPython notebook, and update the display as the png files are updated.
One possible solution is below. Unfortunately, my implementation does not update the file, and creates a new HTML block at the end of the old one. What I want instead, is to replace the old HTML block with the new one -i.e. replace the content only.
As example code, I have two notebooks. One notebook generates pngs and saves them in a figures directory.
import os
import glob
import time
import matplotlib.pyplot as plt
import numpy as np
for ix in range(20):
N = 50
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
area = np.pi * (15 * np.random.rand(N))**2 # 0 to 15 point radiuses
fig = plt.figure(figsize=(8,8))
plt.scatter(x, y, s=area, c=colors, alpha=0.5)
fig.savefig(os.path.join("figures", "fig1.png"), bbox_inches="tight")
plt.close(fig)
time.sleep(3)
A second notebook shows the pngs It is supposed top show a single png which updates. Instead it stacks the same png on itself, every time the png is updated.
import os
import time
from IPython.html.widgets import interact, interactive, fixed
from IPython.html import widgets
from IPython.display import clear_output, display, HTML
def get_latest_file_ts(directory="figures", file_name="fig1.png", strip_directory=True):
"""
Continuously check for modifications to the file file_name in directory. If file has been
modified after touched_on, return the Unix timestamp of the modification time.
:param directory: string / the directory where the file is
:param file_name: string / the file name
:param strip_directory: boolean / if True, strip the directory part of the file name
:return:
"""
if strip_directory:
fname = os.path.join(directory, file_name)
else:
fname = file_name
try:
return os.stat(fname).st_mtime
except:
print "FileNotFoundException: Could not find file %s" % fname
return None
def check_if_modified_file(directory="figures", file_name="fig1.png",
touched_on=1420070400, sleep_time=1, strip_directory=True):
"""
Continuously check for modifications to the file file_name in directory. If file has been
modified after touched_on, return the Unix timestamp of the modification time.
:param directory: string / the directory where the file is
:param file_name: string / the file name
:param touched_on: float / the Unix timestamp on which the file was last modified
:param sleep_time: float / wait time between interactions
:param strip_directory: boolean / if True, strip the directory part of the file name
:return:
"""
if strip_directory:
fname = os.path.join(directory, file_name)
else:
fname = file_name
while True:
try:
latest_touch = os.stat(fname).st_mtime
if latest_touch == touched_on:
time.sleep(sleep_time)
else:
return latest_touch
except:
print "FileNotFoundException: Could not find %s" % fname
return None
def show_figs(directory="figures", file_name="fig1.png"):
s = """<figure>\n\t<img src="%s" alt="The figure" width="304" height="228">\n</figure>""" % os.path.join(directory, file_name)
display(HTML(s))
timestamp = get_latest_file_ts(directory="figures", file_name="fig1.png", strip_directory=True)
show_figs(directory="figures", file_name="fig1.png")
cnt = 1
while True and cnt < 4:
timestamp = check_if_modified_file(directory="figures", file_name="fig1.png", touched_on=timestamp, sleep_time=1, strip_directory=True)
display(HTML(""))
show_figs(directory="figures", file_name="fig1.png")
time.sleep(1)
cnt += 1
(as you can see I have added upper limits on the executions of both the generator and consumer loops)
Any help on how to make widgets update HTML content would be awesome.
The problem that you only see the first image is very likely related to caching of the browser. To overcome this issue a simple solution is to add a varying query string to the image src as shown e.g. here.
Thus your show_figs method could look like:
import time
def show_figs(directory="figures", file_name="fig1.png"):
s = """<figure>\n\t<img src="{0}?{1}" alt="The figure" width="304" height="228">\n</figure>""".format(os.path.join(directory, file_name),time.time())
display(HTML(s))
In combination with the clear_output function you should be able to get your updated image.

Python: How to draw coordinates using tkinter whilst reading from a .txt

First time user. I'm a grad student at George Mason and I've been greatly aided, and impressed by the community here so I thought that I would pose a question.
I'm trying to draw points specified from a textfile using tkinter (the points are specified at the top of the code but I put them in a textfile). My assignment requires me to project the points but I want to go a step further and have them read directly from my variables so if the .txt changes they change aswell. My problem is that I'm not sure how to parse the variables to so tkinter can see them.
Here is the code:
"""
Read the following data (I put them into .txt first):
Polyline;
1: 1603714.835939442,142625.48838266544; 1603749.4678153452,142620.21243656706; 1603780.3769339535,142607.37201781105; 1603801.475846678,142582.27024446055; 1603830.4767344964,142536.14692804776;
2: 1602514.2066492266,142330.66992144473; 1602521.4127475217,142414.92978276964; 1602520.1146955898,142433.93817959353; 1602501.3840010355,142439.12358761206; 1602371.6780588734,142417.84858870413; 1602351.6610373354,142408.02716448065; 1602334.5180692307,142388.58748627454; 1602331.6999511716,142376.66073128115; 1602334.8067251327,142348.965322732; 1602338.308919772,142323.6111663878; 1602349.0226452332,142314.50124930218; 1602363.9090971674,142310.79584660195; 1602514.2066492266,142330.66992144473;
The following code define a function 'readPolylineFile' to read out data one line by one line
The readPolylineFile function will return two polylines
In addtion, try....except...finally are used to catch the exceptions
"""
import math
class Points:
def __init__(self, x=0.0, y=0.0):
self.x,self.y = x, y
class Polyline:
def __init__(self, points =[] ):
self.points = points
def getLength(self):
i = 0
length = 0.0
while i < len(self.points)-1:
length += math.sqrt((self.points[i+1].x -self.points[i].x)**2 + (self.points[i+1].y -self.points[i].y)**2 )
i += 1
return length
## function to read out data one line by one line
## return polylines list
def readPolylineFile(fileName):
## Declare variables that will be used outside of try blocks
polylines = [] ## empty polyline list to keep all polylines
f = None # empty file object
try:
f = open(fileName, 'r') ## Open the file and assign the return object to f
firstPolyLineNum = 0
index = 0
for line in f:
index += 1
if index == 1: ## Pass the first line
continue
coords = line.split(':')[1]
eachcoords = coords.split(';')
coordsLen = len(eachcoords)
points = [] ## Declare a points list to keep the points for each polyline
for i in range(coordsLen-1):
singlecoords = eachcoords[i]
xCoord = singlecoords.split(',')[0]
yCoord = singlecoords.split(',')[1]
print singlecoords
try:
point = Points(float(xCoord),float(yCoord))
points.append(point)
except ValueError:
print 'Can not convert non-number to float'
except TypeError:
print 'Object type can not conver to float'
## Create a polyline object based on the points
polyline = Polyline(points)
polylines.append(polyline)
except IOError: ##File does not exist
print 'IO Error while opening or reading the file'
finally:
if f: ## If file object exist, close the file
print 'Input .txt has been read and is now closed......'
f.close()
return polylines ## Return the polylines
polylines = readPolylineFile('F://GMU Fall 2013/GGS 650/HW6/input.txt')
try:
## Get the first polyline
polyLine1 = polylines[0]
lengthForFirstPoly = polyLine1.getLength()
print "length for first polyline (first 5 coordinates) -> ", lengthForFirstPoly
## Gets the points for second polyline
polyLine2 = polylines[1]
lengthForSecondPoly = polyLine2.getLength()
print "length for Second polyline (last 13 coordinates) -> ", lengthForSecondPoly
except:
print "error in processing polyline objects created"
from Tkinter import *
master = Tk()
master2 = Tk()
w = Canvas(master, width=800, height=600)
w.pack()
w.create_line(0, 0, 200, 100)
w = Canvas(master2, width=800, height=600)
w.pack()
w.create_line(0, 0, 200, 297)
mainloop()
All you need to do is create a method in Polyline that returns the coordinates of all of it's points as a flat list, then use that to create your line.
Here's a quick and dirty example of returning a flattened list of coordinates:
class Polyline(self):
...
def getCoordinates(self):
coords = []
for point in self.points:
coords.append(point.x)
coords.append(point.y)
return coords
Here's how to create a line on a canvas for every polyline:
for polyline in polylines:
canvas.create_line(polyline.getCoordinates())

Categories

Resources