WorldViz User Forum

WorldViz User Forum (https://forum.worldviz.com/index.php)
-   Vizard (https://forum.worldviz.com/forumdisplay.php?f=17)
-   -   Flock of Birds question (again) (https://forum.worldviz.com/showthread.php?t=1282)

Elittdogg 11-26-2007 11:37 AM

Flock of Birds question (again)
 
If I collect with the Birds through Vizard, I get a different number of data points each time I run the program. Even if I standardize the collection rate at "(1.0/30)" because I want it to collect at 30 Hz. So I should be getting 1800 data points all of the time. The problem is that sometimes I get 1700, sometimes 1800, often times a completely random value like 1793, etc.

def onkeydown(key):
if key == ' ':
viz.starttimer(0,(1.0/30),viz.FOREVER)
viz.starttimer(4,(1.0/30),viz.FOREVER)
viz.starttimer(3,60,1)

Is this a problem with the code or a processing speed problem? I'm using an old computer (and it happens to be the only one I can use) so if it's a problem with the processing speed of the computer then it could be a problem. Also the way the Birds are hooked up are that all 6 of them can be "plugged into" the other computer (the one with MotionMonitor) but on the computer with Vizard only Bird 1 can be plugged and subsequent birds are read through that. That being said, could that be contributing to a slow processing speed--the fact that everything has to be channelled through 1 Bird?

I hope it's something in the code that I'm missing because that would save me a lot of hassle. So If I'm trying to standardize my data collection and collect at 30 Hz for 60 seconds and get 1800 data points everytime (or at the very least some consistent amount of data points close to 1800) is there something in the code that I'm missing?

Sorry to be long-winded.

Thanks for the help in advance.

farshizzo 11-26-2007 01:02 PM

If you need exactly 1800 samples, then setup a counter that will stop the timer after the specified number of samples have been recorded. Here is some sample code that should show you how it works:
Code:

import viz
viz.go()

MAX_SAMPLES = 1800
SAMPLE_RATE = 1.0 / 30.0

samples = 0
def onTimer(num):
        global samples
        if num == 1:
               
                #TODO: Process sample
               
                #Increment samples
                samples += 1
                if samples < MAX_SAMPLES:
                        viz.starttimer(1,SAMPLE_RATE)
                else:
                        print 'Finished collecting samples'
                       
viz.callback(viz.TIMER_EVENT,onTimer)


def onKeyDown(key):
        global samples
        if key == ' ':
                #Clear samples and start timer
                samples = 0
                viz.starttimer(1,SAMPLE_RATE)

viz.callback(viz.KEYDOWN_EVENT,onKeyDown)


Elittdogg 11-26-2007 01:08 PM

But I also need it to be flexible in the sense that if I collect for one minute so then I get 1800 samples at a rate of 30 Hz, but if I only collect for 30 seconds then I need 900 samples still at a rate of 30 Hz. Likewise if I only collect for 42 seconds at 30 Hz I need 1260 data points. Does this allow for that? Or will it continue to collect until all 1800 samples are obtained?

farshizzo 11-26-2007 01:12 PM

Set the MAX_SAMPLES variable to however many samples you need, it's up to you. If you want to collect for only 45 seconds then set it to the following:
Code:

MAX_SAMPLES = 45 * 30

Elittdogg 11-26-2007 01:21 PM

I got that, but what if I need MAX SAMPLES to be variable...i.e. to be able to be changed depending on how long the participant takes to complete a task. I.e. to make a general code because I won't be able to know how long each trial will last. Trial 1 might last 30s, or 31s, or 27s, or 37s, etc. And there is no way to plan ahead. Or does it have to be fixed beforehand?

farshizzo 11-26-2007 01:24 PM

You can change the value of MAX_SAMPLES anytime you want. If you want to set it in your callback then you can do the following:
Code:

def onKeyDown(key):
        global samples, MAX_SAMPLES
        if key == ' ':
                #Clear samples and start timer
                samples = 0
                MAX_SAMPLES = 45 * 30
                viz.starttimer(1,SAMPLE_RATE)

viz.callback(viz.KEYDOWN_EVENT,onKeyDown)


Elittdogg 11-27-2007 01:00 PM

So with this code would I have to alter the code between each trial? Like if I'm running 10 trials each of which lasts as long as it takes the participant to perform the desired goal-action, would I have to change the max samples in between each trial? Or is there a way to make it such that it collects at a constant collection rate for however long it takes the participant?


Also I don't understand the notation:
MAX_SAMPLES = 45 * 30

What's the * do? Does that mean that it will collect for 45 seconds at a rate of 30Hz? (That's what I gathered from an earlier response of yours). But the issue I will run into with that is that I'm not working with fixed time on any trial and I have no way of knowing exactly how long it will take. (E.g. if people are running from A to B to C to D etc. everyone will take a different amount of time depending on their respective abilities. There's no way to know exactly how long it will take a person to do that beforehand.) This code seems to be predicated on knowing how long the trial will last prior to the onset. Whereas I need to be able to be flexible enough such that whenever the person is done (accomplishes the goal) the collection stops (and that could range anywhere from 5 seconds to 20 minutes).

So maybe is there a way to do: MAX_SAMPLES = N * 30 (where N is however many seconds it takes on that particular trial)?

farshizzo 11-27-2007 04:42 PM

I'm confused, I thought the whole point was that you wanted to collect a preset amount of samples? If the duration of the trial is not known at runtime, then the number of samples to collect cannot be known either.

To answer your other question, the '*' is simply the multiplication operator.

Elittdogg 11-27-2007 06:16 PM

Ok, you're right. Originally I wanted to collect a fixed amount of data points. But then I switched which program I was working on and the new one needs to be flexible depending on how long the trial lasts. Given that....I'm worried that if i'm unable to specify MAX_SAMPLES value then I will get disparate values across the board (i.e. two different independent trials which both happen to be for the same duration may yield different amount of data points (e.g. 2000 vs 1849)). Which is what leads me to think it might be a processing speed issue. Unless, if I'm able to specify the SAMPLE_RATE and that would hold true for all trials then if everything goes smoothly it should collect properly. (i.e. if i can get the Birds to collect at 30 Hz consistently then I don't have any other problem.) My problem was that when I set (what I thought was) the collection rate to 1.0/30: viz.starttimer(0,(1.0/30),viz.FOREVER)
viz.starttimer(4,(1.0/30),viz.FOREVER)

I thought that that would tell Vizard to record data at a rate of 30 Hz. If that's not how I'm supposed to tell the Birds what rate to collect at then that's what I need to know. Namely, all I need is for the Birds to collect at a fixed rate for every trial (and the right (i.e. consistent) amount of total data points should emerge from that every time---without a need to specify MAX_SAMPLES).

Elittdogg 11-28-2007 10:07 AM

So if I define the sample rate but not max samples then it should sample at that rate regardless right? And then data collection would stop whenever the trial ended? So everytime a trial lasted 60 seconds I should get 1800 data points (without having to define max samples). And everytime a trial lasted 30 seconds I should get 900 data points (without having to define max samples)....etc etc etc.????

farshizzo 11-28-2007 10:50 AM

Computers are not %100 perfect when it comes to timing, however you should be able to achieve a reliable sample rate of 30Hz. I did some tests here and I got the same number of samples every time. I don't know why you would get such varying values. Is your simulation running at 60Hz? Do you have a simple script that reproduces your results?

Elittdogg 11-28-2007 01:13 PM

How do I check/make sure it is running at 60Hz?

Reproduces what results?

farshizzo 11-28-2007 01:17 PM

Press the F4 key while your script is running and it will display the framerate in the upper left corner of the window.

I was referring to the results of your script that vary between 1700 to 1800 samples recorded.

Elittdogg 11-29-2007 08:02 AM

When I press F4 the number keeps rapidly changing. It looks like it's fluctuating between 45-55. I don't know what that means but that's what I got. Is it supposed to be stationary? If so, is there a way to fix that value?

Elittdogg 11-29-2007 08:32 AM

Here's the code of what I have:

import viz
import math
import whrandom
import string

viz.go(viz.PROMPT)

# Get subject number from prompt box
promptMesg = viz.get(viz.INITMESG)
if promptMesg == "":
Subnum = 999
Trial = 100

else:
text = string.split(promptMesg)
Subnum = int(text[0])
Trial = int(text[1])

print "Subnum =", Subnum
print "Trial =", Trial

PORT_FOB = 1
NUM_FOB = 6
NUM_DOTS = 900
RADIUS = .5
DATA = 2
AMPLITUDE = .05
X1 = 0
X2 = 64

MAX_SAMPLES = 60.0 * 30.0
SAMPLE_RATE = 1.0 / 30.0
samples = 0

viz.startlayer(viz.POINTS)
viz.vertexcolor(1,1,1)
viz.pointsize(4)

for i in range(0, NUM_DOTS):
x = whrandom.random() - 0.5
y = whrandom.random() - 0.5
z = whrandom.random() - 0.5
length = math.sqrt(x*x + y*y + z*z)
x = x / length * RADIUS
y = y / length * RADIUS
z = z / length * RADIUS
viz.vertex(x, y, z)

sphere = viz.endlayer()
sphere.translate(0,1.8,.2)

flock1 = viz.add('flockofbirds.dls')
#flock2 = viz.add('flockofbirds.dls')
#flock3 = viz.add('flockofbirds.dls')
#flock4 = viz.add('flockofbirds.dls')

flock1.command(6)
#flock2.command(6)
#flock3.command(6)
#flock4.command(6)

tracking_data = open('openloopsine_complex/headdata_'+ str(Subnum) + " " + str(Trial) + '.txt', 'a')
#tracking_data2 = open('openloopsine_complex/hipdata_'+ str(Subnum) + " " + str(Trial) + '.txt', 'a')
#tracking_data3 = open('openloopsine_complex/kneedata_'+ str(Subnum) + " " + str(Trial) + '.txt', 'a')
#tracking_data4 = open('openloopsine_complex/ankledata_'+ str(Subnum) + " " + str(Trial) + '.txt', 'a')

def mytimer(num):
if num == 0:
global AMPLITUDE, TOTALCYCLES, X1, X2, samples

data1 = flock1.get()

HEADLAT = data1[0]
HEADVERT = data1[1]
HEADAP = data1[2]
HEADYAW = data1[3]
HEADPITCH = data1[4]
HEADROLL = data1[5]

head_data = str(Subnum) + '\t' + str(Trial) + '\t' + str(HEADAP) + '\t' +str(HEADLAT) + '\t' +str(HEADVERT) + '\t' +str(HEADYAW) + '\t' +str(HEADPITCH) + '\t' +str(HEADROLL) +'\n'
tracking_data.write(head_data)

if num == 4:
xmove = AMPLITUDE*math.sin(2*(math.pi/180)*X1) + AMPLITUDE*math.sin(2.5*(math.pi/180)*X1) + AMPLITUDE*math.sin(3.5*(math.pi/180)*X1) + AMPLITUDE*math.sin(1.75*(math.pi/180)*X1) + AMPLITUDE*math.sin(2*(math.pi/180)*X1) + AMPLITUDE*math.sin(2.5*(math.pi/180)*X1) + AMPLITUDE*math.sin(3*(math.pi/180)*X1) + AMPLITUDE*math.sin(2.5*(math.pi/180)*X1)+ AMPLITUDE*math.sin(2*(math.pi/180)*X1) + AMPLITUDE*math.sin(1.75*(math.pi/180)*X1)
X1 = X1 + 1
# print xmove
sphere.translate(0,1.8,.2+.3*xmove, viz.ABSOLUTE)

if num == 3:
viz.quit()

if num == 1:

#TODO: Process sample

#Increment samples
samples += 1
if samples < MAX_SAMPLES:
viz.starttimer(1,SAMPLE_RATE)
else:
print 'Finished collecting samples'

viz.callback(viz.TIMER_EVENT,mytimer)

def onkeydown(key):
if key == ' ':
viz.starttimer(0,(1.0/30.0), viz.FOREVER)
#Clear samples and start timer
samples = 0
MAX_SAMPLES = 60 * 30
viz.starttimer(1,SAMPLE_RATE)
viz.starttimer(4,(1.0/30.0),viz.FOREVER)

viz.callback(viz.KEYDOWN_EVENT,onkeydown)

In this instance I need it to collect for 60 seconds at a rate of 30 HZ recording from the birds once I press ' ' at which point everything should start. The field of points should only run for 60 seconds and I need to collect at 30Hz for a total of 1800 points. I ran this once so far and I got 1167 points of data.

Additionally, I also need to be able to not have to specify the amount of time that I'm collecting for or the total number of samples I need but rather JUST the sample rate or collection rate. That way I will consistently collect at 30Hz but the amount of data points will vary given the length of the trial (but in each instance will be a multiple of 30 Hz).

What am I missing/doing wrong/why isn't this working?

farshizzo 11-29-2007 09:25 AM

I cannot run your code because it is not inside the [code][/code] tags. Python code depends on indentation, and posting code without the proper tag loses the indentation.

Either way, I've included a sample script that will manually maintain a proper sample rate. Here is the code:
Code:

import viz
from time import clock
viz.go()

class SampleRate(viz.EventClass):
        def __init__(self,rate,func):
                viz.EventClass.__init__(self)
                self.rate = rate
                self.func = func
                self.lastSampleTime = 0.0
                self.callback(viz.TIMER_EVENT,self.onTimer)

        def onTimer(self,num):
                now = clock()
                while (now - self.lastSampleTime) >= self.rate:
                        self.func()
                        self.lastSampleTime += self.rate
                       
        def start(self):
                self.killtimer(0)
                self.lastSampleTime = clock()
                self.starttimer(0,0,viz.FOREVER)
               
        def stop(self):
                self.killtimer(0)
               

def DoSample():
        #Collect sample here
        pass

#Call function 'DoSample' at rate of '1/30.0'
sampler = SampleRate(1/30.0,DoSample)

#Start the sampler
sampler.start()


farshizzo 11-29-2007 09:28 AM

Also, your framerate should usually be 60. What is your framerate when you run the following basic script?
Code:

import viz
viz.go()


Elittdogg 11-29-2007 10:17 AM

Hopefully you can run it now:

Code:

import viz                                       
import math                                       
import whrandom                       
import string                               

viz.go(viz.PROMPT)                       

# Get subject number from prompt box
promptMesg = viz.get(viz.INITMESG)               
if promptMesg == "":                                       
        Subnum        = 999                                               
        Trial        = 100                                               
       
else:                                                                       
        text = string.split(promptMesg)               
        Subnum = int(text[0])                                 
        Trial = int(text[1])                               
       
print "Subnum =", Subnum                               
print "Trial =", Trial                                       

PORT_FOB = 1
NUM_FOB = 6                                                               
NUM_DOTS = 900                                                       
RADIUS = .5                                                               
DATA = 2                                                               
AMPLITUDE = .05                                                       
X1 = 0                                                                       
X2 = 64                                                                       

MAX_SAMPLES = 60.0 * 30.0
SAMPLE_RATE = 1.0 / 30.0
samples = 0

viz.startlayer(viz.POINTS)                               
viz.vertexcolor(1,1,1)                                       
viz.pointsize(4)                                               

for i in range(0, NUM_DOTS):                       
  x = whrandom.random() - 0.5                       
  y = whrandom.random() - 0.5                       
  z = whrandom.random() - 0.5                       
  length = math.sqrt(x*x + y*y + z*z)       
  x = x / length * RADIUS                               
  y = y / length * RADIUS                               
  z = z / length * RADIUS                               
  viz.vertex(x, y, z)                                       

sphere = viz.endlayer()                                       
sphere.translate(0,1.8,.2)                               

flock1 = viz.add('flockofbirds.dls')       
#flock2 = viz.add('flockofbirds.dls')
#flock3 = viz.add('flockofbirds.dls')       
#flock4 = viz.add('flockofbirds.dls')       

flock1.command(6)                                               
#flock2.command(6)                                               
#flock3.command(6)                                               
#flock4.command(6)                                               

tracking_data = open('openloopsine_complex/headdata_'+ str(Subnum) + " " + str(Trial) + '.txt', 'a')                       
#tracking_data2 = open('openloopsine_complex/hipdata_'+ str(Subnum) + " " + str(Trial) + '.txt', 'a')                       
#tracking_data3 = open('openloopsine_complex/kneedata_'+ str(Subnum) + " " + str(Trial) + '.txt', 'a')                       
#tracking_data4 = open('openloopsine_complex/ankledata_'+ str(Subnum) + " " + str(Trial) + '.txt', 'a')                       

def mytimer(num):                                                               
        if num == 0:                                                               
                global AMPLITUDE, TOTALCYCLES, X1, X2, samples       
               
                data1 = flock1.get()                                                       
                               
                HEADLAT = data1[0]                                                               
                HEADVERT = data1[1]                                                               
                HEADAP = data1[2]                                                               
                HEADYAW = data1[3]                                                               
                HEADPITCH = data1[4]                                                       
                HEADROLL = data1[5]                                                               
       
                head_data = str(Subnum) + '\t' + str(Trial) + '\t' + str(HEADAP) + '\t' +str(HEADLAT) + '\t' +str(HEADVERT) + '\t' +str(HEADYAW) + '\t' +str(HEADPITCH) + '\t' +str(HEADROLL) +'\n'                       
                tracking_data.write(head_data)                                                                                                                                                                                                                                                                                                                               
       
        if num == 4:                                                                                               
                xmove = AMPLITUDE*math.sin(2*(math.pi/180)*X1) + AMPLITUDE*math.sin(2.5*(math.pi/180)*X1) + AMPLITUDE*math.sin(3.5*(math.pi/180)*X1) + AMPLITUDE*math.sin(1.75*(math.pi/180)*X1) + AMPLITUDE*math.sin(2*(math.pi/180)*X1) + AMPLITUDE*math.sin(2.5*(math.pi/180)*X1) + AMPLITUDE*math.sin(3*(math.pi/180)*X1) + AMPLITUDE*math.sin(2.5*(math.pi/180)*X1)+ AMPLITUDE*math.sin(2*(math.pi/180)*X1) + AMPLITUDE*math.sin(1.75*(math.pi/180)*X1)               
                X1 = X1 + 1                                                                                               
#                print xmove
                sphere.translate(0,1.8,.2+.3*xmove, viz.ABSOLUTE)               
               
        if num == 3:                                                       
                viz.quit()                                                       

        if num == 1:
               
                #TODO: Process sample
               
                #Increment samples
                samples += 1
                if samples < MAX_SAMPLES:
                        viz.starttimer(1,SAMPLE_RATE)
                else:
                        print 'Finished collecting samples'
                       
viz.callback(viz.TIMER_EVENT,mytimer)

def onkeydown(key):
        if key == ' ':
                viz.starttimer(0,(1.0/30.0), viz.FOREVER)
                #Clear samples and start timer
                samples = 0
                MAX_SAMPLES = 60 * 30
                viz.starttimer(1,SAMPLE_RATE)
                viz.starttimer(4,(1.0/30.0),viz.FOREVER)

viz.callback(viz.KEYDOWN_EVENT,onkeydown)


Elittdogg 11-29-2007 10:20 AM

When I run that simple script my fram rate is essentially 60 (it constantly changes between 59 and 60).

Elittdogg 11-29-2007 03:04 PM

So now the question is why am I not getting consistent data collection results?

farshizzo 11-29-2007 03:05 PM

I'm not sure, it might be a framerate issue. Did the sample script I posted above give you better results?

Elittdogg 11-30-2007 08:37 AM

The sample script didn't really do anything. Maybe I'm not implementing it correctly, but I can't seem to get consistent results. When I'm running a script other than just that simple script the frame rate fluctuates around 49. Anyway, is there a way that I'm supposed to put your sample script within the code I have to make it work? Because what I did didn't do anything.

farshizzo 11-30-2007 02:45 PM

Did you place your code for collecting samples in the DoSample function? That function will be called at the specified rate.

Elittdogg 12-03-2007 08:39 AM

This is what I did:

Code:

class SampleRate(viz.EventClass):
        def __init__(self,rate,func):
                viz.EventClass.__init__(self)
                self.rate = rate
                self.func = func
                self.lastSampleTime = 0.0
                self.callback(viz.TIMER_EVENT,self.onTimer)

        def onTimer(self,num):
                now = clock()
                while (now - self.lastSampleTime) >= self.rate:
                        self.func()
                        self.lastSampleTime += self.rate
                       
        def start(self):
                self.killtimer(0)
                self.lastSampleTime = clock()
                self.starttimer(0,0,viz.FOREVER)
               
        def stop(self):
                self.killtimer(0)
               

def DoSample():
        #Collect sample here
        flock1 = viz.add('flockofbirds.dls')       
        flock1.command(6)
        tracking_data = open('openloopsine_complex/headdata_'+ str(Subnum) + " " + str(Trial) + '.txt', 'a')
        def mytimer(num):
                if num == 0:
                        global AMPLITUDE, TOTALCYCLES, X1, X2, samples
                       
                        data1 = flock1.get()
                       
                        HEADLAT = data1[0]
                        HEADVERT = data1[1]
                        HEADAP = data1[2]
                        HEADYAW = data1[3]
                        HEADPITCH = data1[4]
                        HEADROLL = data1[5]
                       
                        head_data = str(Subnum) + '\t' + str(Trial) + '\t' + str(HEADAP) + '\t' +str(HEADLAT) + '\t' +str(HEADVERT) + '\t' +str(HEADYAW) + '\t' +str(HEADPITCH) + '\t' +str(HEADROLL) +'\n'
                        tracking_data.write(head_data)       
                if num == 4:
                        xmove = AMPLITUDE*math.sin(2*(math.pi/180)*X1) + AMPLITUDE*math.sin(2.5*(math.pi/180)*X1) + AMPLITUDE*math.sin(3.5*(math.pi/180)*X1) + AMPLITUDE*math.sin(1.75*(math.pi/180)*X1) + AMPLITUDE*math.sin(2*(math.pi/180)*X1) + AMPLITUDE*math.sin(2.5*(math.pi/180)*X1) + AMPLITUDE*math.sin(3*(math.pi/180)*X1) + AMPLITUDE*math.sin(2.5*(math.pi/180)*X1)+ AMPLITUDE*math.sin(2*(math.pi/180)*X1) + AMPLITUDE*math.sin(1.75*(math.pi/180)*X1)
                        X1 = X1 + 1       
                        sphere.translate(0,1.8,.2+.3*xmove, viz.ABSOLUTE)
                if num == 3:
                        viz.quit()       
        pass

#Call function 'DoSample' at rate of '1/30.0'
sampler = SampleRate(1/30.0,DoSample)

#Start the sampler
sampler.start()

viz.callback(viz.TIMER_EVENT,mytimer)

def onkeydown(key):
        if key == ' ':
                viz.starttimer(0,(1.0/30.0), viz.FOREVER)
                viz.starttimer(4,(1.0/30.0),viz.FOREVER)
                viz.starttimer(3,60,1)
viz.callback(viz.KEYDOWN_EVENT,onkeydown)


I think my problem is that I don't know how to embed "mytimer" within "dosample." Because even when I try different indentations it doesn't start at all. And it keeps giving me this error message:
Traceback (most recent call last):
File "", line 12, in ?
File "openloopsine(complex)_adjusted timer3.py", line 111, in ?
viz.callback(viz.TIMER_EVENT,mytimer)
NameError: name 'mytimer' is not defined

So I'm assuming that it's not registering it as it's own identity/function but I'm a bit confused as to how that would work. Would I have to change "dosample" to a class? And if so, would the rest stay the same?

farshizzo 12-04-2007 09:37 AM

You only need to place your timer code inside the DoSample function. Everything else should be outside the function. So it should looke something like this:
Code:

def DoSample():
        global AMPLITUDE, TOTALCYCLES, X1, X2, samples

        data1 = flock1.get()

        HEADLAT = data1[0]
        HEADVERT = data1[1]
        HEADAP = data1[2]
        HEADYAW = data1[3]
        HEADPITCH = data1[4]
        HEADROLL = data1[5]

        head_data = str(Subnum) + '\t' + str(Trial) + '\t' + str(HEADAP) + '\t' +str(HEADLAT) + '\t' +str(HEADVERT) + '\t' +str(HEADYAW) + '\t' +str(HEADPITCH) + '\t' +str(HEADROLL) +'\n'
        tracking_data.write(head_data)



All times are GMT -7. The time now is 02:39 AM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Copyright 2002-2023 WorldViz LLC