pylablib.devices.IMAQ.IMAQ.IMAQCamera: read_trigger method is not asserting when external trigger is pressed - python

I am working on a script which grabs frames from a c-arm camera using a PCIe-1433 frame grabber. The frames must be grabbed when a pedal is pressed down; pressing and holding the pedal results in a repeated rising voltage edge at a consistent rate until the pedal is no longer pressed. In other words, the frame grabber must be synchronized with the camera capture. I also have a working LabView block diagram which provides me the correct trigger parameters, so I know my configure_trigger_in method is set up correctly.
The issue that I keep coming up against is that the read_trigger method is not asserting when I press down the external trigger pedal. I want to make 100% sure that I am correctly setting up my trigger line code, so I can turn my attention to the hardware itself if necessary.
Here is a script which first opens the frame grabber connected to the camera, then configures the input trigger, then continuously reads the trigger line for a rising edge. When there is a rising edge, it prints "asserted". I have also set up a timer which cancels the while loop after 30 seconds.
from pylablib.devices import IMAQ
import time
# identify frame grabber
cam = IMAQ.IMAQCamera('FPD::0')
# configure trigger in with corretc parameters
cam.configure_trigger_in('ext', trig_line=0, trig_pol='high', trig_action='buffer', timeout=1000.0)
# set 30 sec timer for while loop
timeout = time.time() + 30
# while loop continuously reads trigger line
while True:
# checks trigger line value:
# if 0, then unasserted -> continue
# if not 0, then asserted -> print "asserted" then continue
while cam.read_trigger('ext', trig_line=0, trig_pol='high') == 0:
# checks timer
if time.time() > timeout:
print('timeout')
break
else:
print('asserted')
# checks timer
if time.time() > timeout:
print('timeout')
break
continue
break
cam.close()
A successful read_trigger line would print multiple "asserted" whenever the external trigger pedal is pressed. However, I get no "asserted" for the entire 30 sec timer when I am pressing the pedal.
Is there something wrong with my script's trigger setup?

Related

A confirmation message that disappears pyqt5 [duplicate]

This question already has answers here:
Equivalent to time.sleep for a PyQt application
(5 answers)
Closed 1 year ago.
I would like to display a confirmation image like below, which disappears in 2s after being launched. I can display the image but I cannot make it disappear afterwards. I tried to use a sleep (2) but in this case the image turns all black for every 2 seconds. thank you for helping me please
Your application turns black, because the event loop is not running.
Qt runs by having an event loop run forever. It waits for events and processes them as they come in the queue. The event loop is getting an event, calling your function, and waiting for your function to finish until it moves on to running the next event. Your function shows the window/widget/dialog, then sits in time.sleep for 2 seconds. While it is sitting in time.sleep the Qt Event Loop is still waiting for your function to end to process more events.
There are 3 ways to handle this situation.
QTimer (recommended for your situation).
Show your widget and tell a timer to call your function in 2 seconds.
This will make your function exit right away, so the event loop can continue processing
After 2 seconds the timer will call the close function
Thread (threads are really for I/O like TCP Sockets).
QApplication.processEvents()
Show your dialog and run a loop waiting for 2 seconds.
While the loop is running and checking if 2 seconds has passed tell the event loop to process events.
QTimer - you simply show your window then have a timer call a function to close your window.
self.widg = ...
self.widg.show()
self.widg.raise_() # if already show bring to top
def close_and_delete_widg():
self.widg.close()
self.widg.setParent(None) # Remove reference
self.widg.deleteLater()
self.widg = None # Remove python reference count.
self.tmr = QtCore.QTimer()
self.tmr.setSingleShot(True)
self.tmr.timeout.connect(close_and_delete_widg)
self.tmr.start(2000) # 2 sec
I made a library to help run things on approximate timeouts qt_thread_updater. This library works by continuously running a timer and calling function that were posted. You basically tell it to run a function, and it will run a function in the main event loop later. The delay function is not accurate. This library was made more for threading. However, it makes it so you don't need to manage your timer.
from qt_thread_updater import get_updater
self.widg = ...
self.widg.show()
self.widg.raise_() # if already show bring to top
def close_and_delete_widg():
self.widg.close()
self.widg.setParent(None) # Remove reference
self.widg.deleteLater()
self.widg = None # Remove python reference count.
get_updater().delay(2, close_and_delete_widg) # After approximately 2 seconds call
Threading - I am going to skip, because you don't need it for your use case.
QApplication.processEvents() - This is not really recommended. It can cause issues, but may still work. Essentially, the event loop is waiting for your function to finish. If you call QApplication.processEvents() you are telling your application to process more events while you are currently waiting for this event to finish.
self.widg = ...
self.widg.show()
self.widg.raise_() # if already show bring to top
start = time.time()
while (time.time() - start) <= 2: # Sec or msec?
QtCore.QApplication.processEvents() # QtCore.QApplication.instance().processEvents()
# Close and delete the widget
self.widg.close()
self.widg.deleteLater()
self.widg = None

Running complicated code inside of pySimpleGUI?

I'm trying to run some code inside of a GUI, where I run a function after I get a few text inputs. however the function I am trying to run is actually really complicated, so when it runs, it makes the entire gui freeze up for 10-15 seconds before continuing.
How can I make it so that when I hit the run button, it doesn't freeze up the entire GUI waiting for the function to complete?
I do understand that there is a way to make functions threaded, however, I don't know how to implement that?
An example of how I can wrap a function to make it a threaded one would be great.
The code below gives an example of the problem that I am dealing with.
import PySimpleGUI as sg
import time
def simple_gui():
layout = [ [sg.T('try clicking "do something" and move the window')],
[sg.Button('do something'), sg.Button('Exit')] ]
w = sg.Window('test', layout)
while True:
events, values = w.read()
if events == 'do something':
# If you hit the button "do something":
# run a function that takes 30 seconds to complete.
time.sleep(30)
if events == sg.WIN_CLOSED or events == 'Exit':
break
w.close()
simple_gui()
There are a number of examples of how you can use threads to perform "long operations" using PySimpleGUI. You'll find the demo programs located at http://Demos.PySimpleGUI.org . There are at least 6 sample programs labeled as being multi-threaded examples.
Some are also available on Trinket to run online. This one shows how to run a thread and then wait for it to complete:
https://pysimplegui.trinket.io/demo-programs#/multi-threaded/multi-threaded-long-task-simple
Here's the code that you'll find there.
#!/usr/bin/python3
import threading
import time
import PySimpleGUI as sg
"""
DESIGN PATTERN - Multithreaded Long Tasks GUI using shared global variables
Presents one method for running long-running operations in a PySimpleGUI environment.
The PySimpleGUI code, and thus the underlying GUI framework, runs as the primary, main thread
The "long work" is contained in the thread that is being started. Communicating is done (carefully) using global variables
There are 2 ways "progress" is being reported to the user.
You can simulate the 2 different scenarios that happen with worker threads.
1. If a the amount of time is known ahead of time or the work can be broken down into countable units, then a progress bar is used.
2. If a task is one long chunk of time that cannot be broken down into smaller units, then an animated GIF is shown that spins as
long as the task is running.
"""
total = 100 # number of units that are used with the progress bar
message = '' # used by thread to send back a message to the main thread
progress = 0 # current progress up to a maximum of "total"
def long_operation_thread(seconds):
"""
A worker thread that communicates with the GUI through a global message variable
This thread can block for as long as it wants and the GUI will not be affected
:param seconds: (int) How long to sleep, the ultimate blocking call
"""
global message, progress
print('Thread started - will sleep for {} seconds'.format(seconds))
for i in range(int(seconds * 10)):
time.sleep(.1) # sleep for a while
progress += total / (seconds * 10)
message = f'*** The thread says.... "I am finished" ***'
def the_gui():
"""
Starts and executes the GUI
Reads data from a global variable and displays
Returns when the user exits / closes the window
"""
global message, progress
sg.theme('Light Brown 3')
layout = [[sg.Text('Long task to perform example')],
[sg.Output(size=(80, 12))],
[sg.Text('Number of seconds your task will take'),
sg.Input(key='-SECONDS-', size=(5, 1)),
sg.Button('Do Long Task', bind_return_key=True),
sg.CBox('ONE chunk, cannot break apart', key='-ONE CHUNK-')],
[sg.Text('Work progress'), sg.ProgressBar(total, size=(20, 20), orientation='h', key='-PROG-')],
[sg.Button('Click Me'), sg.Button('Exit')], ]
window = sg.Window('Multithreaded Demonstration Window', layout)
thread = None
# --------------------- EVENT LOOP ---------------------
while True:
event, values = window.read(timeout=100)
if event in (None, 'Exit'):
break
elif event.startswith('Do') and not thread:
print('Thread Starting! Long work....sending value of {} seconds'.format(float(values['-SECONDS-'])))
thread = threading.Thread(target=long_operation_thread, args=(float(values['-SECONDS-']),), daemon=True)
thread.start()
elif event == 'Click Me':
print('Your GUI is alive and well')
if thread: # If thread is running
if values['-ONE CHUNK-']: # If one big operation, show an animated GIF
sg.popup_animated(sg.DEFAULT_BASE64_LOADING_GIF, background_color='white', transparent_color='white', time_between_frames=100)
else: # Not one big operation, so update a progress bar instead
window['-PROG-'].update_bar(progress, total)
thread.join(timeout=0)
if not thread.is_alive(): # the thread finished
print(f'message = {message}')
sg.popup_animated(None) # stop animination in case one is running
thread, message, progress = None, '', 0 # reset variables for next run
window['-PROG-'].update_bar(0,0) # clear the progress bar
window.close()
if __name__ == '__main__':
the_gui()
print('Exiting Program')

How should I properly use cv2.waitKey when wanting to start/pause a video?

I've written a small script that allows be to run/pause a video stream using OpenCV. I don't understand why I needed to use the cv2.waitkey() in the manner I did. The structure of my code is as follows:
def marker(event, x, y, flags, param):
# Method called by mouse click
global run
if event == cv2.EVENT_LBUTTONDOWN:
run = not run
...
window_name = 'Editor Window'
cv2.namedWindow(window_name)
cv2.setMouseCallback(window_name, marker)
fvs = cv2.VideoCapture(args["video"])
(grabbed, frame) = fvs.read()
while grabbed:
# grab the frame from the threaded video file stream, resize
# it, and convert it to grayscale (while still retaining 3
# channels)
if run:
# Code to display video fames ...
cv2.waitKey(1) & 0xFF # Use A
(grabbed, frame) = fvs.read()
else:
cv2.waitKey(1) & 0xFF # Use B
The code is very sensitive to the use of cv2.waitKey:
If I don't have "Use A", the window freezes, without ever showing the video. I would've expected it to run and then close very quickly. Why is this not the case?
If "Use B" is absent, execution freezes after the first mouse click. Does openCV somehow need to be waiting for a keyboard entry in order to see a mouse click? If so, why?
If "Use B" has a delay of 0 (i.e. wait indefinitely), then it only seems to see mouse click events intermittently, though sometimes I'm also periodically pressing on the space bar as I click. Why is this? Am I somehow getting 'lucky' if I give a mouse-click soon enough before (or after?) a key press? If not, why the intermittent response?
Ultimately, I don't really understand the workings of cv2.waitKey(). I would've thought it waits for the given time delay for a keyboard event and then moves on. The interaction with a mouse click even confuses me.
According to the OpenCV Documentation:
The function waitKey waits for a key event infinitely (when delay <= 0 ) or for delay milliseconds, when it is positive. Since the OS has a minimum time between switching threads, the function will not wait exactly delay ms, it will wait at least delay ms, depending on what else is running on your computer at that time. It returns the code of the pressed key or -1 if no key was pressed before the specified time had elapsed.
So you can pause by pressing the "p" button of the keyboard using the OpenCV cv2.waitKey(delay) function like this:
import cv2
cap = cv2.VideoCapture('your_video.mov')
while(True):
_, frame = cap.read()
cv2.imshow("Frame", frame)
key = cv2.waitKey(1)
if key == ord("p"):
cv2.waitKey(0)
waitKey drives the event-loop. Which is essential for things like keyboard or mouse events. Thus you always need to drive it if you expect interactive reactions.
Also, you can pull the waitKey in front of the if, and just issue it once.

Difference in output with waitKey(0) and waitKey(1)

I've just begun using the OpenCV library for Python and came across something I didn't understand.
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read() #returns ret and the frame
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
When I use cv2.waitKey(1), I get a continuous live video feed from my laptops webcam. However when I use cv2.waitKey(0), I get still images. Every time I close the window, another one pops up with another picture taken at the time.
Why does it not show as a continuous feed?
From the doc:
1.waitKey(0) will display the window infinitely until any keypress (it is suitable for image display).
2.waitKey(1) will display a frame for 1 ms, after which display will be automatically closed. Since the OS has a minimum time between switching threads, the function will not wait exactly 1 ms, it will wait at least 1 ms, depending on what else is running on your computer at that time.
So, if you use waitKey(0) you see a still image until you actually press something while for waitKey(1) the function will show a frame for at least 1 ms only.
waitKey(0) will pause your screen because it will wait infinitely for keyPress on your keyboard and will not refresh the frame(cap.read()) using your WebCam.
waitKey(1) will wait for keyPress for just 1 millisecond and it will continue to refresh and read frame from your webcam using cap.read().
More clearly, Use debugger in your code.When using waitKey(0) in the while loop, the debugger never crosses this statement and does not refresh the frame and hence the frame output seems stable.Does not move.
Where as with waitKey(1), the debugger will cross the code after pausing at
if cv2.waitKey(1) & 0xFF == ord('q')
for 1 milli second.
From the documentation you can see that cv2.waitKey(delay) waits for delay milliseconds if delay is positive but forever (waits for a key event infinitely) if it's zero or negative. That's why you see these differences in behavior.
In the case of cv2.waitKey(1) this is, in fact, negligible but its use provides the user the opportunity to press a key (the key might be caught in some next iteration but does not make a big difference).
Delay in milliseconds. 0 is the special value that means “forever”.
The function waitKey waits for a key event infinitely (when \texttt{delay}\leq 0 ) or for delay milliseconds, when it is positive. Since the OS has a minimum time between switching threads, the function will not wait exactly delay ms, it will wait at least delay ms, depending on what else is running on your computer at that time. It returns the code of the pressed key or -1 if no key was pressed before the specified time had elapsed.
Note: This function is the only method in HighGUI that can fetch and handle events, so it needs to be called periodically for normal event processing unless HighGUI is used within an environment that takes care of event processing.
Note: The function only works if there is at least one HighGUI window created and the window is active. If there are several HighGUI windows, any of them can be active
cv2.waitkey(1) is being used in while loop.It shows the output for 1msec but because of infinite while loop it is the sequence of images that are perceived by our brain as a single continuos video.
Hope this helped.
Indratej Reddy's answer is the only one to clearly explain why this works — and why no GUI events act until waitkey is called. Unclear how to handle menu/mouse events — e.g., ignores menu quit.
$ python3
>>> import cv2
>>> im = cv2.imread("/tmp/portrait.jpg")
>>> print("im =", im)
im = […]
>>> cv2.imshow("image", im)
>>> print("imshow called")
imshow called
>>> print("waitKey =", cv2.waitKey(0))
waitKey = 32
>>> print("destroyAllWindows =", cv2.destroyAllWindows())
destroyAllWindows = None
>>> print("Final waitKey 1ms =", cv2.waitKey(1))
Final waitKey 1ms = -1
>>>

How can keep a timed count of user input (from a button)?

I'm using a Raspberry Pi 2 and a breadboard to make a morse code interpreter. The circuit is a simple button that lights up an LED when pressed. How could I use functions to count how long the button is held down?
You haven't given sufficient details of your circuit to pin this down to your particular use case, so I'll suggest the following (on which I'll base my code):
Connect the LED (with series resistor) to GPIO 12
Connect a 10k resistor between GPIO 11 and the 3.3V rail (acts as a pull-up)
Connect the push-button between GPIO 11 and Ground (0V).
I'd then write the code to monitor the pin and log the time for each press into a list. You can read out the values in the same order which allows you to process the times and interpret the code from them.
import RPi.GPIO as GPIO
import time
# set up an empty list for the key presses
presses = []
# set up the GPIO pins to register the presses and control the LED
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
GPIO.setup(11, GPIO.IN)
# turn LED off initially
GPIO.output(12, False)
while True:
# wait for input to go 'low'
input_value = GPIO.input(11)
if not input_value:
# log start time and light the LED
start_time = time.time()
GPIO.output(12, True)
# wait for input to go high again
while not input_value:
input_value = GPIO.input(11)
else:
# log the time the button is un-pressed, and extinguish LED
end_time = time.time()
GPIO.output(12, False)
# store the press times in the list, as a dictionary object
presses.append({'start':start_time, 'end':end_time})
You'll finish up with a list that looks something like this:
[{start:123234234.34534, end:123234240.23482}, {start:123234289.96841, end:123234333.12345}]
The numbers you see here are in units of seconds (this is your system time, which is measured in seconds since the epoch).
You can then use a for loop to run through each item in the list, subtract each end time from the start time, and of course subtract the start of the next press from the end of the previous one, so that you can assemble characters and words based on the gaps between presses. Have fun :-)

Categories

Resources