Vizard 7 » Tutorials & Examples » Example scripts » Demos » Experiment Design
7.7

Experiment Design

\tutorials\flowControl\experimentDesign.py

Shows how to setup simple trial based experiments and log results to a file.

import viz
import viztask
import vizact
import vizinfo
import vizproximity
import vizshape

viz.setMultiSample(4)
viz.fov(60)
viz.go()

#Set up the environment and proximity sensors

dojo = viz.addChild('dojo.osgb')

#Create proximity manager and set debug on. Toggle debug with d key
manager = vizproximity.Manager()
manager.setDebug(viz.ON)
debugEventHandle = vizact.onkeydown('d',manager.setDebug,viz.TOGGLE)

#Add main viewpoint as proximity target
target = vizproximity.Target(viz.MainView)
manager.addTarget(target)

#fade to true color when viewpoint moves near
def EnterSphere(e, sphere, color):
    sphere.runAction(vizact.fadeTo(color,time=1))

#fade to white when viewpoint moves away
def ExitSphere(e, sphere):
    sphere.runAction(vizact.fadeTo(viz.WHITE,time=1))

#add spheres and create a proximity sensor around each one
sphereSensors = []
def AddSphere(name, color, position):

    sphere = vizshape.addSphere(radius=0.2)
    sphere.setPosition(position)

    sensor = vizproximity.addBoundingSphereSensor(sphere,scale=5)
    sensor.name = name
    sphereSensors.append(sensor)
    manager.addSensor(sensor)

    manager.onEnter(sensor, EnterSphere, sphere, color)
    manager.onExit(sensor, ExitSphere, sphere)

AddSphere('red', viz.RED, [0,1.8,4])
AddSphere('blue', viz.BLUE, [3.5,1.8,2])
AddSphere('yellow', viz.YELLOW, [3.5,1.8,-2])
AddSphere('green', viz.GREEN, [0,1.8,-4])
AddSphere('purple', viz.PURPLE, [-3.5,1.8,-2])
AddSphere('gray', viz.GRAY, [-3.5,1.8,2])

#Add a sensor in the center of the room for the participant to return to after each trial
centerSensor = vizproximity.Sensor(vizproximity.CircleArea(1.5,center=(0.0,0.0)),None)
manager.addSensor(centerSensor)

#Add vizinfo panel to display instructions
info = vizinfo.InfoPanel("Explore the environment\nPress 'd' to toggle the visibility of the sensors\nPress spacebar to begin the experiment")

def participantInfo():

    #Turn off visibility of proximity sensors and disable toggle
    manager.setDebug(viz.OFF)
    debugEventHandle.setEnabled(viz.OFF)

    #Hide info panel currently displayed
    info.visible(viz.OFF)

    #Add an InfoPanel with a title bar
    participantInfo = vizinfo.InfoPanel('',title='Participant Information',align=viz.ALIGN_CENTER, icon=False)

    #Add name and ID fields
    textbox_last = participantInfo.addLabelItem('Last Name',viz.addTextbox())
    textbox_first = participantInfo.addLabelItem('First Name',viz.addTextbox())
    textbox_id = participantInfo.addLabelItem('ID',viz.addTextbox())
    participantInfo.addSeparator(padding=(20,20))

    #Add gender and age fields
    radiobutton_male = participantInfo.addLabelItem('Male',viz.addRadioButton(0))
    radiobutton_female = participantInfo.addLabelItem('Female',viz.addRadioButton(0))
    droplist_age = participantInfo.addLabelItem('Age Group',viz.addDropList())
    ageList = ['20-30','31-40','41-50','51-60','61-70']
    droplist_age.addItems(ageList)
    participantInfo.addSeparator()

    #Add submit button aligned to the right and wait until it's pressed
    submitButton = participantInfo.addItem(viz.addButtonLabel('Submit'),align=viz.ALIGN_RIGHT_CENTER)
    yield viztask.waitButtonUp(submitButton)

    #Collect participant data
    data = viz.Data()
    data.lastName = textbox_last.get()
    data.firstName = textbox_first.get()
    data.id = textbox_id.get()
    data.ageGroup = ageList[droplist_age.getSelection()]

    if radiobutton_male.get() == viz.DOWN:
         data.gender = 'male'
    else:
         data.gender = 'female'

    participantInfo.remove()

    # Return participant data
    viztask.returnValue(data)

def learnPhase():

    #provide instructions for the participant
    info.setText("You'll have 30 seconds to walk around and learn the true color of each sphere")
    info.visible(viz.ON)

    #hide instructions after 5 seconds
    yield viztask.waitTime(5)
    info.visible(viz.OFF)

    #let participant know learning phase has ended
    yield viztask.waitTime(30)
    info.setText("Please return to the center of the room to begin the testing phase")
    info.visible(viz.ON)

    #Start testing phase after 5 seconds
    yield viztask.waitTime(5)

def testPhase():

    results = []
    trials = [3,2,0,4,1]

    for i in trials:

        #Check to see if participant is already in room center. If not
        #wait until the centerSensor is activated
        if centerSensor not in manager.getActiveSensors():
            yield vizproximity.waitEnter(centerSensor)

        #Get sensor for this trial
        sensor = sphereSensors[i]

        #Instruct participant where to go
        instruction = 'Walk to the {} sphere'.format(sensor.name)
        info.setText(instruction)

        #store the time at which this trial started
        startTime = viz.tick()

        #The yielded command returns a viz.Data object with information
        #about the proximity event such as the sensor, target involved
        yield vizproximity.waitEnter(sensor)
        info.setText('Please return to the center of the room')

        #calculate the time it took for the subject to find the correct object
        elapsedTime = viz.tick() - startTime

        #save results
        results.append((sensor.name, elapsedTime))

    info.setText('Thank You. You have completed the experiment')

    #return results
    viztask.returnValue(results)

def experiment():

    #Wait for spacebar to begin experiment
    yield viztask.waitKeyDown(' ')

    #Proceed through experiment phases
    participant = yield participantInfo()
    yield learnPhase()
    results = yield testPhase()

    #Log results to file
    try:
        with open(participant.id + '_experiment_data.txt','w') as f:

            #write participant data to file
            data = "Participant ID: {p.id}\nLast Name: {p.lastName}\nFirst Name: {p.firstName}\nGender: {p.gender}\nAge: {p.ageGroup}\n\n".format(p=participant)
            f.write(data)

            #write result of each trial
            for name,time in results:
                data = "The {} trial took {:.2f} seconds\n".format(name,time)
                f.write(data)
    except IOError:
        viz.logWarn('Could not log results to file. Make sure you have permission to write to folder')

viztask.schedule(experiment)