I have been searching stackoverflow for a solution to the issue of an interactive mpl figure when streaming data to it. I've gotten close with the below example, but when I plot this no matter what mods I make to the code I'm unable to interact with the figure window. What concept am I missing that would allow me to stream data to this window AND drag the window around? As you can see it opens up and plots, but if I grab the frame to move it to a different location it crashes and most of the time is stuck in place.
I'm using Python 2.7, Paycharm and Windows 10.
Here is a helpful example I'm working with.
Example-from-documentation
Is the problem because I'm using plt.show()? My test code consists of 3 files, a datagen, data consumer (plotter) and a top level file (test bench) instantiating and starting the data generator and plotting module. I am just appending 62bytes of sine wave data to the end of an array and plotting it so it looks like it is scrolling by.
Test bench:
NB_DataGen -> NB_Plotter (receives 62 bytes of data and plots).
MODULE1: DATA PLOTTING MODULE
# This is the no blitting data plot module built out as a threaded module.
#
#
# Notes:
# 1. Bug in frame rate code
# 2. Going to try to remove queue from plotter and just have a direct access call for
# direct writes to plot. Queue seems to be bogging down window and I can't drag it
# around.
#
try:
import Queue as queue
except:
import queue
import numpy as np
from matplotlib import pyplot as plt
import time
import threading
import matplotlib
print(matplotlib.__version__)
class BlitManager:
def __init__(self, canvas, animated_artists=()):
"""
Parameters
----------
canvas : FigureCanvasAgg
The canvas to work with, this only works for sub-classes of the Agg
canvas which have the `~FigureCanvasAgg.copy_from_bbox` and
`~FigureCanvasAgg.restore_region` methods.
animated_artists : Iterable[Artist]
List of the artists to manage
"""
self.canvas = canvas
self._bg = None
self._artists = []
for a in animated_artists:
self.add_artist(a)
# grab the background on every draw
self.cid = canvas.mpl_connect("draw_event", self.on_draw)
def on_draw(self, event):
"""Callback to register with 'draw_event'."""
cv = self.canvas
if event is not None:
if event.canvas != cv:
raise RuntimeError
self._bg = cv.copy_from_bbox(cv.figure.bbox)
self._draw_animated()
def add_artist(self, art):
"""
Add an artist to be managed.
Parameters
----------
art : Artist
The artist to be added. Will be set to 'animated' (just
to be safe). *art* must be in the figure associated with
the canvas this class is managing.
"""
if art.figure != self.canvas.figure:
raise RuntimeError
art.set_animated(True)
self._artists.append(art)
def _draw_animated(self):
"""Draw all of the animated artists."""
fig = self.canvas.figure
for a in self._artists:
fig.draw_artist(a)
def update(self):
"""Update the screen with animated artists."""
cv = self.canvas
fig = cv.figure
# paranoia in case we missed the draw event,
if self._bg is None:
self.on_draw(None)
else:
# restore the background
cv.restore_region(self._bg)
# draw all of the animated artists
self._draw_animated()
# update the GUI state
cv.blit(fig.bbox)
# let the GUI event loop process anything it has to do
cv.flush_events()
#
# Main Class
#
class NB_Plotter4(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.i = 0
# thread loop flag
self.thread_event = threading.Event()
self.thread_event.set() # set thread by default
# create plot objects
self.fig = plt.figure()
self.ax1 = self.fig.add_subplot(1,1,1)
self.ax1.grid()
self.line, = self.ax1.plot([], lw=3)
self.text = self.ax1.text(0.8, 0.5, "")
self.x_new = np.linspace(0.0, 200.0, num=1000)
self.y_total = np.empty(1000, dtype=float)
#set limits
self.ax1.set_xlim(self.x_new.min(), self.x_new.max())
self.ax1.set_ylim([-1.1, 1.1])
# start timer for frame counter
self.t_start = time.time()
#self.bm = BlitManager(self.fig.canvas, [self.line, self.text])
self.bm = BlitManager(self.fig.canvas, [self.line])
plt.show(block=False)
plt.pause(0.1)
#
# main thread loop
#
def Write(self, data):
# need to grab y-data here from queue
self.y_ndata = data
self.y_total = np.concatenate([self.y_total[62:], self.y_ndata])
self.i = self.i + 1
#
# Over-ride thread run method
#
def run(self):
while self.thread_event.is_set():
self.line.set_data(self.x_new, self.y_total)
tx = 'Mean Frame Rate:\n {fps:.5f}FPS'.format(fps=((self.i + 1) / (time.time() - self.t_start)))
self.text.set_text(tx)
self.bm.update()
MODULE2: DATA GENERATION MODULE
# This is the no blitting data gen module. This module is intended to produce data
# in 62 byte blocks resulting in sine wave data blocks. This is initally meant to
# spoof my DR500 USB payload size so I can' drive some real time plotting.
#
#
# Notes:
#
#
#
try:
import Queue as queue
except:
import queue
import numpy as np
import threading
import time
#
# Main Class
#
# For the 62 byte class the rounding in the x vector produces some small errors. This shouldn't
# be a big problem since the resolution is so high.
#
class NB_DataGen2(threading.Thread):
def __init__(self, Plotter):
threading.Thread.__init__(self)
self.y_data = np.empty(62, dtype=float)
self.x_data = np.linspace(0.0, np.pi/62.0, num=62)
self.offset_val = self.x_data[1]
self.Plotter_Handle = Plotter
self.inc_cnt = 0.0
self.first_it_flag = 0 # first iteration flag
# thread loop flag
self.thread_event = threading.Event()
self.thread_event.set() # set thread by default
#
# Produce 62 byte packet of sine wave data
# - produce next 62 byte chunk of sine wave data
def Get62ByteSine(self, debug=False):
# hit for iterations > 0
if(self.first_it_flag > 0):
# gen
self.x_data = self.x_data + (np.pi / 62.0) + self.offset_val
self.y_data = np.sin(self.x_data)
if(debug == True):
print(self.y_data)
return self.y_data
# hit for iterations < 1 -> (first iteration)
else:
# first iteration
self.x_data = self.x_data
self.y_data = np.sin(self.x_data)
if (debug == True):
print(self.y_data)
self.inc_cnt = self.inc_cnt + 1.0
# flip first run flag
self.first_it_flag = 1
return self.y_data
#
# Ignore / Not in use
#
# Used to check the error from the last value in one block (62 byte block)
# and the first value of the next block. the difference in the two should
# match the offset value roughly. Enable print funcitons in the above
# Get62ByteSine function for this to work.
#
def CheckError(self):
self.Get62ByteSine(True)
self.Get62ByteSine(True)
self.Get62ByteSine(True)
# print offset
print(self.offset_val)
#
# Kill thread
#
def KillThread(self):
self.thread_event.clear()
#
# main thread loop
#
def run(self):
while self.thread_event.is_set():
self.Plotter_Handle.Write(self.Get62ByteSine())
time.sleep(1)
MODULE3: TOP LEVEL TEST BENCH
# This is the no blitting test bench top module
#
#
# Notes:
#
#
#
from NB_DataGen2 import NB_DataGen2
from NB_Plotter4 import NB_Plotter4
#
# Testbench Class
#
class NB_TestBench(object):
def __init__(self):
# create data/plot objects (DUTs) - obj's under test
self.Plotter = NB_Plotter4()
self.DataGen = NB_DataGen2(self.Plotter)
def Start(self):
self.DataGen.start()
self.DataGen.isDaemon()
self.Plotter.start()
self.Plotter.isDaemon()
# Run test bench
NB = NB_TestBench()
NB.Start()
Long story short - I'm trying to run this code to plot incoming data and be able to drag the window around or just generally interact with it via the mouse. Does anyone see where I went wrong?
Related
I'd like to be able to run the exact same run, given I didn't change any parameters of the simulation, in the autonomous driving simulator Carla. Before I paste my code, my logic is that I have to set a specific seed for any Random operation to be repeatable, set a specific seed for the traffic manager, and in general to work in synchronous_mode=True so the lag in my computer won't interrupt(?). As you'll see, I log the x,y,z location of the ego vehicle, and run the simulation twice. It is similar, but not the same. What can I do to make it repeatable (not in recording mode, actual live runs)?
Additional info: Carla 0.9.14 on Ubuntu 20.04, Python 3.8.
import random
import numpy as np
import sys
import os
try:
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '/carla')
except IndexError:
pass
import carla
from agents.navigation.behavior_agent import BehaviorAgent # pylint: disable=import-error
seed = 123
N_vehicles = 50
camera = None
telemetry = []
random.seed(seed)
try:
# Connect the client and set up bp library and spawn points
client = carla.Client('localhost', 2000)
client.set_timeout(60.0)
world = client.get_world()
bp_lib = world.get_blueprint_library()
spawn_points = world.get_map().get_spawn_points()
settings = world.get_settings()
settings.synchronous_mode = True
settings.fixed_delta_seconds = 0.10
world.apply_settings(settings)
traffic_manager = client.get_trafficmanager()
traffic_manager.set_random_device_seed(seed)
traffic_manager.set_synchronous_mode(True)
# Spawn ego vehicle
vehicle_bp = bp_lib.find('vehicle.audi.a2')
# breakpoint()
vehicle = world.try_spawn_actor(vehicle_bp, random.choice(spawn_points))
# Move spectator behind vehicle to motion
spectator = world.get_spectator()
transform = carla.Transform(vehicle.get_transform().transform(carla.Location(x=-6,z=2.5)),vehicle.get_transform().rotation)
spectator.set_transform(transform)
world.tick()
# set the car's controls
agent = BehaviorAgent(vehicle, behavior="normal")
destination = random.choice(spawn_points).location
agent.set_destination(destination)
print('destination:')
print(destination)
print('current location:')
print(vehicle.get_location())
#Iterate this cell to find desired camera location
camera_bp = bp_lib.find('sensor.camera.rgb')
# Spawn camera
camera_init_trans = carla.Transform(carla.Location(z=2))
camera = world.spawn_actor(camera_bp, camera_init_trans, attach_to=vehicle)
# Callback stores sensor data in a dictionary for use outside callback
def camera_callback(image, data_dict):
data_dict['image'] = np.reshape(np.copy(image.raw_data), (image.height, image.width, 4))
# Get gamera dimensions and initialise dictionary
image_w = camera_bp.get_attribute("image_size_x").as_int()
image_h = camera_bp.get_attribute("image_size_y").as_int()
camera_data = {'image': np.zeros((image_h, image_w, 4))}
# Start camera recording
camera.listen(lambda image: camera_callback(image, camera_data))
# Add traffic to the simulation
SpawnActor = carla.command.SpawnActor
SetAutopilot = carla.command.SetAutopilot
FutureActor = carla.command.FutureActor
vehicles_list, batch = [], []
for i in range(N_vehicles):
ovehicle_bp = random.choice(bp_lib.filter('vehicle'))
npc = world.try_spawn_actor(ovehicle_bp, random.choice(spawn_points))
# add it if it was successful
if(npc):
vehicles_list.append(npc)
print(f'only {len(vehicles_list)} cars were spawned')
world.tick()
# Set the all vehicles in motion using the Traffic Manager
for idx, v in enumerate(vehicles_list):
try:
v.set_autopilot(True)
except:
pass
# Game loop
while True:
world.tick()
pose = vehicle.get_location()
telemetry.append([pose.x, pose.y, pose.z])
# keep following the car
transform = carla.Transform(vehicle.get_transform().transform(carla.Location(x=-6,z=2.5)),vehicle.get_transform().rotation)
spectator.set_transform(transform)
if agent.done():
print("The target has been reached, stopping the simulation")
break
control = agent.run_step()
control.manual_gear_shift = False
vehicle.apply_control(control)
finally:
# Stop the camera when we've recorded enough data
if(camera):
camera.stop()
camera.destroy()
settings = world.get_settings()
settings.synchronous_mode = False
settings.fixed_delta_seconds = None
world.apply_settings(settings)
traffic_manager.set_synchronous_mode(True)
if(vehicles_list):
client.apply_batch([carla.command.DestroyActor(v) for v in vehicles_list])
vehicle.destroy()
np.savetxt('telemetry.txt', np.array(telemetry), delimiter=',')
y-axis is the error between two runs, x-axis is the time index of the run
I am currently working working on a program that tries to replicate labview functionality by establishing a connection to SR830 via RS-232. For some reasons, I am not able to record data and I cannot seem to figure out why. I tried to google about it but I did not find anything. If someone could please help me figure out what I am doing wrong.
Here is my code:
import serial
import tkinter as tk
from datetime import datetime
import time
import os
import atexit
import threading
import numpy as np
import math
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import matplotlib.animation as animation
class SR830:
'''SR830 Class creates an object that can interface with and control an SR830 via RS-232.
Class data structure allows the SR830 code to be imported into other scripts via "from SSTR_Serial import SR830"
This can be used to encapsulate SR830 interface mechanics into a larger control scheme...
by passing the class a frame to pack itself into as the frame argument.'''
def command(self, command_string, command_value): #Basic command protocol, can be used as a template for other command functions.
#Note: queries should have null command_value arguments (command_value = '').
packet = command_string+str(command_value)+'\r' #Can be adjusted to include checksums/parity if needed.
try:
self.inst.write(packet.encode('ascii'))
except AttributeError as AE:
print(AE)
def create_log(self):
try: #Makes log file if it does not exist already.
log_dir = self.name+'_logs'
os.mkdir(log_dir)
except OSError:#Log file already exists
pass
self.log_open = datetime.now() #Var to hold time log was created (Different from when timer is started.)
date = str(self.log_open).split(' ')[0] #Date that log file was opened.
h = 0
a = False
while not a:
h += 1
log_str = log_dir+'/'+self.name+"_"+date+'_'+str(h)+'.txt'
log_path = os.path.join(os.getcwd(), log_str)
if os.path.exists(log_path):
pass
else:
a = True
self.log = open(log_str, "w+")
self.log.write(self.name+" log created on "+ str(self.log_open)+"\nTime \tShift (Degrees)\tAmplitude (mV)\tR ()\tTheta ()\n") #Writing opening lines.
def start_graph(self): #Should be threaded at begining. This begins making the graph and recording data when the start/record buttons are pressed.
def get_vals(self):
current_time = time.time()#Get current time
if (current_time - self.previous_time) >= self.sample_time: #Time is equal or passed sampling time.
time_elapsed = current_time - self.start_time #Total time elapsed since transmission begun.
#Transmission zone:
try: #Querying and storing commands below
self.command("PHAS?",'')
phase_shift = self.inst.read(5).decode('ascii').replace('\r','')
self.command('SLVL?','')
phase_amplitude = self.inst.read(5).decode('ascii').replace('\r','')
self.shifts = np.append(self.shifts,[phase_shift]); self.amplitudes = np.append(self.amplitudes,[phase_amplitude]); self.times = np.append(self.times,[time_elapsed]) #Will only append time if both other arrays are appended.
#^ Append on one line to keep all lengths consistant when switching threads.
#Variables that are queried but not logged.
self.command('OEXP?1','')
R = self.inst.read(5).decode('ascii').replace('\r','')
self.command('OEXP?2','')
Theta = self.inst.read(5).decode('ascii').replace('\r','')
except AttributeError as AE:#Exceptions for testing without connection to device
print(AE)
'''
#This area generates random sine waves. Only use for testing without connection to actual device.---------
self.times = np.append(self.times,[len(self.times)])
self.shifts = np.append(self.shifts,[math.sin(len(self.times))])
self.amplitudes = np.append(self.amplitudes, [5*math.cos(len(self.times))])
phase_shift = 5
phase_amplitude = 7
R = 10
Theta = 11
print(str(len(self.times)))
print(str(len(self.shifts)))
print(str(len(self.amplitudes)))
#End test zone ---------------------------------------------------------------------------------------
'''
#Remove extra elements to reduce memeory usage for long runs
while len(self.times) > 200: #Integer on RHS of inequality is max number of elements.
self.shifts = self.shifts[2:-1:1]; self.amplitudes = self.amplitudes[2:-1:1]; self.times=self.times[2:-1:1]
#Log writing zone:
if self.recording is True: #Updates log, otherwise only updates graph.
self.log.write(str(round(time_elapsed-self.pause_time,4))+'\t'+str(phase_shift)+'\t\t'+str(phase_amplitude)+'\t\t'+str(R)+'\t'+str(Theta)+'\n')
self.previous_time = current_time #Resets time value for calculating interval.
while self.running: #Loops as long as running is true and kills thread once runing is false.
get_vals(self)
def animate(self, i): #Only redraw matplotlib aspects that get cleared with a.clear() and a2.clear() to conserve memory.
#Todo - optimize drawing order
try:
self.a.clear()
self.a.plot(self.times,self.shifts, label='Phase shift ()', color='tab:blue')
self.a.set_ylabel('Shift')
self.a.set_ylabel('Shift', color='tab:blue')
self.a.set_xlabel('Time (s)')
self.a.legend(loc='upper left')
self.a2.clear()
self.a2.plot(self.times,self.amplitudes,label='Phase amplitude ()',color='tab:red')
self.a2.set_ylabel('Amplitude', color='tab:red')
self.a2.legend(loc='upper right')
self.a.get_yaxis_transform()#Fits axis to widget area.
except ValueError as VE:
print(VE)
def clear_graph(self): #Clears all arrays to make graph reset. Does not erase logged data.
self.times = np.array([])
self.shifts = np.array([])
self.amplitudes = np.array([])
def startstop(self): #Flips button to begin or stop graphing.
if self.running is False: #Recording and graphing is off. Calling function will turn it on and activate the following lines
self.running = True
self.clear_graph() #Clears last run.
self.run_btn.config(text='Stop', bg='red')
#self.start_graph()
self.sample_time = float(self.sample_box.get())
self.pause_time = 0 #Resets pause adjustment time.
self.start_time = time.time() #Resets start time. TODO-Add adjustments for pauses
self.pause_point = time.time() #Last time that pause activated. Used to calculate pause_time later.
self.graph_thread = threading.Thread(target=self.start_graph)
self.graph_thread.start()
else: #graphing is on. Calling function will turn it off and activate the following line
self.running = False
self.run_btn.config(text='Start',bg='green')
self.recording=False
self.record_btn.config(text='Start recording', bg="green")
try: #Shuts down log file if it exists.
self.log.close()
except AttributeError as AE:
print(AE)
def startstop_record(self): #Flips recording button.
if self.running is False:
self.startstop() #Makes sure data is being transmitted before recording starts.
if self.recording is False: #Device is running, but not recording. Command turns recording on.
self.record_btn.config(text='Pause recording', bg="yellow")
try:
self.log.write('') #Attempts to write an empty string to test if file is open.
except AttributeError: #File has not been created -> run function to open a new log.
self.create_log()
except ValueError: #Previous log file has been closed -> run function to open new log.
self.create_log()
self.recording = True
self.pause_time += time.time() - self.pause_point #Adjusts for
else: #Device is running AND recording. Command pauses recording.
self.recording = False
self.pause_point = time.time()
self.record_btn.config(text='Start recording', bg="green")
def __init__(self, name, frame):
self.name = name
self.running = False
self.recording = False
#Read config -----------------------------------------------------------------------
config = open('SR830 config.txt','w+')
try:
config_read = config.readlines()
config_read = config_read[1].split('\t')
except IndexError: #config coudl not be read - creates default file.
config.write('COM Baudrate\ttimeout\tsampling time\n10\t9600\t0.1\t1')
config.close()
config = open('SR830 config.txt','r')
config_read = config.readlines()
config_read = config_read[1].split('\t')
com = config_read[0]
baud = int(config_read[1])
self.config_timeout = float(config_read[2])
self.sample_time = float(config_read[3])
config.close()
#establish communication -----------------------------------------------------------
com = 'COM'+str(com) #TODO- make this read from config
try:
SR_inst = serial.Serial(port=com, baudrate=baud, timeout=self.config_timeout) #Opens communication.
#Note: SR830 has adjustablebaud rate and parity, but defaults to 9600 and none, respectively.
self.inst = SR_inst
self.command('OUTX',0) #Tells device to output responses via RS-232.
print(self.inst.read(5)) #Prints response to OUTX command.
#self.command('OUTX?','') #TEST - see if communication has switched.
#print(self.inst.read(10)) #Should print b'0\r' for RS-232 communication.
self.command('DDEF',110)#Sets CH1 to R.
print(self.inst.read(5))
self.command('DDEF',210)#Sets CH2 to Theta.
print(self.inst.read(5))
except ValueError as ve:
SR_inst = 0
print(ve)
except AttributeError as ae:
SR_inst = 0
print (ae)
except NameError as ne:
print(ne)
SR_inst = 0
except serial.SerialException as SE:
SR_inst = 0
print(SE)
#Create Tkinter GUI------------------------------------------------------------------
id_label=tk.Label(frame, text=name)
id_label.grid(row=0,column=0, sticky=tk.N+tk.S+tk.E+tk.W)
version_label = tk.Label(frame, text = 'Version 0.1')
version_label.grid(row=0, column=1, sticky=tk.N+tk.S+tk.E+tk.W)
sample_label = tk.Label(frame, text="Sampling time =")
sample_label.grid(row=1,column=0,sticky=tk.N+tk.S+tk.E+tk.W)
self.sample_box = tk.Entry(frame)
self.sample_box.insert(tk.END, self.sample_time)
self.sample_box.grid(row=1,column=1,sticky=tk.N+tk.S+tk.E+tk.W)
self.run_btn = tk.Button(frame, text='Start', command = self.startstop)
self.run_btn.grid(row=2,column=0,sticky=tk.N+tk.S+tk.E+tk.W)
self.run_btn.config(bg="green")
self.record_btn = tk.Button(frame, text='Start recording', command = self.startstop_record)
self.record_btn.grid(row=2,column=1,sticky=tk.N+tk.S+tk.E+tk.W)
self.record_btn.config(bg="green")
#Graph setup:
self.f = Figure(figsize=(5,5),dpi=100) #Figure that graphs appears in
self.a = self.f.add_subplot() #111 means there is only 1 chart. use a.plot to plot lists.
self.a2 = self.a.twinx()
self.graph_canvas = FigureCanvasTkAgg(self.f, frame)
self.graph_canvas.get_tk_widget().grid(row=3, column=0,columnspan=2)
#Make grid resizeable
for row in range(4): #Number of rows
try:
tk.Grid.rowconfigure(frame,row,weight=2)
except AttributeError as AE: #FOr unfilled rows & columns
print(AE)
for column in range(2): #Number of columns
try:
#root.grid_columnconfigure(column, weight=1)
tk.Grid.columnconfigure(frame,column,weight=1)
except AttributeError as AE: #For unfilled rows & columns
print(AE)
#Extra declarations
self.sample_time = float(self.sample_box.get())-2*self.config_timeout #Adjusts for timeout of device.
self.times = np.array([]) #Holds time values queried (May not be recorded)
self.shifts = np.array([])#Holds shift values queried.
self.amplitudes = np.array([])#Holds amplitude values queried.
#self.start_time = time.time() #TODO - Move this somewhere better
self.previous_time = 0
time.sleep(1)
self.ani = animation.FuncAnimation(self.f,self.animate, interval=1000)
def SR830_exit(self): #Exit handler.
self.running = False
self.recording = False
try:
self.inst.close()
except AttributeError as AE:
print(AE)
root.destroy()
exit()
#TEST AREA: ------------------------------------------------------------------------------
# Create tk root -------------------
root = tk.Tk()
root.title('SR830')
frame1 = tk.Frame(root)
frame1.pack()
#Create instrument object ---------
sr1 = SR830("SSTR", frame1) #TODO - remove once testing is done.
atexit.register(sr1.SR830_exit)
root.protocol('WM_DELETE_WINDOW', sr1.SR830_exit)
root.mainloop()
I'm trying to create an experiment using Psychopy.
In the specific I'm trying to create a routine ("trial") where a video ("movie1") is presented and at the same time I would like to play a sequence of 4 sounds (one per second) randomly chosen from a list of 10 in an excel file (sounds.routine.xlsx).
Here's what I have done so far:
from __future__ import absolute_import, division
from psychopy import locale_setup
from psychopy import prefs
from psychopy import sound, gui, visual, core, data, event, logging, clock
from psychopy.constants import (NOT_STARTED, STARTED, PLAYING, PAUSED,
STOPPED, FINISHED, PRESSED, RELEASED, FOREVER)
import numpy as np # whole numpy lib is available, prepend 'np.'
from numpy import (sin, cos, tan, log, log10, pi, average,
sqrt, std, deg2rad, rad2deg, linspace, asarray)
from numpy.random import random, randint, normal, shuffle
import os # handy system and path functions
import sys # to get file system encoding
from psychopy.hardware import keyboard
# Ensure that relative paths start from the same directory as this script
_thisDir = os.path.dirname(os.path.abspath(__file__))
os.chdir(_thisDir)
# Store info about the experiment session
psychopyVersion = '3.2.4'
expName = 'dsffdsfads' # from the Builder filename that created this script
expInfo = {'participant': '', 'session': '001'}
dlg = gui.DlgFromDict(dictionary=expInfo, sortKeys=False, title=expName)
if dlg.OK == False:
core.quit() # user pressed cancel
expInfo['date'] = data.getDateStr() # add a simple timestamp
expInfo['expName'] = expName
expInfo['psychopyVersion'] = psychopyVersion
# Data file name stem = absolute path + name; later add .psyexp, .csv, .log, etc
filename = _thisDir + os.sep + u'data/%s_%s_%s' % (expInfo['participant'], expName, expInfo['date'])
# An ExperimentHandler isn't essential but helps with data saving
thisExp = data.ExperimentHandler(name=expName, version='',
extraInfo=expInfo, runtimeInfo=None,
originPath='/Users/Documents/dsffdsfads.py',
savePickle=True, saveWideText=True,
dataFileName=filename)
# save a log file for detail verbose info
logFile = logging.LogFile(filename+'.log', level=logging.EXP)
logging.console.setLevel(logging.WARNING) # this outputs to the screen, not a file
endExpNow = False # flag for 'escape' or other condition => quit the exp
frameTolerance = 0.001 # how close to onset before 'same' frame
# Start Code - component code to be run before the window creation
# Setup the Window
win = visual.Window(
size=(1024, 768), fullscr=True, screen=0,
winType='pyglet', allowGUI=False, allowStencil=False,
monitor='testMonitor', color=[0,0,0], colorSpace='rgb',
blendMode='avg', useFBO=True,
units='height')
# store frame rate of monitor if we can measure it
expInfo['frameRate'] = win.getActualFrameRate()
if expInfo['frameRate'] != None:
frameDur = 1.0 / round(expInfo['frameRate'])
else:
frameDur = 1.0 / 60.0 # could not measure, so guess
# create a default keyboard (e.g. to check for escape)
defaultKeyboard = keyboard.Keyboard()
# Initialize components for Routine "trial"
trialClock = core.Clock()
sound1 = sound.Sound(Sounds, secs=-1, stereo=True, hamming=True,
name='sound1')
sound1.setVolume(1)
movie1 = visual.MovieStim3(
win=win, name='movie1',
noAudio = True,
filename='Movies/Random_4.mp4',
ori=0, pos=(0, 0), opacity=1,
loop=False,
depth=-1.0,
)
from np.random import choice
# Create some handy timers
globalClock = core.Clock() # to track the time since experiment started
routineTimer = core.CountdownTimer() # to track time remaining of each (non-slip) routine
# set up handler to look after randomisation of conditions etc
trials = data.TrialHandler(nReps=1, method='random',
extraInfo=expInfo, originPath=-1,
trialList=data.importConditions('../Desktop/Countingpuppet/sounds_routine.xlsx', selection=choice(10, size = 4, replace = False)),
seed=None, name='trials')
thisExp.addLoop(trials) # add the loop to the experiment
thisTrial = trials.trialList[0] # so we can initialise stimuli with some values
# abbreviate parameter names if possible (e.g. rgb = thisTrial.rgb)
if thisTrial != None:
for paramName in thisTrial:
exec('{} = thisTrial[paramName]'.format(paramName))
for thisTrial in trials:
currentLoop = trials
# abbreviate parameter names if possible (e.g. rgb = thisTrial.rgb)
if thisTrial != None:
for paramName in thisTrial:
exec('{} = thisTrial[paramName]'.format(paramName))
# ------Prepare to start Routine "trial"-------
# update component parameters for each repeat
sound1.setSound(Sounds, hamming=True)
sound1.setVolume(1, log=False)
# keep track of which components have finished
trialComponents = [sound1, movie1]
for thisComponent in trialComponents:
thisComponent.tStart = None
thisComponent.tStop = None
thisComponent.tStartRefresh = None
thisComponent.tStopRefresh = None
if hasattr(thisComponent, 'status'):
thisComponent.status = NOT_STARTED
# reset timers
t = 0
_timeToFirstFrame = win.getFutureFlipTime(clock="now")
trialClock.reset(-_timeToFirstFrame) # t0 is time of first possible flip
frameN = -1
continueRoutine = True
# -------Run Routine "trial"-------
while continueRoutine:
# get current time
t = trialClock.getTime()
tThisFlip = win.getFutureFlipTime(clock=trialClock)
tThisFlipGlobal = win.getFutureFlipTime(clock=None)
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# start/stop sound1
if sound1.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
sound1.frameNStart = frameN # exact frame index
sound1.tStart = t # local t and not account for scr refresh
sound1.tStartRefresh = tThisFlipGlobal # on global time
sound1.play(when=win) # sync with win flip
# *movie1* updates
if movie1.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
movie1.frameNStart = frameN # exact frame index
movie1.tStart = t # local t and not account for scr refresh
movie1.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(movie1, 'tStartRefresh') # time at next scr refresh
movie1.setAutoDraw(True)
# check for quit (typically the Esc key)
if endExpNow or defaultKeyboard.getKeys(keyList=["escape"]):
core.quit()
# check if all components have finished
if not continueRoutine: # a component has requested a forced-end of Routine
break
continueRoutine = False # will revert to True if at least one component still running
for thisComponent in trialComponents:
if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
continueRoutine = True
break # at least one component has not yet finished
# refresh the screen
if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
win.flip()
# -------Ending Routine "trial"-------
for thisComponent in trialComponents:
if hasattr(thisComponent, "setAutoDraw"):
thisComponent.setAutoDraw(False)
sound1.stop() # ensure sound has stopped at end of routine
trials.addData('sound1.started', sound1.tStartRefresh)
trials.addData('sound1.stopped', sound1.tStopRefresh)
trials.addData('movie1.started', movie1.tStartRefresh)
trials.addData('movie1.stopped', movie1.tStopRefresh)
# the Routine "trial" was not non-slip safe, so reset the non-slip timer
routineTimer.reset()
thisExp.nextEntry()
# completed 1 repeats of 'trials'
# Flip one final time so any remaining win.callOnFlip()
# and win.timeOnFlip() tasks get executed before quitting
win.flip()
# these shouldn't be strictly necessary (should auto-save)
thisExp.saveAsWideText(filename+'.csv')
thisExp.saveAsPickle(filename)
logging.flush()
# make sure everything is closed down
thisExp.abort() # or data files will save again on exit
win.close()
core.quit()
The problem is that using np.choice only one number is reproduced and not the entire sequence of four randomly chosen numbers without repetitions. How can I do this?
Thanks in advance
Not tested, but something like this:
FPS = 60 # Frame rate of your monitor
from random import choice
from psychopy import visual, sound
win = visual.Window()
movie = visual.MovieStim(win, 'my_file.avi')
sounds = [sound.Sound('sound1.wav'), sound.Sound('sound2.wav'), sound.Sound('sound3.wav'), sound.Sound('sound4.wav')]
frame = 1
while movie.status != visual.FINISHED:
movie.draw() # Show the next frame of the movie
if frame % FPS == 0: # If a second has passed
choice(sounds).play() # Play a random sound
I really don't now why I can't call the method setTRSKey from inside my for loop. Am I missing something? This makes no sense to me at all. Pycharm declares it as an unsolved reference
Here is the code:
import math
import nuke
originNode = nuke.selectedNode()
world_matrix = originNode['world_matrix'] # this is an iArray Knob with 16 fields
mResult = nuke.math.Matrix4() # Matrix to copy iArray to
# Ask user for Frame Range operation
ret = nuke.getFramesAndViews('Frame range', '%s-%s' % (nuke.root().firstFrame(), nuke.root().lastFrame()))
if ret != None:
nuke.nodeCopy("%clipboard%") # creating node duplicate
originNode.setSelected(False)
newNode = nuke.nodePaste("%clipboard%") # creating origin node duplicate
newNode['translate'].clearAnimated()
newNode['translate'].setValue(0)
newNode['translate'].setAnimated()
newNode['rotate'].clearAnimated()
newNode['rotate'].setValue(0)
newNode['rotate'].setAnimated()
newNode['scaling'].clearAnimated()
newNode['scaling'].setValue(0)
newNode['scaling'].setAnimated()
frange = nuke.FrameRange(ret[0]) # convert to frange object
for frame in frange:
for i in xrange(0, 16):
mResult[i] = world_matrix.valueAt(frame)[i]
mResult.transpose() # row become columns and vice versa
mTranslate = nuke.math.Matrix4(mResult)
mTranslate.translationOnly()
mRotate = nuke.math.Matrix4(mResult)
mRotate.rotationOnly()
mScale = nuke.math.Matrix4(mResult)
mScale.scaleOnly()
translate = (mTranslate[12], mTranslate[13], mTranslate[14])
rotateRad = mRotate.rotationsZXY()
rotate = (math.degrees(rotateRad[0]), math.degrees(rotateRad[1]),
math.degrees(rotateRad[2])) # convert from radiants to defrees
scale = (mScale.xAxis().x, mScale.yAxis().y, mScale.zAxis().z)
setTRSKey(frame, translate, rotate, scale)
else:
print "User canceled the operation"
def setTRSKey(frame, translate, rotate, scale):
print type(translate(0))
newNode['translate'].setValueAt(translate(0), frame, 0)
newNode['translate'].setValueAt(translate(1), frame, 1)
newNode['translate'].setValueAt(translate(2), frame, 2)
edit: Example with classes where loadDataFromScript is called before defining
class Connecthor(QtWidgets.QDialog, Ui_Dialog):
#
allowedNodes = ["Read", "Write", "Merge", "Keymix", "ChannelMerge", "Roto", "RotoPaint", "Copy", "Shuffle", "PostageStamp", "Camera", "Camera2", "ScanlineRender", "Connector", "ReadGeo", "ReadGeo2", "BackdropNode"]
script_path = os.path.dirname(os.path.realpath(__file__))
#constructor
def __init__(self, parent=None):
super(Connecthor, self).__init__(parent)
self.setupUi(self)
self.setFixedSize(self.size())
#self.setWindowOpacity(0.95)
popupmenu = QtWidgets.QMenu(self.btn_settings)
#popupmenu.addAction("save links for script", self.writeListDictToJson)
#popupmenu.addAction("import links from json", self.readJsonToDict)
popupmenu.addAction("save links for script (manual)", self.saveDatatoScript)
popupmenu.addAction("settings", self.opensetting)
self.btn_settings.setMenu(popupmenu)
self.btn_settings.setIcon(QtGui.QIcon(os.path.join(iconpath, "settings.png")))
self.btn_addSelectedNodes.setIcon(QtGui.QIcon(os.path.join(iconpath, "add.png")))
self.btn_addSelectedNodes.clicked.connect(self.addSelectedNodes)
# #Loading test Json
#self.readJsonToDict()
self.loadDataFromScript()
In Python you must define functions before they are called. Move your setTRSKey definition above the for loop. Generally speaking, function definitions are one of the very first things in the file after imports, though this is not always the case.
#!/usr/bin/env python
import sys
import vtk
from PyQt4 import QtCore, QtGui
from vtk.qt4.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
import pickle
import numpy as np
from time import time
import matplotlib.pyplot as plt
import scipy as sp
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent = None):
QtGui.QMainWindow.__init__(self, parent)
self.frame = QtGui.QFrame()
self.vl = QtGui.QVBoxLayout()
self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
self.vl.addWidget(self.vtkWidget)
self.ren = vtk.vtkRenderer()
self.renWin= self.vtkWidget.GetRenderWindow()
self.renWin.AddRenderer(self.ren)
self.iren = self.renWin.GetInteractor()
t0 = time()
try:
with open('/home/nxpd/VTK/Image35.pickle','rb') as readData:
I = pickle.load(readData)
except pickle.PickleError as pErr:
print('Pickling error: '+ str(pErr))
t1 = time()
print "Time elapsed in pickle reading: " , t1 - t0
data_matrix = I
#print data_matrix
# For VTK to be able to use the data, it must be stored as a VTK-image. This can be done by the vtkImageImport-class which
# imports raw data and stores it.
dataImporter = vtk.vtkImageData()
dataImporter.SetDimensions(728,728,35)
data=vtk.vtkUnsignedCharArray()
data.SetName('scalar')
#data.SetNumberOfTuples(728*728*35)
for k in range(35):
for j in range(728):
for i in range(728):
data.InsertNextTuple1(data_matrix[i][j][k]/256)
t2 = time()
print "Time elapsed in writing to array: " , t2 - t1
dataImporter.SetExtent(0, 727, 0,727,0,34)
# The following class is used to store transparencyv-values for later retrieval. In our case, we want the value 0 to be
# completly opaque whereas the three different cubes are given different transperancy-values to show how it works.
alphaChannelFunc = vtk.vtkPiecewiseFunction()
alphaChannelFunc.AddPoint(0, 0)
alphaChannelFunc.AddPoint(53000/256, 0)
alphaChannelFunc.AddPoint(53000/256+1, 1)
alphaChannelFunc.AddPoint(65535/256, 1)
# This class stores color data and can create color tables from a few color points. For this demo, we want the three cubes
# to be of the colors red green and blue.
colorFunc = vtk.vtkColorTransferFunction()
colorFunc.AddRGBPoint(0, 0, 0, 0)
colorFunc.AddRGBPoint(53000/256, 0,0,0)
colorFunc.AddRGBPoint(53000/256+1, 1,1,1)
colorFunc.AddRGBPoint(65535/256, 1, 1, 1)
# The preavius two classes stored properties. Because we want to apply these properties to the volume we want to render,
# we have to store them in a class that stores volume prpoperties.
volumeProperty = vtk.vtkVolumeProperty()
volumeProperty.SetColor(colorFunc)
volumeProperty.SetScalarOpacity(alphaChannelFunc)
# This class describes how the volume is rendered (through ray tracing).
compositeFunction = vtk.vtkVolumeRayCastCompositeFunction()
# We can finally create our volume. We also have to specify the data for it, as well as how the data will be rendered.
volumeMapper = vtk.vtkVolumeRayCastMapper()
volumeMapper.SetVolumeRayCastFunction(compositeFunction)
volumeMapper.SetInputData(dataImporter)
# The class vtkVolume is used to pair the preaviusly declared volume as well as the properties to be used when rendering that volume.
volume = vtk.vtkVolume()
volume.SetMapper(volumeMapper)
volume.SetProperty(volumeProperty)
t3 = time()
print "Time elapsed in Setting parameters: " , t3 - t2
# With almost everything else ready, its time to initialize the renderer and window, as well as creating a method for exiting the application
#renderer = vtk.vtkRenderer()
#renderWin = vtk.vtkRenderWindow()
#renderWin.AddRenderer(renderer)
#renderInteractor = vtk.vtkRenderWindowInteractor()
#renderInteractor.SetRenderWindow(renderWin)
# We add the volume to the renderer ...
self.ren.AddVolume(volume)
# ... set background color to white ...
self.ren.SetBackground(0.5,0.5,0.7)
# ... and set window size.
self.renWin.SetSize(800,800)
t4 = time()
print "Time elapsed in rendering: " , t4 - t3
# Tell the application to use the function as an exit check.
self.renWin.AddObserver("AbortCheckEvent", exitCheck)
self.iren.Initialize()
# Because nothing will be rendered without any input, we order the first render manually before control is handed over to the main-loop.
self.ren.Render()
self.ren.ResetCamera()
self.iren.Start()
t5 = time()
print "Time elapsed in setting up: " , t5 - t4
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
I am not able to figure out why this code is showing me segmentation fault. I have used the example from http://www.vtk.org/Wiki/VTK/Examples/Python/Widgets/EmbedPyQt to get the details how exactly it works.
The standalone code works fine without using pyqt.