Refocus To Terminal after Matlab Plt - python

Currently trying to pull up figures that go with a response, whenever I open the figure (plt.draw) it pans focus to the picture and the user has to click back to the terminal each time the picture is called. I am trying to get it where the figure is a background object (so it will open but it won't shift focus) or possibly manually shift the Foreground Window to the terminal or the file name the code is running on. Also trying to make it linux and windows friendly so can't be windows specific commands, but anything helps. My code is provided below:
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import warnings
warnings.filterwarnings("ignore")
def ShowImageCommon(wintitle = "", imgpath = "", imgtitle = "", imgshowdelay = 5):
ImageAddress = imgpath
ImageItself = Image.open(ImageAddress)
ImageNumpyFormat = np.asarray(ImageItself)
plt.title(imgtitle)
figure = plt.gcf()
# figure.set_visible(not figure.get_visible())
figure.canvas.set_window_title(wintitle)
axis = plt.gca()
x_axis = axis.axes.get_xaxis()
x_axis.set_visible(False)
y_axis = axis.axes.get_yaxis()
y_axis.set_visible(False)
plt.show()
return ImageNumpyFormat
def ShowImageInteractive(wintitle = "", imgpath = "", imgtitle = "", imgpause = 0):
while True:
try:
ImageNumpyFormat = ShowImageCommon(wintitle, imgpath, imgtitle)
plt.imshow(ImageNumpyFormat)
plt.draw()
plt.pause(0.1) # Window closes after specified delay in sec
return plt
except:
imgpath = input(f'Could not open image path {imgpath}, please type path here >> ')
def main():
imgpause = 0.1
wintitle = 'UIB Functional Test'
imgpath = '{path to file}/Keypad Press Sequence.png'
imgtitle = 'Keypad Press Sequence'
plt = ShowImageInteractive(wintitle, imgpath, imgtitle, imgpause)
y_n= input("is this clear? >> ") # want focus back to terminal to answer question
if __name__ == "__main__":
main()
Also any suggestions for labeling windows and opening them are greatly appreciated but again, Linux friendly!

Related

Python : how to have preview of DSLR camera

I came here as I am lost.
I have a code which basically provides a preview on screen before a picture is taken. The code runs on 2 camera (it doesn't make sense I know).
Pi camera : for preview
DSLR camera : for taking the pictures
The scripts works as expected. The issue is that the PIcamera zoom is not aligned with the DSLR.
I know it is possible to get the DSLR preview on screen which would be better. However I don't know how to do it. As I am new to python, I read as much as I could. I read solution with VLC but I didn't understand the specificities. I read the gphoto2 help but got lost in the technical parts. Hence I'd highly appreciate if someone can help me out or point me to the correct direction.
The DSLR camera is a Canon EOS D60 which should be compatible for screen preview.
I attached below the code
from picamera import PiCamera
import time
from time import sleep
import logging
import sys
import gphoto2 as gp
import locale
photonr = 1
countdown = 5
FolderRaw='/home/pi/'
def TakePicture():
global rafale
try:
rafale +=1
except Exception as e:
rafale =1
camera1 = PiCamera()
locale.setlocale(locale.LC_ALL, '')
logging.basicConfig(
format='%(levelname)s: %(name)s: %(message)s', level=logging.WARNING)
callback_obj = gp.check_result(gp.use_python_logging())
camera2 = gp.Camera()
camera2.init()
i = 1
while i < photonr+1:
preview = camera1.start_preview()
preview.fullscreen = True
picture_time = time.strftime("%Y-%m-%d")
global image
image = picture_time+ '_' + str(rafale) + '_' + str(i)
if i == 1 :
countdown2 = countdown +1
else :
countdown2 = 3
for counter in range(countdown2, 0, -1):
camera1.annotate_text = str(counter)
camera1.annotate_text_size = 120
sleep(1)
camera1.annotate_text = ''
print('Capturing image')
file_path = camera2.capture(gp.GP_CAPTURE_IMAGE)
print('Camera file path: {0}/{1}'.format(file_path.folder, file_path.name))
target = FolderRaw+image +'.jpg'
print('Copying image to', target)
camera_file = camera2.file_get(
file_path.folder, file_path.name, gp.GP_FILE_TYPE_NORMAL)
camera_file.save(target)
#camera.capture(FolderRaw+image +'.jpg')
camera1.stop_preview()
print ("Raw picture taken and saved on " + image )
i += 1
camera1.close()
camera2.exit()
TakePicture()
Thank you beforehand for any tips/direction/help

Pytesseract really slow

so I'm trying to read out text from MS Teams and use that text to make inputs on the keyboard.
Right now, I work with the threading module to have one thread for the input and one thread for the image_to_string. Following is the function for the image_to_string.
def imToString():
global message
print("Image getting read")
pytesseract.pytesseract.tesseract_cmd ='C:\\Users\\gornicec\\AppData\\Local\\Programs\\Tesseract-OCR\\tesseract.exe'
while(True):
print("preIMGgrab")
cap = ImageGrab.grab(bbox=(177, 850, 283, 881))
grayCap = cv2.cvtColor(np.array(cap), cv2.COLOR_BGR2GRAY)
print("postIMGgrab")
t = time.perf_counter()
print("preMSG" + str(t))
message = pytesseract.image_to_string(
grayCap,
lang ='deu',config='--psm 6')
print(str(message) + "was read" + str(time.perf_counter() - t))
I don't know how but it takes about 8 seconds to read an image thats 1000 pixels big. I need this to be at highest 2 seconds. I'll add the whole code at the end. If there is any way to make it faster or to do it differently please tell me so.
WHOLE CODE:
import numpy as np
import time
import pytesseract
from win32gui import GetWindowText, GetForegroundWindow
import win32api
import cv2
import pyautogui
from PIL import ImageGrab
import threading
from ahk import AHK
import keyboard
message = ""
ahk = AHK(executable_path='C:\\Program Files\\AutoHotkey\\AutoHotkey.exe')
def Controls():
global message
while True:
booleanVal = True
if booleanVal:
#imToString()
print("message")
#print("rechts" in message.lower())
#print(f'LĂ„NGE: {len(message)}')
if "vorne" in message.lower():
# Control(message, 'w')
ahk.key_press('w')
#message = ""
if "hinten" in message.lower():
# Control(message, 's')
ahk.key_press('s')
#message = ""
if "links" in message.lower():
# Control(message, 'a')
ahk.key_press('a')
#message = ""
if "rechts" in message.lower():
# Control(message, 'd')
#print("HAHAHA")
ahk.key_press('d')
#message = ""
if "greif" in message.lower():
ahk.key_press('space')
#message = ""
time.sleep(0.5)
#IMGTOSTRING---
controls = threading.Thread(target=Controls)
controls.start()
grab = threading.Thread(target=imToString)
grab.start()
pytesseract is not suit for large amount of images or images that are already in memory, its write them to a file and then pass the file path to tesseract cli, if you want to improve the performance of you script try using library that works directly with tesseract api.
like this: https://pypi.org/project/tess-py-api/

plotting multiple lines of streaming data in a bokeh server application

I'm trying to build a bokeh application with streaming data that tracks multiple "strategies" as they are generated in a prisoners-dilemma agent based model. I've run into a problem trying to get my line plots NOT to connect all the data points in one line. I put together this little demo script that replicates the issue. I've read lots of documentation on line and multi_line rendering in bokeh plots, but I just haven't found something that seems to match my simple case. You can run this code & it will automatically open a bokeh server at localhost:5004 ...
from bokeh.server.server import Server
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler
from bokeh.plotting import figure, ColumnDataSource
from bokeh.models import Button
from bokeh.layouts import column
import random
def make_document(doc):
# Create a data source
data_source = ColumnDataSource({'step': [], 'strategy': [], 'ncount': []})
# make a list of groups
strategies = ['DD', 'DC', 'CD', 'CCDD']
# Create a figure
fig = figure(title='Streaming Line Plot',
plot_width=800, plot_height=400)
fig.line(x='step', y='ncount', source=data_source)
global step
step = 0
def button1_run():
global callback_obj
if button1.label == 'Run':
button1.label = 'Stop'
button1.button_type='danger'
callback_obj = doc.add_periodic_callback(button2_step, 100)
else:
button1.label = 'Run'
button1.button_type = 'success'
doc.remove_periodic_callback(callback_obj)
def button2_step():
global step
step = step+1
for i in range(len(strategies)):
new = {'step': [step],
'strategy': [strategies[i]],
'ncount': [random.choice(range(1,100))]}
fig.line(x='step', y='ncount', source=new)
data_source.stream(new)
# add on_click callback for button widget
button1 = Button(label="Run", button_type='success', width=390)
button1.on_click(button1_run)
button2 = Button(label="Step", button_type='primary', width=390)
button2.on_click(button2_step)
doc.add_root(column(fig, button1, button2))
doc.title = "Now with live updating!"
apps = {'/': Application(FunctionHandler(make_document))}
server = Server(apps, port=5004)
server.start()
if __name__ == '__main__':
server.io_loop.add_callback(server.show, "/")
server.io_loop.start()
My hope was that by looping thru the 4 "strategies" in the example (after clicking button2), I could stream the new data coming out of the simulation into a line plot for that one strategy and step only. But what I get is one line with all four values connected vertically, then one of them connected to the first one at the next step. Here's what it looks like after a few steps:
I noticed that if I move data_source.stream(new) out of the for loop, I get a nice single line plot, but of course it is only for the last strategy coming out of the loop.
In all the bokeh multiple line plotting examples I've studied (not the multi_line glyph, which I can't figure out and which seems to have some issues with the Hover tool), the instructions seem pretty clear: if you want to render a second line, you add another fig.line renderer to an existing figure, and it draws a line with the data provided in source=data_source for this line. But even though my for-loop collects and adds data separately for each strategy, I don't get 4 line plots, I get only one.
Hoping I'm missing something obvious! Thanks in advance.
Seems like you need a line per strategy, not a line per step. If so, here's how I would do it:
import random
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler
from bokeh.layouts import column
from bokeh.models import Button
from bokeh.palettes import Dark2
from bokeh.plotting import figure, ColumnDataSource
from bokeh.server.server import Server
STRATEGIES = ['DD', 'DC', 'CD', 'CCDD']
def make_document(doc):
step = 0
def new_step_data():
nonlocal step
result = [dict(step=[step],
ncount=[random.choice(range(1, 100))])
for _ in STRATEGIES]
step += 1
return result
fig = figure(title='Streaming Line Plot', plot_width=800, plot_height=400)
sources = []
for s, d, c in zip(STRATEGIES, new_step_data(), Dark2[4]):
# Generate the very first step right away
# to avoid having a completely empty plot.
ds = ColumnDataSource(d)
sources.append(ds)
fig.line(x='step', y='ncount', source=ds, color=c)
callback_obj = None
def button1_run():
nonlocal callback_obj
if callback_obj is None:
button1.label = 'Stop'
button1.button_type = 'danger'
callback_obj = doc.add_periodic_callback(button2_step, 100)
else:
button1.label = 'Run'
button1.button_type = 'success'
doc.remove_periodic_callback(callback_obj)
def button2_step():
for src, data in zip(sources, new_step_data()):
src.stream(data)
# add on_click callback for button widget
button1 = Button(label="Run", button_type='success', width=390)
button1.on_click(button1_run)
button2 = Button(label="Step", button_type='primary', width=390)
button2.on_click(button2_step)
doc.add_root(column(fig, button1, button2))
doc.title = "Now with live updating!"
apps = {'/': Application(FunctionHandler(make_document))}
server = Server(apps, port=5004)
if __name__ == '__main__':
server.io_loop.add_callback(server.show, "/")
server.start()
server.io_loop.start()
Thank you, Eugene. Your solution got me back on the right track. I played around with it a bit more and ended up with the following:
import colorcet as cc
from bokeh.server.server import Server
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler
from bokeh.plotting import figure, ColumnDataSource
from bokeh.models import Button
from bokeh.layouts import column
import random
def make_document(doc):
# make a list of groups
strategies = ['DD', 'DC', 'CD', 'CCDD']
# initialize some vars
step = 0
callback_obj = None
colors = cc.glasbey_dark
# create a list to hold all CDSs for active strategies in next step
sources = []
# Create a figure container
fig = figure(title='Streaming Line Plot - Step 0', plot_width=800, plot_height=400)
# get step 0 data for initial strategies
for i in range(len(strategies)):
step_data = dict(step=[step],
strategy = [strategies[i]],
ncount=[random.choice(range(1, 100))])
data_source = ColumnDataSource(step_data)
color = colors[i]
# this will create one fig.line renderer for each strategy & its data for this step
fig.line(x='step', y='ncount', source=data_source, color=color, line_width=2)
# add this CDS to the sources list
sources.append(data_source)
def button1_run():
nonlocal callback_obj
if button1.label == 'Run':
button1.label = 'Stop'
button1.button_type='danger'
callback_obj = doc.add_periodic_callback(button2_step, 100)
else:
button1.label = 'Run'
button1.button_type = 'success'
doc.remove_periodic_callback(callback_obj)
def button2_step():
nonlocal step
data = []
step += 1
fig.title.text = 'Streaming Line Plot - Step '+str(step)
for i in range(len(strategies)):
step_data = dict(step=[step],
strategy = [strategies[i]],
ncount=[random.choice(range(1, 100))])
data.append(step_data)
for source, data in zip(sources, data):
source.stream(data)
# add on_click callback for button widget
button1 = Button(label="Run", button_type='success', width=390)
button1.on_click(button1_run)
button2 = Button(label="Step", button_type='primary', width=390)
button2.on_click(button2_step)
doc.add_root(column(fig, button1, button2))
doc.title = "Now with live updating!"
apps = {'/': Application(FunctionHandler(make_document))}
server = Server(apps, port=5004)
server.start()
if __name__ == '__main__':
server.io_loop.add_callback(server.show, "/")
server.io_loop.start()
Result is just what I was looking for ...

script in python: Template is not defined

I am using the following Python script:
import numpy as np
import matplotlib.pyplot as plt
import nibabel
import os
def collapse_probtrack_results(waytotal_file, matrix_file):
with open(waytotal_file) as f:
waytotal = int(f.read())
data = nibabel.load(matrix_file).get_data()
collapsed = data.sum(axis=0) / waytotal * 100.
return collapsed
matrix_template = 'results/{roi}.nii.gz.probtrackx2/matrix_seeds_to_all_targets.nii.gz'
processed_seed_list = [s.replace('.nii.gz','').replace('label/', '')
for s in open('/home/salvatore/tirocinio/aal_rois_diff_space/aal.txt').read().split('\n')
if s]
N = len(processed_seed_list)
conn = np.zeros((N, N))
rois=[]
idx = 0
for roi in processed_seed_list:
matrix_file = template.format(roi=roi)
seed_directory = os.path.dirname(result)
roi = os.path.basename(seed_directory).replace('.nii.gz.probtrackx2', '')
waytotal_file = os.path.join(seed_directory, 'waytotal')
rois.append(roi)
try:
# if this particular seed hasn't finished processing, you can still
# build the matrix by catching OSErrors that pop up from trying
# to open the non-existent files
conn[idx, :] = collapse_probtrack_results(waytotal_file, matrix_file)
except OSError:
pass
idx += 1
# figure plotting
fig = plt.figure()
ax = fig.add_subplot(111)
cax = ax.matshow(conn, interpolation='nearest', )
cax.set_cmap('hot')
caxes = cax.get_axes()
When I try to run it I get the following error: NameError: name 'template' is not defined. This refers to line 22 of the script above. Can you please help me to figure out what is this about?
There is no variable like template, so template cannot be used in the right side of the expression. Try
matrix_file = matrix_template.format(roi=roi)
instead.

Python Traits GUI recursion depth

I'm developing a GUI in python using Enthought's Traits. I keep getting a "RuntimeError: maximum recursion depth exceeded in cmp" If I flip the order in which the "Item" labels are used in my MainWindow class, the code executes fine. I can't seem to find any documentation on why this would happen. It seems like it has something to do with the Chaco plot. Below is my test code.
from chaco.api import ArrayPlotData, Plot
from traits.api import HasTraits, Instance, String, Float, Enum, Button, Str
from traitsui.api import Handler, View, Item, Group, HSplit, NoButtons, VGroup, VGrid
from pyface.api import GUI
from threading import Thread
from time import sleep
from enthought.enable.component_editor import ComponentEditor
from scipy import rand, indices, exp, sqrt, sum
import numpy as np
from PIL import Image
import matplotlib.image as mpimg
from enthought.chaco.api import gray
from enthought.savage.traits.ui.svg_button import SVGButton
class User_Input_Panel(HasTraits):
User = Str(name='User', label="User Name")
Sample_Name = Str(name='Sample_Name',label="Sample Name")
Path = Str(name='Path', label="Save Location", style = 'readonly')
#I use this to create a folder icon on the button
#~ Save_Folder_Button = SVGButton(label='Choose save Location', \
#~ filename=Folder-drag-accept.svg', \
#~ width=28, \
#~ height=28 \
#~ )
#~ #Create the User Information panel
User_Information_Panel = View(VGroup(
VGrid(
Item('User'),
Item('Sample_Name'),
Item('Path', width=.700, visible_when = 'Save_Visible == True'),
#Item('Save_Folder_Button', show_label=False),
),
show_border=True, label="User Information"
))
def _Save_Folder_Button_fired(self, event):
print("Pushed the Save Folder")
#self.file, self.dir = wxOpenFile(multi=False)
#fdir = GUI_tools.wxOpenFile()
#fdir = GUI_tools.wxSavePath()
#I'm planning on setting up threading later
class MainWindowHandler(Handler):
def close(self, info, is_OK):
#~ if (info.object.user_input.acquisition_thread and \
#~ info.object.user_input.acquisition_thread.isAlive()):
#~ info.object.user_input.acquisition_thread.wants_abort = True
#~ while info.object.user_input.acquisition_thread.isAlive():
#~ sleep(0.1)
#~ GUI.process_events()
return True
class MainWindow(HasTraits):
plot = Instance(Plot)
plotdata = Instance(ArrayPlotData, ())
user_input = Instance(User_Input_Panel, ())
def _user_input_default(self):
return User_Input_Panel(plotdata = self.plotdata)
Save_Folder_Button = SVGButton(label='Choose save Location', \
filename='C:\Python27\Examples\Mill_GUI\Tescan_BatchScan\Folder-drag-accept.svg', \
width=28, \
height=28 \
)
def _plot_default(self):
self.plotdata = ArrayPlotData(imagedata=np.zeros((100,100)))
plot = Plot(self.plotdata)
plot.img_plot('imagedata')
self.plot = plot
return plot
# If I flip the "Item('user_input'" with "Item('plot') the code will run...
view = View(VGroup(Item('user_input', style = 'custom', show_label = False),
Item('plot', editor = ComponentEditor(), dock = 'vertical'),
show_labels = False),
resizable = True, handler = MainWindowHandler(),
buttons = NoButtons)
if __name__ == '__main__':
MainWindow().configure_traits()
Does anybody know why you would get recursion errors with this code? I have to display the plot below my user_input panel so the users can see the live time data they are gathering.
Cheers,
Shivels
You need to remove the following line from your _plot_default method:
self.plot = plot
For this to happen in traits, you simply need to return that plot object and the assignment to self.plot will be done by Traits. The recursion error happens because you as trying to access the plot attribute of the object inside the method that is trying to set it.

Categories

Resources