pygame from a ssh session : how to display on attached screen? [duplicate] - ssh

I have a simple Pygame program:
#!/usr/bin/env python
import pygame
from pygame.locals import *
pygame.init()
win = pygame.display.set_mode((400,400))
pygame.display.set_caption("My first game")
But every time I try to run it, I get this:
pygame 2.0.0 (SDL 2.0.12, python 3.8.3)
Hello from the pygame community. https://www.pygame.org/contribute.html
And then nothing happens.
Why I can't run this program?

Your application works well. However, you haven't implemented an application loop:
import pygame
from pygame.locals import *
pygame.init()
win = pygame.display.set_mode((400,400))
pygame.display.set_caption("My first game")
clock = pygame.time.Clock()
run = True
while run:
# handle events
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# update game objects
# [...]
# clear display
win.fill((0, 0, 0))
# draw game objects
# [...]
# update display
pygame.display.flip()
# limit frames per second
clock.tick(60)
pygame.quit()
The typical PyGame application loop has to:
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()
limit frames per second to limit CPU usage with pygame.time.Clock.tick
repl.it/#Rabbid76/PyGame-MinimalApplicationLoop See also Event and application loop

This is interesting. Computer read your program line by line[python]. When all the line are interpreted, the program closed. To solve this problem you need to add a while loop to make sure the program will continue until you close the program.
import pygame,sys
from pygame.locals import *
pygame.init()
pygame.display.set_caption("My first game")
win = pygame.display.set_mode((400,400))
#game loop keeps the game running until you exit the game.
game_running=True
while game_running:
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
win.fill((0, 250, 154)) #Fill the pygame window with specific color. You can use hex or rgb color
pygame.display.update() #Refresh the pygame window
You can check more pygame Examples.
https://github.com/01one/Pygame-Examples
I think this will be helpful.

Related

Controlling USB Thorlabs camera via Python - OpenCV

There are several topics on this but many of them are very very old and no real solutions have been offered (or none that work for me for sure).
I am trying various libraries to get Python to read the frames of my USB camera (DCC1545M) and they all have various module or DLL import errors. I'm trying Instrumental, Thorcam API, py-harware, micromanager..
Specifically I would ideally love to get it to work with OpenCV, because of all the useful computer vision features that you can later use on the image, which I am not sure you can do with the other libraries.
However, I encounter the same issue as everyone else, in that openCV can not read the USB camera in the first place.
cap = cv2.VideoCapture(1) ## tried difference indices
cap.isOpened() ## returns FALSE
img_counter = 0
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
while True:
ret,frame = cap.read() ## returned frame is empty
cv2.imshow('preview',frame)
k = cv2.waitKey(1)
if k%256==32: # if SPACE is pressed, take image
img_name = 'frame_number_{}.png'.format(img_counter)
cv2.imwrite(img_name,frame)
print('frame taken ')
img_counter += 1
cap.release()
cv2.destroyAllWindows()
I have installed the driver from Thorlabs website and I have the uc480_64.dll. The camera is successfully located using the Instrumental() library:
from instrumental import list_instruments, instrument
from ctypes import *
paramsets = list_instruments() ## camera found
print(paramsets)
which returns
[<ParamSet[UC480_Camera] serial=b'4102675270' model=b'C1285R12M'
id=1>]
I was wondering if anyone knows if in the last couple of years openCV has managed to find a way to read USB cameras and if so, what is the way?
Or of any other reliable method, which allows further image processing on the captured frames.
PS: I posted this on superuser because apparently hardware questions are not allowed on stackoverflow, but suoeruser migrated it back here .. So apologies if it is off-topic here as well.
Can you communicate with the camera it its native software?
https://www.thorlabs.com/software_pages/ViewSoftwarePage.cfm?Code=ThorCam
Our lab is using "pylablib cam-control" to communicate with a variety of cameras (including Thorlabs USB ones): https://pylablib-cam-control.readthedocs.io/en/latest/
Or if you would prefer writing your own code, pylablib includes a class for Thorlabs USB cameras (actually has been tested with your specific camera).
https://pylablib.readthedocs.io/en/latest/devices/uc480.html#cameras-uc480
Try the following code. It works with my Thorlab DCx camera:
import cv2
import numpy as np
from instrumental.drivers.cameras import uc480
# init camera
instruments = uc480.list_instruments()
cam = uc480.UC480_Camera(instruments[0])
# params
cam.start_live_video(framerate = "10Hz")
while cam.is_open:
frame = cam.grab_image(timeout='100s', copy=True, exposure_time='10ms')
frame1 = np.stack((frame,) * 3,-1) #make frame as 1 channel image
frame1 = frame1.astype(np.uint8)
gray = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
#now u can apply opencv features
cv2.imshow('Camera', gray)
if cv2.waitKey(30) & 0xFF == ord('q'):
break
cam.close()
cv2.destroyAllWindows()

Ipywidgets not interacting in "while True" loop

1)This is the code snippet that I am trying to run.The main idea is that, I want the ipywidgets to be interactive, while the data is constantly being fetched from the data source. And the data is being updated at certain interval using the while loop.The objective is to plot the principal components interactively by changing the number of principal components(PC) to be considered, using the #interact function.
Also it runs perfectly fine without while loop, that is, when we are not considering the auto-update for the dataset, with the while loop. But when I include the while loop, it doesn't handle the interactive-ness of the widgets(that is, the interaction of the number of PC).
My feeling is that "while True" loop does not let the interaction of ipywidget to happen, due to some execution issue.
2) Also I looked into threading but i am unsure of how to use the fucntion which is in functools(select_data), be called using threading.Thread.
Any sort of help would be appreciated. Thanks
def data_import_date(start_date,end_date):
end_date1=end_date.strftime('%Y-%m-%dT%H:%M:%S')
start_date=pd.Timestamp(start_date)
end_date=pd.Timestamp(end_date1)
button=widgets.Button(description='Pull Data')
button.on_click(functools.partial(select_data,rs_=[start_date,end_date]))
vbox=widgets.VBox([button])
display(vbox,out)
def select_data(b,rs_):
# clear_output()
start_date=rs_[0]
end_date1=rs_[1]
print("Data pulling started")
with out:
clear_output()
seeq_login()
[item1,item2]=query_seeq_for_data()
i=0
while True:
end_date=end_date1.strftime('%Y-%m-%dT%H:%M:%S')
print("Start & End date: ",start_date,end_date)
if i==0:
[X_data,Y_data]=pull_data(item1,item2,start_date,end_date)
else:
[X_data_live,Y_data_live]=pull_data(item1,item2,start_date,end_date)
X_data=X_data.append(X_data_live)
Y_data=Y_data.append(Y_data_live)
print("Data pulling completed.\nNow you're ready for your analysis")
clear_output()
[X_train,X_test,Y_train,Y_test]=train_test(X_data,Y_data)
[Xp_train,components,explained_variance_ratio,_,_]=apply_PCA(X_train,X_test)
plot_PC_variance(X_data,explained_variance_ratio)
plot_PC(X_data,components)
time.sleep(20)
start_date=end_date
end_date1=end_date1+datetime.timedelta(days=1)
i+=1
a=interact(data_import_date,
start_date=widgets.DatePicker(value=pd.to_datetime(start_date)),
end_date=widgets.DatePicker(value=pd.to_datetime(end_date)))
def plot_PC(X_data,components):
Np_comp=(1,len(X_data.columns),1)
#interact
def principal_components(PC1=Np_comp,PC2=Np_comp):
fig,ax=plt.subplots(1,1,figsize=(10,10))
plt.figure(5)
print(PC1, PC2)
ax.set_xlabel("Principal Component {}".format(PC1), fontsize=14)
ax.set_ylabel("Principal Component {}".format(PC2), fontsize=14)
ax.set_title("Principal components {0} & {1}".format(PC1,PC2), fontsize=(20))
ax.scatter(components[:,PC1],components[:,PC2])
A fairly rudimentary example that shows how you can run a loop whilst polling for widget changes, but it's not really my area of expertise.
Drag the slider whilst the values are printing and you should see the printed value change to reflect current slider position.
import threading
from IPython.display import display
import ipywidgets as widgets
import time
float_val = widgets.FloatSlider()
display(float_val)
def work(progress):
total = 10
for i in range(total):
time.sleep(1)
print(float_val.value)
thread = threading.Thread(target=work, args=(progress,))
thread.start()

FuncAnimation doesn't respond when after dynamically sending data to plot to move a scatter point

So I'm using FuncAnimation from matplotlib so dynamically plot some data as it arrives from a serial port (in my project is the vehicle class from dronekit, which is displayed with the green dot), what I have basically is the animation called which every loop is receiving a new vehicle class with data changed so it can be plotted, but for some reason it plots but after a couple of seconds later after the thread of the mission(which allows the "refresh" of the vehicle data it pops up and kills python (Wheel of death), here's what I get:
I've put some tracking prints inside the function that is called when the FuncAnimation starts running, looks like this:
def droneAnimation(i, vehicle, droneScatter):
time.sleep(1)
lat = [vehicle.location.global_relative_frame.lat]
lon = [vehicle.location.global_relative_frame.lon]
alt = [vehicle.location.global_relative_frame.alt]
print("Alt received: " + str(alt))
droneScatter._offsets3d = (lat,lon,alt)
print("Changed pos")
As you can see those prints are triggered the first few seconds but still crashes after a few iterations.
The FuncAnimation is called like this:
fig,droneScatter = plotLiveSimpleFacade(vehicle,w,2)
ani = FuncAnimation(fig,droneAnimation, fargs = (vehicle,droneScatter))
plt.draw()
plt.pause(0.1)
m = threading.Thread(target=MissionStart(vehicle,hmax) , name = "MISSION")
m.start()
For reference: fig is a plt.figure(),droneScatter is just a scatter point, vehicle is the vehicle class containing the data that dynamically updates and the MissionStart thread is just a thread to make the vehicle class change overtime.
I would like to mention as well that the fig is on interactive mode on, and the axes limits are set well (I saw that when you dynamically change data but don't scale the axes may have problems) also, trying different combinations of plt.draw() and plt.plot(block = False) leads me to not plotting at all or just a blank plot.
Since I have no idea of what is causing this I'll put the dronekit tag on this and the threading to see if anyone has any idea!
I've looked onto threading with matplotlib and looks like threading with this said library it's not the best as it's not thread safe, the best bet is to look at multiprocessing with python or approaching the problem in a different manner.
You can find more information at this post

Best way to interactively draw a line on a 2D matplotlib plot

I'm a novice using matplotlib as an embedded control in my PyQt4 application to display image data. I'd like to be able to allow the user to interactively draw a line on the image by clicking and dragging. I have it working but it is so slow as to be unusable, leading me to believe I'm not going about it the correct way. The only way I can get the line to appear is by forcing the canvas to redraw each time the mouse moves (I suspect this is the cause of the slowdown).
For example, on the mouse down event I store the current coordinates and add a Line2D object to the plot as follows:
def onMouseMove(self, event):
if self.drawingLine:
self.lineStartX = event.xdata
self.lineStopX = event.xdata
self.lineStartY = event.ydata
self.lineStopY = event.ydata
self.line = Line2D([self.lineStartX, self.lineStopX], [self.lineStartY, self.lineStopY], linewidth = 1.5, color = 'r')
self.axes.add_line(self.line)
Then, in my mouse move event I redraw the line as follows:
def onMouseMove(self, event):
if self.drawingLine:
self.lineStopX = event.xdata
self.lineStopY = event.ydata
# Adjust the line to the new endpoint:
self.line.set_data([self.lineStartX, self.lineStopX], [self.lineStartY, self.lineStopY])
# Force a redraw otherwise you don't see any changes:
self.fig.canvas.draw()
As I've stated this approach is unusably slow and hence probably wrong. Can somebody please clue me in to what the proper approach is here? Thank you all in advance.
First off, you will already gain a little by using
self.fig.canvas.draw_idle()
instead of draw(). This redraws the canvas only when it's not currently beeing repainted, saving you a lot of draws.
If this is not enough, you would need to use the technique of blitting. Now since you don't have a minimal example, I will not provide any complete solution for this here, but e.g. the answer to this question, why is plotting with Matplotlib so slow?, has an example of that.
The idea is to store the background, and only redraw the part that changes (here the line).
background = fig.canvas.copy_from_bbox(ax.bbox)
# then during mouse move
fig.canvas.restore_region(background)
line.set_data(...)
ax.draw_artist(line)
fig.canvas.blit(ax.bbox)
# only after mouse has stopped moving
fig.canvas.draw_idle()
This technique is also used internally by some matplotlib widgets, e.g. matplotlib.widgets.Cursor to let the lines follow the cursor quickly.
This brings me to the last point, which is: You don't need to reinvent the wheel. There is a matplotlib.widgets.RectangleSelector, which by defaut draws a rectangle for selection. But you may use its drawtype='line' argument, to change the selection to a line, together with the argument blit=True this should already give you what you need - you will just need to add the code to finally draw a line once the selection is finished.
Note that in the newest matplotlib version, there is even a matplotlib.widgets.PolygonSelector, which may directly be what you need.
matplotlib is built to be flexible and to work with multiple different backends. It is very slow at real-time plotting. The problem is that your mouse move events are very rapid. Anything trying to keep up with the mouse movement will probably be slow. You need to call the plot less often. You can do this by checking the time in your mouse move function and trying to limit the plotting calls to whatever works.
import time
def onMouseMove(self, event):
if self.drawingLine and time.time() - last_time > 0.03: # Change the 0.03 to change how often you plot.
last_time = time.time()
...
I highly suggest pyqtgraph. pyqtgraph has built in rate limiting signals that you can work with to do this.
Below is a basic example of how you can do this.
# Change the style to look like matplotlib
pyqtgraph.setConfigOption("background", QtGui.QColor.fromRgbF(230/255, 230/255, 234/255, 255/255))
pyqtgraph.setConfigOption("background", 'w')
pyqtgraph.setConfigOption("foreground", 'k')
pyqtgraph.setConfigOption("antialias", True)
# Create the widgets and plot items
glw = pyqtgraph.GraphicsLayoutWidget()
pg = glw.addPlot(0, 0)
class MyClass(object):
...
...
def onMouseMove(self, event):
if self.drawingLine:
scene_pos = event[0]
data_pos = pg.getViewBox().mapSceneToView(scene_pos)
x, y = data_pos.x(), data_pos.y()
self.lineStopX = x
self.lineStopY = y
# Adjust the line to the new endpoint:
if not self.line:
self.line = pg.plot(x=[], y=[])
self.line.setData(x=[self.lineStartX, self.lineStopX],
y=[self.lineStartY, self.lineStopY])
mouse_move_sig = pyqtgraph.SignalProxy(pg.scene().sigMouseMoved,
rateLimit=60, slot=onMouseMove)

QThread doesn't appear to start; PyQt5, Python 2.7.9

SUMMARY
PyQt5 doesn't appear to be creating a new thread corresponding to QThread object, or I haven't established Slot/Signal linkage correctly. Please help me to isolate my problem.
I'm a relatively casual user of Python, but I've been asked to create a utility for another team that wraps some of their Python libraries (which themselves wrap C++) in a GUI. Because this utility is for another team, I can't change versions of compilers etc, or at least, not without providing a decent reason.
The utility is intended to provide an interface for debugging into some hardware that my colleagues are developing.
After examining the options, I decided to use Qt and the PyQt bindings. The steps I followed were:
Install Visual Studio 2010 SP1 (required because other team's libraries are compiled using this version of the MS compiler).
Install Python 2.7.9 (their version of Python)
Install qt-opensource-windows-x86-msvc2010-5.2.1.exe
Get source for SIP-4.18.zip and compile and install
Get source for PyQt-gpl-5.2.1.zip, compile and install
Try to build a PyQt application that wraps the other team's comms and translation libraries. Those libraries aren't asynchronous as far as I can tell, so I think that I need to separate that part of the application from the GUI.
The code that I've written produces the UI and is responsive in the sense that if I put break points in the methods that are called from the QAction objects, then those break points are appropriately triggered. My problem is that the Worker object that I create doesn't appear to move to a separate thread, (despite the call to moveToThread) because if I make the connection of type BlockingQueuedConnection instead of QueuedConnection then I get a deadlock. Breakpoints that I put on the slots in the Worker type are never triggered.
Here's the code::
import os
import sys
import time
from PyQt5.QtWidgets import QMainWindow, QTextEdit, QAction, QApplication, QStatusBar, QLabel, QWidget, QDesktopWidget, QInputDialog
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt, QThread, QObject, pyqtSignal, pyqtSlot
class Worker(QObject):
def __init__(self):
super(Worker, self).__init__()
self._isRunning = True
self._connectionId = ""
self._terminate = False
#pyqtSlot()
def cmd_start_running(self):
"""This slot is used to send a command to the HW asking for it to enter Running mode.
It will actually work by putting a command in a queue for the main_loop to get to
in its own serialised good time. All the other commands will work in a similar fashion
Up until such time as it is implemented, I will fake it."""
self._isRunning = True
pass
#pyqtSlot()
def cmd_stop_running(self):
"""This slot is used to send a command to the HW asking for it to enter Standby mode.
Up until such time as it is implemented, I will fake it."""
self._isRunning = False
#pyqtSlot()
def cmd_get_version(self):
"""This slot is used to send a command to the HW asking for its version string"""
pass
#pyqtSlot()
def cmd_terminate(self):
"""This slot is used to notify this object that it has to join the main thread."""
pass
#pyqtSlot()
def main_loop(self):
"""This slot is the main loop that is attached to the QThread object. It has sleep periods
that allow the messages on the other slots to be processed."""
while not self._terminate:
self.thread().sleep(1)
# While there is stuff on the wire, get it off, translate it, then
# signal it
# For the mean while, pretend that _isRunning corresponds to when
# RT streams will be
# being received from the HW.
if self._isRunning:
pass
# Search queue for commands, if any found, translate, then put on
# the wire
class DemoMainWindow(QMainWindow):
sgnl_get_version = pyqtSignal()
sgnl_start_running = pyqtSignal()
sgnl_stop_running = pyqtSignal()
sgnl_terminate = pyqtSignal()
def __init__(self):
super(DemoMainWindow, self).__init__()
self.initUI()
self._workerObject = Worker()
self._workerThread = QThread()
self._workerObject.moveToThread(self._workerThread)
self._workerThread.started.connect(self._workerObject.main_loop, type=Qt.QueuedConnection)
# I changed the following connection to type BlockingQueuedConnection,
# and got a Deadlock error
# reported, so I assume that there is already a problem before I get to
# this point.
# I understand that the default for 'type' (Qt.AutoConnection) is
# supposed to correctly infer that a QueuedConnection is required.
# I was getting desperate.
self.sgnl_get_version.connect(self._workerObject.cmd_get_version, type=Qt.QueuedConnection)
self.sgnl_start_running.connect(self._workerObject.cmd_start_running, type=Qt.QueuedConnection)
self.sgnl_stop_running.connect(self._workerObject.cmd_stop_running, type=Qt.QueuedConnection)
self.sgnl_terminate.connect(self._workerObject.cmd_terminate, type=Qt.QueuedConnection)
def initUI(self):
textEdit = QTextEdit()
self.setCentralWidget(textEdit)
lbl = QLabel(self.statusBar())
lbl.setText("HW Version: ")
self.statusBar().addPermanentWidget(lbl)
exitAction = QAction(QIcon('exit24.png'), 'Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')
exitAction.triggered.connect(self.close)
connectAction = QAction(QIcon('connect24.png'), 'Connect', self)
connectAction.setStatusTip('Connect to HW')
connectAction.triggered.connect(self.establishCanConnection)
enterRunningAction = QAction(QIcon('start24.png'), 'Start Running', self)
enterRunningAction.setStatusTip('Start Running')
enterRunningAction.triggered.connect(self.enterRunning)
enterStandbyAction = QAction(QIcon('stop24.png'), 'Stop Running', self)
enterStandbyAction.setStatusTip('Stop Running')
enterStandbyAction.triggered.connect(self.enterStandby)
self.statusBar()
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAction)
hwMenu = menubar.addMenu('&Hardware')
hwMenu.addAction(connectAction)
hwMenu.addAction(enterRunningAction)
hwMenu.addAction(enterStandbyAction)
toolbar = self.addToolBar('Exit')
toolbar.addAction(exitAction)
toolbar.addAction(connectAction)
toolbar.addAction(enterRunningAction)
toolbar.addAction(enterStandbyAction)
self.setGeometry(300, 300, 400, 350) # x, y, width, height
self.setWindowTitle('Demo Prog')
self.show()
def establishCanConnection(self):
iDlg = QInputDialog(self)
iDlg.setInputMode(QInputDialog.IntInput)
idInt, ok = iDlg.getInt(self, 'CAN ID Selection', 'HW ID:')
canID = '%s%d' % ('HW', idInt)
if ok:
self._workerThread.start()
pass
# this would be where the channel is established
def enterRunning(self):
self.sgnl_start_running.emit()
# this would be where the command to start running is sent from
def enterStandby(self):
self.sgnl_stop_running.emit()
# send the command to stop running
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWindow = DemoMainWindow()
sys.exit(app.exec_())
Note that the call to start the _workerThread is in the establishCanConnection method, but that shouldn't be a problem, should it?
I used the procmon utility to check if more threads are created if establishCanConnection is run, and it appears that there are more threads, but I found it hard to relate which thread (if any of them) related to the QThread object.
Don't use BlockingQueuedConnection unless you really need it. If you don't know whether you need it or not, then you don't need it.
Cross-thread signals are queued in the event-loop of the receiving thread. If that thread is running code that blocks, it won't be able to process any events. Thus, if you send a signal with BlockingQueuedConnection to a thread that is blocked, you'll get a deadlock.
Your example uses a worker object that runs a blocking while loop, so it is subject to the deadlock problem outlined above. If you want to send signals to a thread that is blocked, you will need to arrange for the blocking code to periodically allow the thread to process its events, like this:
while not self._terminate:
self.thread().sleep(1)
QApplication.processEvents()
PS:
If you want to check that the worker is running in a different thread, you can print the return value of QThread.currentThread() or QThread.currentThreadId() (these functions are static, so you don't need an instance of QThread to call them).