I make a ‘photoplethysmograph’ with Raspberry pi(CM3+) and Maxim sensor(max30102).
I connect between Raspberry pi and Maxim sensor by I2C. I write python program. I want to display ‘photoplethysmograpy’ in canvas.
First, I am success to display that, but noise appear.(program0)
Second, I try to use digital signal processing for removing noise.
sampling frequency: 100Hz
band pass filter :0.1Hz : 10Hz
I write program with band pass filter(progmam1) But, the following error message appear and the program don't move. I want to improve program1. What should I do?
error message:
/usr/lib/python3/dist-packages/scipy/signal/signaltools.py:1344: FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array index, `arr[np.array(seq)]`, which will result either in an error or a different result.
out = out_full[ind]
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/usr/lib/python3.7/threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "/home/pi/exercize/r210210.py", line 62, in sensor
self.add_point0(self.l0,y0_digital/2000)
File "/home/pi/exercize/r210210.py", line 80, in add_point0
self.c0.coords(line, *coords)
File "/usr/lib/python3.7/tkinter/__init__.py", line 2469, in coords
self.tk.call((self._w, 'coords') + args))]
_tkinter.TclError: bad screen distance "[1.50422694e-04 1.51988575e-02 1.51988575e-02 2.08"
program:
import tkinter as tk
import threading
import time
import max30102
import scipy.signal as signal
class Test():
def __init__(self,master):
self.master = master
self.master.geometry("800x600")
self.frame = tk.Frame(self.master)
self.flag = True
self.c0 = tk.Canvas(self.frame, bg="white", widt=760, height=160)
self.c0.grid(row=0,column=0)
self.c1 = tk.Canvas(self.frame, bg="white", widt=760, height=160)
self.c1.grid(row=1,column=0)
self.buttonB = tk.Button(self.frame, text="start",command=self.measure)
self.buttonB.grid(row=2,column=0)
self.l0 = self.c0.create_line(0,80,0,80,fill="blue")
self.l1 = self.c1.create_line(0,80,0,80,fill="blue")
self.l2 = self.c0.create_line(0,80,0,80,fill="red")
self.frame.grid()
def measure(self):
th0 = threading.Thread(target=self.sensor)
if self.buttonB['text'] == "start":
self.buttonB['text'] = "stop"
self.flag = True
th0.start()
else:
self.buttonB['text'] = "start"
self.flag = False
def sensor(self):
m = max30102.MAX30102()
a,b = signal.buttord([0.002,0.2],[0.001,0.3],3,40)
y0 = []
y1 = []
while self.flag:
red, ir = m.read_fifo()
print('RED'+str(red))
print('IR'+str(ir))
#self.add_point0(self.l0, (red/2000))
#self.add_point1(self.l1, (ir/2000))
y0.append(red)
y1.append(ir)
if len(y0) >= 100:
y0_digital = signal.lfilter(b,a,y0)
y1_digital = signal.lfilter(b,a,y1)
self.add_point0(self.l0,y0_digital/2000)
self.add_point1(self.l1.y1_digital/2000)
self.c0.xview_moveto(1.0)
self.c1.xview_moveto(1.0)
y0.pop(0)
y1.pop(0)
time.sleep(0.01)
m.shutdown()
def add_point0(self, line, y):
coords = self.c0.coords(line)
x = coords[-2] + 1
coords.append(x)
coords.append(y)
coords = coords[-1500:]
self.c0.coords(line, *coords)
self.c0.configure(scrollregion=self.c0.bbox("all"))
def add_point1(self, line, y):
coords = self.c1.coords(line)
x = coords[-2] + 1
coords.append(x)
coords.append(y)
coords = coords[-1600:]
self.c1.coords(line, *coords)
self.c1.configure(scrollregion=self.c1.bbox("all"))
def main():
root = tk.Tk()
app = Test(root)
root.mainloop()
if __name__ == '__main__':
main()
Related
I'm trying to create a tkinter GUI that presents the 10 processes that are taking up the cpu, refreshing it every 2 seconds, similar to top, on the linux command line. My code is:
import time
import threading
import logging
import psutil
from functools import cmp_to_key
from tkinter import *
import tkinter.scrolledtext as ScrolledText
class TextHandler(logging.Handler):
def __init__(self, text):
logging.Handler.__init__(self)
self.text = text
def emit(self, record):
msg = self.format(record)
def append():
self.text.configure(state='normal')
self.text.insert(END, msg + '\n')
self.text.configure(state='disabled')
# Autoscroll to the bottom
self.text.yview(END)
# This is necessary because we can't modify the Text from other threads
self.text.after(0, append)
class myGUI(Frame):
def __init__(self):
self.window = Tk()
self.window.title("TOP GUI")
self.window.configure(bg='#999999')
self.window.minsize(width=400, height=400)
self.window.resizable(0, 0)
self.lable_title = Label(self.window,
text=" Table of Processes ",
font=("Arial", 20, "bold"),
bg='#4F4F4F', fg='#E6BA00', highlightthickness=2)
self.lable_title.pack(pady=10)
self.frame_label1 = Label(self.window,
text='\n Below are listed the 10 processes with the highest \n'
+ 'CPU consumption, with 5 second refresh. \n',
bg='#E6BA00',
highlightthickness=0,
width=43,
borderwidth=2,
relief='ridge')
self.frame_label1.pack(pady=20)
self.frame_top_message = Frame(self.window, bg='#999999')
self.frame_botao_go = Frame(self.window, bg='#999999')
self.frame_top_message.pack(pady=20)
self.frame_botao_go.pack(pady=20)
self.button_completed = Button(self.frame_botao_go,
font='Arial 14 bold',
text='GO',
width=10,
command=self.window.destroy)
self.button_completed.pack(side='left', padx=50)
self.button_completed.configure(bg='#E6BA00')
# Add text widget to display logging info
st = ScrolledText.ScrolledText(self.frame_top_message)
st.configure(font='TkFixedFont',
width=50,
height=15)
st.pack(padx=30)
# Create textLogger
text_handler = TextHandler(st)
# Logging configuration
logging.basicConfig(filename='test.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s')
# Add the handler to logger
logger = logging.getLogger()
logger.addHandler(text_handler)
trheading()
self.window.mainloop()
def trheading():
t2 = threading.Thread(target=worker, args=[])
t2.start()
def worker():
def cmpCpu(a, b):
a = a['cpu']
b = b['cpu']
if a > b:
return -1
elif a == b:
return 0
else:
return 1
while True:
timestamp = time.asctime()
logging.info(timestamp)
# Collect information for each process
processes = []
for proc in psutil.process_iter(attrs=['name', 'cpu_percent']):
processes.append({'name': proc.info['name'], 'cpu': proc.info['cpu_percent']})
# Sort by cpu usage
logging.info("CPU:")
processes.sort(key=cmp_to_key(cmpCpu))
for i in range(10):
info = processes[i]
info = info['name'] + ", " + str(info['cpu']) + "%"
logging.info(info)
logging.info("\n")
time.sleep(2)
t1 = threading.Thread(target=myGUI, args=[])
t1.start()
It will be used as a module of another larger program and will allow the user to follow a series of processes launched through subprocess.run.
It was written by putting together several examples from the internet. It works very well, but when I click the GO button I get the error message:
Exception in thread Thread-2:
Traceback (most recent call last):
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/threading.py", line 973, in _bootstrap_inner
self.run()
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/threading.py", line 910, in run
self._target(*self._args, **self._kwargs)
File "/home/arymaia/PycharmProjects/TopIso3D_Viewer_vbeta/Table_of_Processes_2.py", line 116, in worker
logging.info(timestamp)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/logging/__init__.py", line 2097, in info
root.info(msg, *args, **kwargs)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/logging/__init__.py", line 1446, in info
self._log(INFO, msg, args, **kwargs)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/logging/__init__.py", line 1589, in _log
self.handle(record)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/logging/__init__.py", line 1599, in handle
self.callHandlers(record)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/logging/__init__.py", line 1661, in callHandlers
hdlr.handle(record)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/logging/__init__.py", line 952, in handle
self.emit(record)
File "/home/arymaia/PycharmProjects/TopIso3D_Viewer_vbeta/Table_of_Processes_2.py", line 27, in emit
self.text.after(0, append)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/tkinter/__init__.py", line 821, in after
name = self._register(callit)
File "/home/arymaia/.pyenv/versions/3.9-dev/lib/python3.9/tkinter/__init__.py", line 1528, in _register
self.tk.createcommand(name, f)
RuntimeError: main thread is not in main loop
Tcl_AsyncDelete: async handler deleted by the wrong thread
I researched several answers that explain that tkinter has limitations with the use of trheading, but what I found different was that the code I made works without error, until the moment of being closed.
Could someone explain to me why this is and how I can solve this problem?
Alrighty so this is the error I get:
AttributeError: 'DES' object has no attribute 'summary_output'
So this is what I am trying to do.
When I am on this frame, I am creating a text variable that is then sent to a set class.
class upload_csv(Frame):
def __init__(self, master):
self.master = master
self.frame = tk.Frame(self.master, width=250, height=160, bg='white')
self.upload_csv_btn = Button(
self.frame,
text="Add Data Source",
fg="DodgerBlue4",
font=("Graph Type", 15),
height=1, width=20,
borderwidth=2,
relief="groove",
command=self.upload)
self.upload_csv_btn.place(x=10, y=10)
self.frame.pack()
def upload(self):
global text
self.xvalues = []
self.yvalues = []
self.xyvalues = []
self.header = []
filename = filedialog.askopenfilename()
if len(filename) != 0:
print('Selected:', filename)
with open(filename) as file:
csvreader = csv.reader(file)
self.header.append(next(csvreader))
for row in csvreader:
if len(row) == 3:
self.xvalues.append(int(row[0]))
self.yvalues.append(int(row[1]))
self.xyvalues.append(int(row[2]))
text = (
self.header[0][0]+ ": " + str(self.xvalues).replace('[','').replace(']','') +
"\n\n" + self.header[0][1] + ": " + str(self.yvalues).replace('[','').replace(']','') +
"\n\n" + self.header[0][2] + ": " + str(self.xyvalues).replace('[','').replace(']',''))
elif len(row) == 2:
self.xvalues.append(row[0])
self.yvalues.append(row[1])
text = (
self.header[0][0] + ": " + str(self.xvalues).replace('[','').replace(']','') +
"\n\n" + self.header[0][1] + ": " + str(self.yvalues).replace('[','').replace(']',''))
# -------------------------------------------------------------------------
s = Set(text)
s.set_summary()
#-----------------------------------------------------------------------
Using the upload class, I am sending the variable by calling the set class, and calling the set_summary method. With this set class, I am setting the string as a an object item, that is then send to my DES class. I want this item to be set on a tk textbox element as a summary. I receive the text fine in the DES class, but I get the following error when trying to modify the summary element.
The error I get:
Traceback (most recent call last):
File "C:\Users\***\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "C:\Users\***\Documents\Workspace\***\***\view\upload_csv.py", line 115, in upload
s.set_summary()
File "C:\Users\***\Documents\Workspace\***\***\view\Set.py", line 14, in set_summary
s.set_summary_text()
File "C:\Users\***\Documents\Workspace\***\***\view\test.py", line 164, in set_summary_text
print(self.summary_output)
AttributeError: 'DES' object has no attribute 'summary_output'
My set class:
class Set:
def __init__ (self, summary):
self.summary = summary
def set_summary(self):
print(self.summary)
s = DES(self.summary)
s.set_summary_text()
My DES Class:
class DES(Frame):
def __init__(self, summary):
self.summary = summary
def createFrame(self, master):
self.frame = tk.Frame(master, width=750, height=968,bg='white')
self.summary_output = tk.Text(
self.frame,
height=8,
width=78,
bg="gray95",
borderwidth=2,
relief="groove",
font=("Arial", 12))
self.summary_output.configure(state='disabled')
self.summary_output.place(x=20, y=610)
self.frame.pack()
def set_summary_text(self):
print(self.summary)
print(self.summary_output)
self.summary_output.configure(state='normal')
self.summary_output.delete('1.0', END) # Remote all text
self.summary_output.insert('end',self.summary)
self.summary_output.configure(state='disabled') #Make text widget read only
def main():
global root
root = tk.Tk()
# app = DES(root)
# app = DES.createFrame(root)
s = DES("")
s.createFrame(root)
root.mainloop()
if __name__ == '__main__':
main()
Edit:
So after trying the answer I got the following error, all I did was add the suggestion:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\***\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "C:\Users\***\Documents\Workspace\\***\\***\view\upload_csv.py", line 115, in upload
s.set_summary()
File "C:\Users\\***\Documents\Workspace\\***\view\Set.py", line 22, in set_summary
s.createFrame(root)
File "C:\Users\\***\Documents\Workspace\\***\view\test.py", line 120, in createFrame
self.canvas.draw() # Create the graph canvas
File "C:\Users\\***\AppData\Local\Programs\Python\Python39\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 11, in draw
self._master.update_idletasks()
AttributeError: 'str' object has no attribute 'update_idletasks'
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\\***\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "C:\Users\\***\AppData\Local\Programs\Python\Python39\lib\site-packages\matplotlib\backends\_backend_tk.py", line 235, in filter_destroy
self._master.update_idletasks()
AttributeError: 'str' object has no attribute 'update_idletasks'
So I remove the matplot graph and got this error:
So maybe the graph is interfering? Im not sure, I need the graph.
The summary_output in DES class, will be defined in the
createFrame method.
You first instatiated from the DES class in the Set.set_summary()
method and then called the set_summary_text() method, which it uses
the summary_output. That's not correct, since the summary_output has not been defined, yet.
You should first, call the createFrame() method to define the
summary_output attribute and then call the set_summary_text() to
use summary_output.
Do something like this, in the Set class:
class Set:
def __init__ (self, summary):
self.summary = summary
def set_summary(self):
global root
print(self.summary)
s = DES(self.summary)
s.createFrame(root)
s.set_summary_text()
Or do whatever you think it's best for you, but you should define the summary_output first, and then print or use it.
I just updated my PC and when I try to run the same program I have started receiving this issue. Earlier it was running perfectly fine. I am using anaconda with python 3.7.6. I tried to look up the details but I am not able to sought it out.
When I try to run my program, I receive:
runfile('C:/Users/Namrata/Desktop/untitled0.py', wdir='C:/Users/Namrata/Desktop')
Traceback (most recent call last):
File "C:\Users\Namrata\anaconda3\lib\ctypes\__init__.py", line 121, in WINFUNCTYPE
return _win_functype_cache[(restype, argtypes, flags)]
KeyError: (<class 'ctypes.HRESULT'>, (<class 'comtypes.automation.tagVARIANT'>, <class 'ctypes.wintypes.VARIANT_BOOL'>, <class 'ctypes.wintypes.VARIANT_BOOL'>), 0)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\Namrata\Desktop\untitled0.py", line 103, in <module>
app = MyApp()
File "C:\Users\Namrata\Desktop\untitled0.py", line 53, in __init__
self.gd = wx.lib.activex.ActiveXCtrl(p, 'DATARAYOCX.GetDataCtrl.1')
File "C:\Users\Namrata\anaconda3\lib\site-packages\wx\lib\activex.py", line 101, in __init__
self._ax = cc.GetBestInterface(unknown)
File "C:\Users\Namrata\anaconda3\lib\site-packages\comtypes\client\__init__.py", line 110, in GetBestInterface
mod = GetModule(tlib)
File "C:\Users\Namrata\anaconda3\lib\site-packages\comtypes\client\_generate.py", line 110, in GetModule
mod = _CreateWrapper(tlib, pathname)
File "C:\Users\Namrata\anaconda3\lib\site-packages\comtypes\client\_generate.py", line 184, in _CreateWrapper
mod = _my_import(fullname)
File "C:\Users\Namrata\anaconda3\lib\site-packages\comtypes\client\_generate.py", line 24, in _my_import
return __import__(fullname, globals(), locals(), ['DUMMY'])
File "C:\Users\Namrata\anaconda3\lib\site-packages\comtypes\gen\_EAB22AC0_30C1_11CF_A7EB_0000C05BAE0B_0_1_1.py", line 401, in <module>
( ['out', 'retval'], POINTER(VARIANT_BOOL), 'pfEnabled' )),
File "C:\Users\Namrata\anaconda3\lib\site-packages\comtypes\__init__.py", line 329, in __setattr__
self._make_methods(value)
File "C:\Users\Namrata\anaconda3\lib\site-packages\comtypes\__init__.py", line 698, in _make_methods
prototype = WINFUNCTYPE(restype, *argtypes)
File "C:\Users\Namrata\anaconda3\lib\ctypes\__init__.py", line 123, in WINFUNCTYPE
class WinFunctionType(_CFuncPtr):
The code is
import wx.lib.activex
import csv
import comtypes.client
class EventSink(object):
def __init__(self, frame):
self.counter = 0
self.frame = frame
def DataReady(self):
self.counter +=1
self.frame.Title= "DataReady fired {0} times".format(self.counter)
class MyApp( wx.App ):
def OnClick(self,e):
rb_selection = self.rb.GetStringSelection()
if rb_selection == "WinCam":
data = self.gd.ctrl.GetWinCamDataAsVariant()
data = [[x] for x in data]
else:
p_selection = self.cb.GetStringSelection()
if p_selection == "Profile_X":
data = self.px.ctrl.GetProfileDataAsVariant()
data = [[x] for x in data]#csv.writerows accepts a list of rows where each row is a list, a list of lists
elif p_selection == "Profile_Y":
data = self.py.ctrl.GetProfileDataAsVariant()
data = [[x] for x in data]
else:
datax = self.px.ctrl.GetProfileDataAsVariant()
datay = self.py.ctrl.GetProfileDataAsVariant()
data = [list(row) for row in zip(datax,datay)]#Makes a list of lists; X1 with Y1 in a list, X2 with Y2 in a list etc...
filename = self.ti.Value
with open(filename, 'wb') as fp:
w = csv.writer(fp, delimiter=',')
w.writerows(data)
def __init__( self, redirect=False, filename=None ):
wx.App.__init__( self, redirect, filename )
self.frame = wx.Frame( parent=None, id=wx.ID_ANY,size=(1000,760), title='Python Interface to DataRay')
#Panel
p = wx.Panel(self.frame, wx.ID_ANY)
#Get Data
self.gd = wx.lib.activex.ActiveXCtrl(p, 'DATARAYOCX.GetDataCtrl.1')
#The methods of the object are available through the ctrl property of the item
self.gd.ctrl.StartDriver()
self.counter = 0
sink = EventSink(self.frame)
self.sink = comtypes.client.GetEvents(self.gd.ctrl, sink)
#Button Panel
bp = wx.Panel(parent=self.frame, id=wx.ID_ANY, size=(215, 250))
b1 = wx.lib.activex.ActiveXCtrl(parent=bp,size=(200,50), pos=(1, 0),axID='DATARAYOCX.ButtonCtrl.1')
b1.ctrl.ButtonID =297 #Id's for some ActiveX controls must be set
b2 = wx.lib.activex.ActiveXCtrl(parent=bp,size=(100,25), pos=(5, 55),axID='DATARAYOCX.ButtonCtrl.1')
b2.ctrl.ButtonID =171
b3 = wx.lib.activex.ActiveXCtrl(parent=bp,size=(100,25), pos=(110,55),axID='DATARAYOCX.ButtonCtrl.1')
b3.ctrl.ButtonID =172
b4 = wx.lib.activex.ActiveXCtrl(parent=bp,size=(100,25), pos=(5, 85),axID='DATARAYOCX.ButtonCtrl.1')
b4.ctrl.ButtonID =177
b4 = wx.lib.activex.ActiveXCtrl(parent=bp,size=(100,25), pos=(110, 85),axID='DATARAYOCX.ButtonCtrl.1')
b4.ctrl.ButtonID =179
#Custom controls
t = wx.StaticText(bp, label="File:", pos=(5, 115))
self.ti = wx.TextCtrl(bp, value="C:\\Users\\Public\\Documents\\output.csv", pos=(30, 115), size=(170, -1))
self.rb = wx.RadioBox(bp, label="Data:", pos=(5, 140), choices=["Profile", "WinCam"])
self.cb = wx.ComboBox(bp, pos=(5,200), choices=[ "Profile_X", "Profile_Y", "Both"])
self.cb.SetSelection(0)
myb = wx.Button(bp, label="Write", pos=(5,225))
myb.Bind(wx.EVT_BUTTON, self.OnClick)
#Pictures
pic = wx.lib.activex.ActiveXCtrl(parent=self.frame,size=(250,250),axID='DATARAYOCX.CCDimageCtrl.1')
tpic = wx.lib.activex.ActiveXCtrl(parent=self.frame,size=(250,250), axID='DATARAYOCX.ThreeDviewCtrl.1')
palette = wx.lib.activex.ActiveXCtrl(parent=self.frame,size=(10,250), axID='DATARAYOCX.PaletteBarCtrl.1')
#Profiles
self.px = wx.lib.activex.ActiveXCtrl(parent=self.frame,size=(300,200),axID='DATARAYOCX.ProfilesCtrl.1')
self.px.ctrl.ProfileID=22
self.py = wx.lib.activex.ActiveXCtrl(parent=self.frame,size=(300,200),axID='DATARAYOCX.ProfilesCtrl.1')
self.py.ctrl.ProfileID = 23
#Formatting
row1 = wx.BoxSizer(wx.HORIZONTAL)
row1.Add(window=bp,flag=wx.RIGHT, border=10)
row1.Add(pic)
row1.Add(window=tpic, flag=wx.LEFT, border=10)
row2 = wx.BoxSizer(wx.HORIZONTAL)
row2.Add(self.px, 0, wx.RIGHT, 100)# Arguments: item, proportion, flags, border
row2.Add(self.py)
col1 = wx.BoxSizer(wx.VERTICAL)
col1.Add(sizer=row1, flag=wx.BOTTOM, border=10)
col1.Add(sizer=row2, flag=wx.ALIGN_CENTER_HORIZONTAL)
self.frame.SetSizer(col1)
self.frame.Show()
if __name__ == "__main__":
app = MyApp()
app.MainLoop()
Thanks for the help in advance!
I have a piece of toy code which does some dummy work to test parallelization. The code works fine as it is, but it fails if I try to import a class from another file. It gives me the error BrokenProcessPool: A process in the process pool was terminated abruptly while the future was running or pending.
#from Geometry import * <- this line causes the code to break
import concurrent.futures
import itertools
import random
import time
class ConProc:
def dummy(self, param):
time.sleep(random.random() * 3) # simulate a longer job
return param[0] * param[1]
def main(self):
ht_iterator = range(4)
wt_iterator = range(5)
paramlist = list(itertools.product(ht_iterator, wt_iterator))
with concurrent.futures.ProcessPoolExecutor() as executor:
ret = executor.map(self.dummy, paramlist)
for result in ret:
print(result)
if __name__ == '__main__':
cp = ConProc()
cp.main()
Contents of Geometry.py-
import math
import numpy as np
class vector(np.ndarray):
def __new__(cls, input_array):
obj = np.asarray(input_array).view(cls)
return obj
def __array_finalize__(self, obj):
if obj is None: return
class ray(vector):
pass
class sphere:
def __init__(self, center, radius, material):
self.center = center
self.radius = radius
self.material = material
def intersects(self, ray, ray_direction):
# import pdb; pdb.set_trace()
sphere_to_ray = ray - self.center
b = np.dot(2*ray_direction, sphere_to_ray)
c = np.dot(sphere_to_ray, sphere_to_ray) - self.radius*self.radius
disc = b * b - 4 * c
if disc >= 0:
dist = (-b - math.sqrt(disc)) / 2
if dist > 0:
return dist
return None
def normal(self, hit_pos):
return (hit_pos - self.center) / np.linalg.norm(hit_pos - self.center)
I find this problem puzzling because this error occurs even if I don't actually use anything from Geometry.
Sometimes I also get this error BrokenProcessPool: A child process terminated abruptly, the process pool is not usable anymore
Additional Info:
Stack-trace -
Traceback (most recent call last):
File "C:\Users\test_conc.py", line 42, in <module>
test = cp.main()
File "C:\Users\test_conc.py", line 35, in main
for result in ret:
File "C:\ProgramData\Anaconda3\lib\concurrent\futures\process.py", line 476, in _chain_from_iterable_of_lists
for element in iterable:
File "C:\ProgramData\Anaconda3\lib\concurrent\futures\_base.py", line 586, in result_iterator
yield fs.pop().result()
File "C:\ProgramData\Anaconda3\lib\concurrent\futures\_base.py", line 432, in result
return self.__get_result()
File "C:\ProgramData\Anaconda3\lib\concurrent\futures\_base.py", line 384, in __get_result
raise self._exception
BrokenProcessPool: A process in the process pool was terminated abruptly while the future was running or pending.
I am writing a program in Python, using matplotlib to (among other things) run an animation showing a numerical solution to the time-dependent Schrodinger Equation.
Everything is working fine, but once an animation has finished running, I would like the window it was in to close itself. My way of doing this (shown below) works, but exceptions are thrown up which I cant seem to catch. It works fine for what I need it to do, but the error looks very messy.
I have an alternative method which works without throwing an error, but requires the user to manually close the window (unacceptable for my purposes). Can someone please point out what I am doing wrong, or suggest a better option?
A simplified version of the relevant parts of my code follows:
from matplotlib import animation as ani
from matplotlib import pyplot as plt
multiplier = 0
def get_data(): # some dummy data to animate
x = range(-10, 11)
global multiplier
y = [multiplier * i for i in x]
multiplier += 0.005
return x, y
class Schrodinger_Solver(object):
def __init__(self, xlim = (-10, 10), ylim = (-10, 10), num_frames = 200):
self.num_frames = num_frames
self.fig = plt.figure()
self.ax = self.fig.add_subplot(111, xlim = xlim, ylim = ylim)
self.p_line, = self.ax.plot([], [])
self.ani = ani.FuncAnimation(self.fig, self.animate_frame,
init_func = self.init_func,
interval = 1, frames = self.num_frames,
repeat = False, blit = True)
plt.show()
def animate_frame(self, framenum):
data = get_data()
self.p_line.set_data(data[0], data[1])
if framenum == self.num_frames - 1:
plt.close()
# closes the window when the last frame is reached,
# but exception is thrown. Comment out to avoid the error,
# but then the window needs manual closing
return self.p_line,
def init_func(self):
self.p_line.set_data([], [])
return self.p_line,
Schrodinger_Solver()
I am running Python 2.7.2 on windows 7, with matplotlib 1.1.0
Thanks in advance
EDIT:
exception and traceback as follows:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 495, in callit
func(*args)
File "C:\Python27\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 116, in _on_timer
TimerBase._on_timer(self)
File "C:\Python27\lib\site-packages\matplotlib\backend_bases.py", line 1092, in _on_timer
ret = func(*args, **kwargs)
File "C:\Python27\lib\site-packages\matplotlib\animation.py", line 315, in _step
still_going = Animation._step(self, *args)
File "C:\Python27\lib\site-packages\matplotlib\animation.py", line 177, in _step
self._draw_next_frame(framedata, self._blit)
File "C:\Python27\lib\site-packages\matplotlib\animation.py", line 197, in _draw_next_frame
self._post_draw(framedata, blit)
File "C:\Python27\lib\site-packages\matplotlib\animation.py", line 220, in _post_draw
self._blit_draw(self._drawn_artists, self._blit_cache)
File "C:\Python27\lib\site-packages\matplotlib\animation.py", line 240, in _blit_draw
ax.figure.canvas.blit(ax.bbox)
File "C:\Python27\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 244, in blit
tkagg.blit(self._tkphoto, self.renderer._renderer, bbox=bbox, colormode=2)
File "C:\Python27\lib\site-packages\matplotlib\backends\tkagg.py", line 19, in blit
tk.call("PyAggImagePhoto", photoimage, id(aggimage), colormode, id(bbox_array))
TclError: this isn't a Tk application
Traceback (most recent call last):
File "C:\Python27\quicktest.py", line 44, in <module>
Schrodinger_Solver()
File "C:\Python27\quicktest.py", line 26, in __init__
plt.show()
File "C:\Python27\lib\site-packages\matplotlib\pyplot.py", line 139, in show
_show(*args, **kw)
File "C:\Python27\lib\site-packages\matplotlib\backend_bases.py", line 109, in __call__
self.mainloop()
File "C:\Python27\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 69, in mainloop
Tk.mainloop()
File "C:\Python27\lib\lib-tk\Tkinter.py", line 325, in mainloop
_default_root.tk.mainloop(n)
AttributeError: 'NoneType' object has no attribute 'tk'
I can catch the second exception, the AttributeError, by a small change:
try: plt.show()
except AttributeError: pass
but the first part, the TclError, remains no matter what I try
I had the same problem a few minutes before... The reason was a very low interval-value in FuncAnimation. Your code tries to update the graphics evere 1 millisecond - quite fast! (1000 fps might not be needed). I tried interval=200 and the error was gone...
HTH
try with:
if framenum == self.num_frames - 1:
exit()
it works for me...
I am facing the exact same problem, and I managed to solve the issue by creating another Animation class. Essentially, I made two changes:
Write a custom class that overwrites the _stop and _step methods.
Riase an StopIteration error in the update function, instead of using plt.close. The exception will be caught and won't break the script.
Here is the code.
from matplotlib import animation as ani
from matplotlib import pyplot as plt
class FuncAnimationDisposable(ani.FuncAnimation):
def __init__(self, fig, func, **kwargs):
super().__init__(fig, func, **kwargs)
def _step(self, *args):
still_going = ani.Animation._step(self, *args)
if not still_going and self.repeat:
super()._init_draw()
self.frame_seq = self.new_frame_seq()
self.event_source.interval = self._repeat_delay
return True
elif (not still_going) and (not self.repeat):
plt.close() # this code stopped the window
return False
else:
self.event_source.interval = self._interval
return still_going
def _stop(self, *args):
# On stop we disconnect all of our events.
if self._blit:
self._fig.canvas.mpl_disconnect(self._resize_id)
self._fig.canvas.mpl_disconnect(self._close_id)
multiplier = 0
def get_data(): # some dummy data to animate
x = range(-10, 11)
global multiplier
y = [multiplier * i for i in x]
multiplier += 0.005
return x, y
class Schrodinger_Solver(object):
def __init__(self, xlim = (-10, 10), ylim = (-10, 10), num_frames = 200):
self.num_frames = num_frames
self.fig = plt.figure()
self.ax = self.fig.add_subplot(111, xlim = xlim, ylim = ylim)
self.p_line, = self.ax.plot([], [])
self.ani = FuncAnimationDisposable(self.fig, self.animate_frame,
init_func = self.init_func,
interval = 1, frames = self.num_frames,
repeat = False, blit = True)
plt.show()
def animate_frame(self, framenum):
data = get_data()
self.p_line.set_data(data[0], data[1])
if framenum == self.num_frames - 1:
raise StopIteration # instead of plt.close()
return self.p_line,
def init_func(self):
self.p_line.set_data([], [])
return self.p_line,
Schrodinger_Solver()
Schrodinger_Solver()
print(multiplier)
(The code snippet was tested with Python 3.7 and matplotlib 3.4.2.)