Creating a visible timer on experiment stimulus in psychopy - timer

New to the forum, thanks in advance for any help you could provide.
I have a series of .jpgs that are being presented to users as they study the info contained within. Instructions state that each jpg can be studied for a max of 120secs. I've already coded it such that the jpg will advance after the 120sec limit:
RespKey= []
RT = []
event.clearEvents()
myClock.reset()
t1example = myClock.getTime()
t2example = t1example
while t2example < (t1example+120): # value added to t1 here is timeout value;
RespKey = event.getKeys(keyList=["space"], timeStamped=myClock) # they are told to press space bar when done studying
if len(RespKey) > 0:
RT = RespKey[0][1]
Resp = RespKey[0][0].lower()
print Resp
print RT
break
else:
t2study = myClock.getTime() # end of timeout loop
myWin.flip()
The problem is, I don't know how to make the Clock/ Timer/ Stopwatch function visible to the user while studying the jpg. Is there a way to superimpose a visible clock onto the stimulus so nobody is surprised when the study time comes to an end?
Note: New to coding, please couch jargon in layman speak if at all possible.
Thank you!

Yes. Before the loop (and before re-setting the clock), create a text stimulus like this:
clockText = visual.TextStim(myWin) # include other parameters if you want to change the default size, font, etc
Then on every frame, you will update the content of that stimulus. i.e. just prior to the myWin.flip() call, do this:
clockText.setText(str(t2study)) # you can format/round this as required
clockText.draw()
Check the face_jpg.py Coder demo for an example of displaying text like this on every frame.

Related

How to continuously send an array of serial data into multiple functions, with the data being updated everywhere? [duplicate]

This question already has answers here:
How do you run your own code alongside Tkinter's event loop?
(5 answers)
Closed 1 year ago.
I want to code a script, that has several different functions in which an array filled with serial data has to be received.
The serial data comes from an arduino every 1 seconds. (don't worry. I changed the code to a reproducible example by using a random array.)
What I've succeeded in so far is, that the code does send the array into the function example ONCE the first time and displays it as I want it to.
What it does not do yet, is, that the information inside the function gets updated as it comes in from the arduino. When you see the code, you're gonna say, well the data is only sent once. BUT when I randomize the array every second inside a loop, the loop obviously blocks the rest of the code and the gui won't build. The fact is, that serial read updates the array WITHOUT a loop, which is highly appreciated.
The question is: How do I transport this updating into the function. Remember: It would be the natural solution for the code below to simply insert the serial read stuff INSIDE the function. BUT this is just the code that boils down the issue. The real code has several widgets invoked inside several functions and I ended up copy-&-pasting THE ENTIRE serial data signal conditioning code block into EVERY function that needs the data. This significantly increased the lag of the code, and thus is no solution.
The example script contains commented out sections to make it easier to follow what I've been trying to do to solve it so far:
import numpy as np
#import rhinoscriptsyntax as rs
import time
import tkinter as tk
import serial
"""
ser = serial.Serial(
port='/dev/ttyUSB0',
baudrate = 500000,
#parity=serial.PARITY_NONE,
#stopbits=serial.STOPBITS_ONE,
#bytesize=serial.EIGHTBITS,
timeout=1
)
ser.flushInput()
ser.flushOutput()
#I've been trying to embed the serial read stuff inside a function itself, which I'd LOVE to implement,
#but it has the same problem: either it is called just once as it is written here, ore a loop blocks the code
def serial_data():
#serialData = ser.readline()
#serialData = serialData.decode()
#floats = [float(value) for value in serialData.split(',')]
#arr = np.array(floats)
arr = np.random.rand(100)
time.sleep(1)
return arr
"""
#above commented out and replaced with random array below.
#serialData = ser.readline()
#serialData = serialData.decode()
#floats = [float(value) for value in serialData.split(',')]
#arr = np.array(floats)
arr = np.random.rand(100)
time.sleep(1)
print(np.round(arr, 3))
def nextWindow(root):
frame1 = tk.Frame(root, width=800, height=500)
frame1.pack()
text= tk.Text(frame1, width=80, height= 12, bd=0)
text.pack()
text.delete("1.0",tk.END)
#serialData = serial_data()
#text.insert(tk.INSERT, serialData)
text.insert(tk.INSERT, np.round(arr, 3))
text.update()
root = tk.Tk()
root.title('PythonGuides')
root.geometry('300x200')
root.config(bg='#4a7a8c')
nextWindow(root)
root.mainloop()
A minimal example as to how to use .after "loops" (explanation in code comments):
import tkinter as tk
# for the example
counter = 1
# your serial_data function, renamed to
# be more self-explanatory
def get_serial_data():
# put the serial reading stuff here
# the counter is just an example
global counter
counter += 1
return str(counter)
def update_text(txt):
# get data, clear text widget, insert new data
serial_data = get_serial_data()
txt.delete('0.0', 'end')
txt.insert('end', serial_data)
# schedule this function to run again in 100ms
# so it will repeat all of this effectively
# updating the text widget, you don't need to call `.update`
# note that this is not recursive
root.after(100, update_text)
def create_text():
text = tk.Text(root)
text.pack()
update_text(text)
root = tk.Tk()
create_text()
root.mainloop()

Data output from the device

I am working on a project,in which I need to extract data from the device: InertialUnit.
I get a single value in real time, but I need data for the first 10 s and in 1 ms increments, or all the data for the entire cycle of the device. Please help me implement this if possible.
Webots controllers are like any other programs, so you can easily get the values of the inertial unit and save them in a file at each step.
Here is a very simple example in Python:
from controller import Robot
robot = Robot()
inertial_unit = robot.getInertialUnit('inertial unit')
inertial_unit.enable(10)
while robot.step(10) != -1:
values = inertial_unit.getValues()
with open('values.txt','a') as f:
f.write('\n'.join(values))

Devexpress: how to add points to Chart Control at runtime?

i'm trying to build a telemetry software using Winform and Devexpress library. Specifically i'm working on a Line Chart Control and what i would like to do is to configure the chart so that it is able to display a data changing in real time.
The graph is generated reading some external sensors that send informations at a rate of 10 values per second.
This is my code for initialize the chart:
series1 = new Series("test test", ViewType.Line);
chartControl1.Series.Add(series1);
series1.ArgumentScaleType = ScaleType.Numerical;
((LineSeriesView)series1.View).LineMarkerOptions.Kind = MarkerKind.Triangle;
((LineSeriesView)series1.View).LineStyle.DashStyle = DashStyle.Dash;
((XYDiagram)chartControl1.Diagram).EnableAxisXZooming = true;
chartControl1.Legend.Visibility = DefaultBoolean.False;
chartControl1.Titles.Add(new ChartTitle());
chartControl1.Titles[0].Text = "A Line Chart";
chartControl1.Dock = DockStyle.Fill;
And this is the one that add a new point and remove the first point available so that the amount of points in my chart is always the same (after a minimum amount of points is reached) and it keeps updating itself displaying the last X seconds of values and discarding the old values.
series1.Points.RemoveRange(0, 1);
series1.Points.Add(new SeriesPoint(time, value));
...
AxisXRange.SetMinMaxValues(newFirstTime, time);
AxisRange is the following
Range AxisXRange
{
get
{
SwiftPlotDiagram diagram = chartControl1.Diagram as SwiftPlotDiagram;
if (diagram != null)
return diagram.AxisX.VisualRange;
return null;
}
}
**The problem ** is that this code works temporarily. After some seconds, the chart stop working and a big red cross is displayed over it.
Is there something that i'm missing with its configuration?
Do you know any better way to realize my task?
Any help would be appreciated.
Thank you
I think you doing it nearly right. Devexpress has an Article about RealTime-Charts. They doing it the same way but using a timer for updating the data. Maybe this would fix your painting problems.

In Python: Why does a Numpy array returned in a method have to be stored in the instance?

The issue is a bit complicated so I need to give you the full story:
I'm trying to create basic sound using the package pyaudio.
The pyaudio module asks for a callback function that reads audio data.
It basically looks like this:
def callback():
return sound.readframes()
I have a class that provides audio data. It creates a signal by indexing a numpy array that contains a wave length of a basic wave form. It basically looks like this:
class Wave(object):
data = [] # one wavelength of a basic waveform like a sine wave will be stored here
def readframes(self):
indices = # the indices for the next frames
# based on a frequency and the current position
return self.data[indices]
class SineWave(Wave):
data = # points of a sine wave in a numpy array
sound = SineWave()
# pyaudio now reads audio data in a non-blocking callback mode
Now to the problem:
There was noise between each call to readframes or each block of audio data. The sound itself was still intact, but there was an additional clicking. Increasing the size of the returned data block also increased the time between each click. I still don't quite know what caused the noise, but I fixed it by storing the returned numpy array in the instance instead of returning it directly.
This causes noise:
return self.data[indices]
This does not cause noise:
+ self.result = self.data[indices]
+ return self.result
It can't be an alteration of the data that causes the noise or else this wouldn't fix it. Why does the result have to be stored in the instance?
Update:
I also have to mention that the noise doesn't occur everytime I run the script. It occurs randomly about 50% of the runs. Either the noise appears right at the start and won't go away or it doesn't appear at all.
It looks like an issue with the initialization of the sound device, but how that could be related to my fix is a mistery.
Here is code that reproduces the noise problem:
import pyaudio
import time
from numpy import sin, linspace, arange, pi, float32, uint32
SR = 44100 # sampling rate
FPB = 2048 # frames per buffer
class SineWave(object):
"""A sine wave"""
data_size = 2**10
data = sin(linspace(0, 2*pi, data_size, endpoint=False, dtype=float32))
def __init__(self, frequency):
self.pos = 0
self.fq = frequency
self.ppf = self.data_size * self.fq / SR # points per frame
def readframes(self):
size = FPB
pos = self.pos
indices = (arange(pos, size+pos)*self.ppf).astype(uint32) & (self.data_size-1)
self.pos = (self.pos + size) % SR
self.result = self.data[indices]
return self.data[indices]
def callback(in_data, frame_count, time_info, status):
return sound.readframes(), pyaudio.paContinue
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(4),
channels=1,
rate=SR,
output=True,
stream_callback=callback,
frames_per_buffer=FPB)
sound = SineWave(440)
stream.start_stream()
time.sleep(2)
stream.stop_stream()
stream.close()
p.terminate()
On my system the noise appears in about 90% of the runs.
Changing
return self.data[indices]
to
return self.result
fixes it.
There shouldn't be a difference whether you store the intermediate array in the instance or not. I suspect there is some other problem going on that causes the error you're experiencing. Can you provide code that actually runs and exhibits the problem?
If you want to see a (hopefully!) working implementation, have a look at the play() function of the sounddevice module, especially at the loop argument. With this, you should be able to play your waveform repeatedly.
The only thing you need to store in the instance, is the frame index where you left off, just to continue with the following frame index in the next callback (and of course wrap around in the end). You should also consider the case where your wave form is shorter than an audio block. It might even be much shorter. I solved that by using a recursive function call, see the code.
UPDATE:
It's indeed quite strange that assigning to self "solves" your problem. I think this has something to do with how PyAudio interprets the returned array as Python buffer.
You should rewrite your code using the sounddevice module, which properly supports NumPy arrays and has a sane API for the callback function.
It's easy, just use this callback function:
def callback(outdata, frames, time, status):
if status:
print(status)
outdata[:, 0] = sound.readframes()
And start the stream with:
import sounddevice as sd
stream = sd.OutputStream(
channels=1, samplerate=SR, callback=callback, blocksize=FPB)
Apart from that, your code is flawed since it doesn't do any interpolation when reading from the wavetable.

Plotting a word-cloud by date for a twitter search result? (using R)

I wish to search twitter for a word (let's say #google), and then be able to generate a tag cloud of the words used in twitts, but according to dates (for example, having a moving window of an hour, that moves by 10 minutes each time, and shows me how different words gotten more often used throughout the day).
I would appreciate any help on how to go about doing this regarding: resources for the information, code for the programming (R is the only language I am apt in using) and ideas on visualization. Questions:
How do I get the information?
In R, I found that the twitteR package has the searchTwitter command. But I don't know how big an "n" I can get from it. Also, It doesn't return the dates in which the twitt originated from.
I see here that I could get until 1500 twitts, but this requires me to do the parsing manually (which leads me to step 2). Also, for my purposes, I would need tens of thousands of twitts. Is it even possible to get them in retrospect?? (for example, asking older posts each time through the API URL ?) If not, there is the more general question of how to create a personal storage of twitts on your home computer? (a question which might be better left to another SO thread - although any insights from people here would be very interesting for me to read)
How to parse the information (in R)? I know that R has functions that could help from the rcurl and twitteR packages. But I don't know which, or how to use them. Any suggestions would be of help.
How to analyse? how to remove all the "not interesting" words? I found that the "tm" package in R has this example:
reuters <- tm_map(reuters, removeWords, stopwords("english"))
Would this do the trick? I should I do something else/more ?
Also, I imagine I would like to do that after cutting my dataset according to time (which will require some posix-like functions (which I am not exactly sure which would be needed here, or how to use it).
And lastly, there is the question of visualization. How do I create a tag cloud of the words? I found a solution for this here, any other suggestion/recommendations?
I believe I am asking a huge question here but I tried to break it to as many straightforward questions as possible. Any help will be welcomed!
Best,
Tal
Word/Tag cloud in R using "snippets" package
www.wordle.net
Using openNLP package you could pos-tag the tweets(pos=Part of speech) and then extract just the nouns, verbs or adjectives for visualization in a wordcloud.
Maybe you can query twitter and use the current system-time as a time-stamp, write to a local database and query again in increments of x secs/mins, etc.
There is historical data available at http://www.readwriteweb.com/archives/twitter_data_dump_infochimp_puts_1b_connections_up.php and http://www.wired.com/epicenter/2010/04/loc-google-twitter/
As for the plotting piece: I did a word cloud here: http://trends.techcrunch.com/2009/09/25/describe-yourself-in-3-or-4-words/ using the snippets package, my code is in there. I manually pulled out certain words. Check it out and let me know if you have more specific questions.
I note that this is an old question, and there are several solutions available via web search, but here's one answer (via http://blog.ouseful.info/2012/02/15/generating-twitter-wordclouds-in-r-prompted-by-an-open-learning-blogpost/):
require(twitteR)
searchTerm='#dev8d'
#Grab the tweets
rdmTweets <- searchTwitter(searchTerm, n=500)
#Use a handy helper function to put the tweets into a dataframe
tw.df=twListToDF(rdmTweets)
##Note: there are some handy, basic Twitter related functions here:
##https://github.com/matteoredaelli/twitter-r-utils
#For example:
RemoveAtPeople <- function(tweet) {
gsub("#\\w+", "", tweet)
}
#Then for example, remove #d names
tweets <- as.vector(sapply(tw.df$text, RemoveAtPeople))
##Wordcloud - scripts available from various sources; I used:
#http://rdatamining.wordpress.com/2011/11/09/using-text-mining-to-find-out-what-rdatamining-tweets-are-about/
#Call with eg: tw.c=generateCorpus(tw.df$text)
generateCorpus= function(df,my.stopwords=c()){
#Install the textmining library
require(tm)
#The following is cribbed and seems to do what it says on the can
tw.corpus= Corpus(VectorSource(df))
# remove punctuation
tw.corpus = tm_map(tw.corpus, removePunctuation)
#normalise case
tw.corpus = tm_map(tw.corpus, tolower)
# remove stopwords
tw.corpus = tm_map(tw.corpus, removeWords, stopwords('english'))
tw.corpus = tm_map(tw.corpus, removeWords, my.stopwords)
tw.corpus
}
wordcloud.generate=function(corpus,min.freq=3){
require(wordcloud)
doc.m = TermDocumentMatrix(corpus, control = list(minWordLength = 1))
dm = as.matrix(doc.m)
# calculate the frequency of words
v = sort(rowSums(dm), decreasing=TRUE)
d = data.frame(word=names(v), freq=v)
#Generate the wordcloud
wc=wordcloud(d$word, d$freq, min.freq=min.freq)
wc
}
print(wordcloud.generate(generateCorpus(tweets,'dev8d'),7))
##Generate an image file of the wordcloud
png('test.png', width=600,height=600)
wordcloud.generate(generateCorpus(tweets,'dev8d'),7)
dev.off()
#We could make it even easier if we hide away the tweet grabbing code. eg:
tweets.grabber=function(searchTerm,num=500){
require(twitteR)
rdmTweets = searchTwitter(searchTerm, n=num)
tw.df=twListToDF(rdmTweets)
as.vector(sapply(tw.df$text, RemoveAtPeople))
}
#Then we could do something like:
tweets=tweets.grabber('ukgc12')
wordcloud.generate(generateCorpus(tweets),3)
I would like to answer your question in making big word cloud.
What I did is
Use s0.tweet <- searchTwitter(KEYWORD,n=1500) for 7 days or more, such as THIS.
Combine them by this command :
rdmTweets = c(s0.tweet,s1.tweet,s2.tweet,s3.tweet,s4.tweet,s5.tweet,s6.tweet,s7.tweet)
The result:
This Square Cloud consists of about 9000 tweets.
Source: People voice about Lynas Malaysia through Twitter Analysis with R CloudStat
Hope it help!

Resources