...
 
Commits (5)
  • Hao Ting Wang's avatar
    add the sliding scale questions · 2e63ddce
    Hao Ting Wang authored
    2e63ddce
  • Hao Ting Wang's avatar
    add notes on places that needs work · a8091097
    Hao Ting Wang authored
    a8091097
  • Hao Ting Wang's avatar
    variable name · cb9da52b
    Hao Ting Wang authored
    cb9da52b
  • Hao Ting Wang's avatar
    integrate experience sampling · efcc0296
    Hao Ting Wang authored
    Committer: Hao Ting Wang <hw1012@nirem008.ynic.york.ac.uk>
    
    On branch nback_refactor
    Your branch is up-to-date with 'origin/nback_refactor'.
    
    Changes to be committed:
    	modified:   example_trial_generator.py
    	modified:   parameters/ConditionsSpecifications_ES.csv
    	modified:   parameters/TrialSpecifications.csv
    	modified:   run.py
    	modified:   settings.py
    	deleted:    src/_ynicmr.py
    	modified:   src/datastructure/datastructure.py
    	modified:   src/datastructure/stimulus.py
    	renamed:    src/datastructure/trialtype.py -> src/datastructure/trial_library.py
    	modified:   src/experiment.py
    efcc0296
  • Hao Ting Wang's avatar
    visual display · 912f613f
    Hao Ting Wang authored
    Committer: Hao Ting Wang <hw1012@nirem008.ynic.york.ac.uk>
    
    On branch nback_refactor
    Your branch is up-to-date with 'origin/nback_refactor'.
    
    Changes to be committed:
    	deleted:    instructions/exp_instr.txt.save
    	new file:   instructions/exp_instr_es.txt
    	renamed:    instructions/exp_instr.txt -> instructions/exp_instr_nback.txt
    	modified:   run.py
    	modified:   settings.py
    	modified:   src/experiment.py
    912f613f
......@@ -3,46 +3,63 @@ This is an example of how to generate a trial list
all the modules have documentation to some extend
find them by typing ?modulename to the console
set working directory to the task folder before runing this example
set working directory to the task folder before running this example
H.T. Wang
'''
# example 1: build your own
from src.fileIO import write_csv, create_headers
from src.datastructure.stimulus import stimulus_onefeat
from src.fileIO import load_conditions_dict, write_csv, create_headers
from src.datastructure.stimulus import stimulus_onefeat, stimulus_ExpSample
from src.datastructure.datastructure import *
from src.datastructure import trialtype
from src.datastructure import trial_library
# set the two features we used for making the stimulus
shape = ['square', 'triangle', 'circle']
questions, _ = load_conditions_dict('./stimuli/ES_questions.csv')
# load experience sampling quesitons
# locate path of experiment specification related files
condition_path = './parameters/ConditionsSpecifications.csv'
# ConditionsSpecifications.csv:
# original design
# ConditionsSpecifications_ES.csv:
# 0 back condition,
# the experience sampling part has not been implemented yet
# condition_path = './parameters/ConditionsSpecifications.csv'
condition_path = './parameters/ConditionsSpecifications_ES.csv'
trialheader_path = './parameters/TrialHeaders.csv'
trialspec_path = './parameters/TrialSpecifications.csv'
stimulus_dir = './stimuli/'
# column name of trial type names in TrialSpecifications.csv
trialspec_col = 'trial_type'
block = '0'
block = None # accept values: '0', '1', None
# now define the generators
# create experiment parameters
# a 1.5 min block can have 6 catch trials max
parameters = experiment_parameters(block_length=4.5, block_go_n=18, runs=1)
# a 1.5 min block can have 6 catch trials max for a pure 0-/1-back task
# a 12 min block can have 8 go-task trials and 8 experience sampling probes max
# runs - minimum 1;
# please don't change the setting here as there are unresolved bugs
parameters = experiment_parameters(block_length=12, block_go_n=16, runs=1)
parameters.load_conditions(condition_path)
parameters.load_header(trialheader_path)
# create trial finder
find_trial = trial_finder(trialspec_path=trialspec_path, trialspec_col=trialspec_col)
# create stimulus generators
stimulus_generator = stimulus_onefeat(feature=shape)
stimulus_generator = stimulus_onefeat(features=shape)
exp_sample_generator = stimulus_ExpSample(questions)
# now build the trials
builder = trial_builder()
# build the trial generator
trial_generator = builder.build(parameters, find_trial, stimulus_generator, block)
trial_generator = builder.build(parameters, find_trial, stimulus_generator, exp_sample_generator, block)
# use it like this - it's a list of dictionaries
# I would just use these to save participant's output
trials = next(trial_generator)
......@@ -69,4 +86,9 @@ for trial in trials:
# the stimulus is saved as a tuple in the dictionar, use tup2str function in module stimulus
# uncomment the following lines to compare theout put
#
write_csv(fileName='../example.csv', list_headers=parameters.headers, thisTrial=trial)
write_csv(fileName='example_run1.csv', list_headers=parameters.headers, thisTrial=trial)
# to get run two: (only if the setting is on)
# trials = next(trial_generator)
# for trial in trials:
# write_csv(fileName='example_run2.csv', list_headers=parameters.headers, thisTrial=trial)
......@@ -4,20 +4,31 @@ Welcome to our experiment.
In it you will be asked to attend to pairs of different shapes divided by a vertical line in the middle of the screen.
You will only be required to keep your eyes in the centre of the screen and attend to the shapes most of the time.
When a reaction is required, the verticle line will change colour.We refer this as an event.
When a reaction is required, the vertical line will change colour.
The condition will switch between blocks. The two types of conditions are 0-back and 1-back. If the line is {0_back_color}, the trial is a 0-back block. If the line is {1_back_color}, the trial is a 1-back block.
The condition will switch between blocks. The two types of conditions are 0-back and 1-back.
When an event occurs in a 0-back block, the screen displays a pair of shapes and a smaller target item in the middle.
You answer according to the CURRENT screen.
When an event occurs in a 1-back block, the screen displays a pair of "?" and a smaller target item in the middle.
You answer according to the PREVIOUS screen.
There are two type of events, a location event and a recognition event.
If the line is {COLOR_REC}, the trial is a Recognition event - please indicate weather the target is/was presented;
If the line is {COLOR_LOC}, the trial is a Location event - please indicate the location of the target.
You are using key "1" and "2" to indicate LEFT or RIGHT.
You should try to be as quick and accurate as possible.
Press "1" to continue reading.
#
We are interested in the thoughts that you experienced during the rest period.
A list of descriptions and a rating scale will be presented on the screen.
Please use the four buttons to indicate how much each description reflects your experience.
Press "1" to move the tick mark towards 1, indicates "not at all".
Press "2" to move the tick mark towards 10, indicates "completely".
Press "4" to confirm the rating.
When the fixation cross is {COLOR_REC}, the {KEY_REC_0} button indicates {RESP_REC_0}, the {KEY_REC_1} button indicates {RESP_REC_1}.
When the fixation cross is {COLOR_LOC}, When the fixation cross is {COLOR_REC}, the {KEY_REC_0} button indicates {RESP_REC_0}, the {KEY_REC_1} button indicates {RESP_REC_1}.hould try to be as quick and accurate as possible.
Please note that there are no right or wrong answers.
Answer the questions as fast as possible.
Press RETURN to start the task.
Press "1" to start the task.
Condition,GoTrial_1,GoTrial_2
Condition,GoTrial1,GoTrial2
ZeroBack,ZeroBackRecog,ZeroBack
OneBack,OneBackRecog,OneBack
Condition,GoTrial1,GoTrial2
ZeroBack,ZeroBack,ExpSample
OneBack,OneBack,ExpSample
......@@ -3,7 +3,7 @@ OneBack,1,2.5,3.5,5,6,1,1
ZeroBack,1,2.5,3.5,5,6,1,1
Recognition,1,2.5,3.5,5,6,1,1
NoGo,1.5,2.5,0.5,1.5,3,2,5
MWQ,0.5,0.5,2,2,2.5,13,13
ExpSample,0.5,0.5,4,4,4.5,13,13
OneBack_feature,1,2.5,3.5,5,6,1,1
ZeroBack_feature,1,2.5,3.5,5,6,1,1
Recognition_feature,1,2.5,3.5,5,6,1,1
......
......@@ -17,7 +17,7 @@ INFO = {
'Experiment': 'nback_mpsych', # compulsory
'Subject': 'R0001_001', # compulsory
'Run': '1', # compulsory
'Version': ['A', 'B'], # counterbalance the fixation cross
'Version': ['A', 'B'], # counterbalance the fixation color
'N-back': ['0', '1'], # start the task with 1-back or 0-back
'Environment': ['mri', 'lab']
}
......@@ -74,6 +74,7 @@ if __name__ == "__main__":
# create display screens
fixation = fixation_cross(window=Experiment.window, color='black')
stimulus = responsescreen(window=Experiment.window, version=settings)
question = Question(window=Experiment.window, questions=None, color='white')
switch = Text(window=Experiment.window, text='Switch', color='black')
endtxt = open('./instructions/end_instr.txt', 'r').read().split('#\n')[0]
end_msg = visual.TextStim(Experiment.window, text=endtxt, color='black',
......@@ -100,12 +101,17 @@ if __name__ == "__main__":
trial = parse_stimulus_name(trial)
# prepare fixation cross and stimulus display
fixation.set_trial(trial)
stim = get_stim_screen(trial, switch, stimulus)
# show fixation
fix_t = fixation.show(timer)
print(trial['TrialType'])
if trial['TrialType'] == 'ExpSample':
question.set(trial)
start_stim, Resp, rt = question.show(timer)
else:
# show stimulus screen and catch response
stim = get_stim_screen(trial, switch, stimulus)
stim_t, KeyResp, Resp, KeyPressTime, respRT, correct = stim.show(timer)
# show stimulus screen and catch response
stim_t, KeyResp, Resp, KeyPressTime, respRT, correct = stim.show(timer)
# post response fixation
if respRT and trial['stim_duration'] - respRT > 0:
fixation.duration = trial['stim_duration'] - respRT
......
......@@ -4,39 +4,39 @@
Define global and environment-specific settings here.
'''
# there's a bug in datastructure so don't change the next two lines
BLOCK_TIME = 4.5
BLOCK_GO_N = 18
BLOCK_TIME = 12
BLOCK_GO_N = 16
# set the two features we used for making the stimulus
shape = ['square', 'triangle', 'circle']
# texture = ['dot', 'solid', 'stripe']
# locate path of experiment specification related files
condition_path = './parameters/ConditionsSpecifications.csv'
condition_path = './parameters/ConditionsSpecifications_ES.csv'
trialheader_path = './parameters/TrialHeaders.csv'
trialspec_path = './parameters/TrialSpecifications.csv'
stimulus_dir = './stimuli/'
exp_questions_path = './stimuli/ES_questions.csv'
# column name of trial type names in TrialSpecifications.csv
trialspec_col = 'trial_type'
# task instruction
instr_txt = './instructions/exp_instr.txt'
instr_txt = './instructions/exp_instr_es.txt'
# wait trigger screen
ready_txt = './instructions/wait_trigger.txt'
# MRI related settings
dummy_vol = 3
dummy_vol = 0
tr = 2
slice_per_vol = 60
from psychopy import logging
from src.fileIO import write_csv, create_headers
from src.datastructure.stimulus import stimulus_onefeat
from src.fileIO import write_csv, create_headers, load_conditions_dict
from src.datastructure.stimulus import stimulus_onefeat, stimulus_ExpSample
from src.datastructure.datastructure import *
from src.datastructure import trialtype
from src.datastructure import trial_library
# Base settings that apply to all environments.
# These settings can be overwritten by any of the
......@@ -125,6 +125,20 @@ VER_B_MRI = {
'loc_keys': ['1', '2']
}
EXP_SAMPLING_A = {
'0_back_color': 'blue',
'1_back_color': 'red',
'loc_keys': ['1', '2'],
'loc_keyans': ['left', 'right']
}
EXP_SAMPLING_B = {
'0_back_color': 'red',
'1_back_color': 'blue',
'loc_keys': ['1', '2'],
'loc_keyans': ['left', 'right']
}
def get_trial_generator(block):
'''
return a trial generator and a list of data log headers
......@@ -135,17 +149,20 @@ def get_trial_generator(block):
block_length=BLOCK_TIME, block_go_n=BLOCK_GO_N, runs=1)
parameters.load_conditions(condition_path)
parameters.load_header(trialheader_path)
questions, _ = load_conditions_dict('./stimuli/ES_questions.csv')
# create trial finder
find_trial = trial_finder(trialspec_path=trialspec_path, trialspec_col=trialspec_col)
# create stimulus generators
# stimulus_generator = stimulus_twofeat(feature1=shape, feature2=texture)
stimulus_generator = stimulus_onefeat(feature=shape)
stimulus_generator = stimulus_onefeat(features=shape)
exp_sample_generator = stimulus_ExpSample(questions)
# now build the trials
builder = trial_builder()
# build the trial generator
trial_generator = builder.build(parameters, find_trial, stimulus_generator, block)
trial_generator = builder.build(parameters, find_trial, stimulus_generator, exp_sample_generator, block)
return trial_generator, parameters.headers
......@@ -162,9 +179,9 @@ def get_settings(env, ver, test=False):
# display and key press counter balancing
if ver == 'A':
settings.update(VER_A)
settings.update(EXP_SAMPLING_A)
elif ver == 'B':
settings.update(VER_B)
settings.update(EXP_SAMPLING_B)
else:
raise ValueError, 'Version "{0}" not supported.'.format(ver)
......@@ -174,12 +191,7 @@ def get_settings(env, ver, test=False):
# settings.update(DEV)
elif env == 'mri':
settings.update(MRI)
if ver == 'A':
settings.update(VER_A_MRI)
elif ver == 'B':
settings.update(VER_B_MRI)
else:
raise ValueError, 'Version "{0}" not supported.'.format(ver)
else:
raise ValueError, 'Environment "{0}" not supported.'.format(env)
......@@ -202,6 +214,6 @@ def parse_stimulus_name(trial):
if type(trial[key]) is tuple:
trial[key] = tup2str(stimulus_dir, trial[key], '.png')
elif 'stimPic' in key and type(trial[key]) is str:
if trial[key] not in ['?', 'SWITCH']:
if trial[key] in shape:
trial[key] = stimulus_dir + trial[key] + '.png'
return trial
# -*- coding: utf-8 -*-
'''
Usful functions for collecting trigger at YNiC
and using serial port to collect participant responses
'''
# YNiC fMRI trigger related information
import sys
import serial
if sys.platform == 'linux2':
# in house script ynicstim location
YNICSTIM = '/groups/stimpc/ynicstim'
SERIAL_PORT = '/dev/ttyS0'
else:
YNICSTIM = 'M:/stimpc/ynicstim'
SERIAL_PORT = 'COM1'
TRIG_PORT = '/dev/parport0'
SLICESPERVOL = 60 # check this information with Charlotte
DUMMY_VOL = 3
sys.path.append(YNICSTIM)
from ynicstim import parallel_compat, trigger
# from src.fileIO import read_only
def get_trig_collector():
p = parallel_compat.getParallelPort(TRIG_PORT)
ts = trigger.ParallelInterruptTriggerSource(port=p)
trig_collector = trigger.TriggerCollector(triggersource=ts,
slicespervol=SLICESPERVOL)
return trig_collector
def save_vol_time(trig_collector, timer, path):
trig_collector.endCollection()
vol_time = trig_collector.getVolumeTimings(timer)
with open(path, 'w+') as f:
f.write('Volume,Time\n')
for i, t in enumerate(vol_time):
f.write('{:d},{:.3f}\n'.format(i, t))
# read_only(path)
resp_device = serial.Serial(SERIAL_PORT, 9600, timeout=0.001)
def get_serial(timer, resp_device):
KeyResp = resp_device.read(1)
KeyPressTime = timer.getTime()
if len(KeyResp) == 0:
KeyResp = None
KeyPressTime = np.nan
else:
# Map button numbers to side
## Blue == 1, Green == 3
if KeyResp in ['1', '3']:
KeyResp = 'left'
elif KeyResp in ['2', '4']:
KeyResp = 'right'
return KeyResp, KeyPressTime
......@@ -8,8 +8,8 @@ import codecs
import csv
from random import randrange, shuffle, randint, choice
from . import trialtype
from .trialtype import *
from . import trial_library
from .trial_library import *
from ..fileIO import *
......@@ -68,8 +68,8 @@ class experiment_parameters(object):
a list of counters for the number of catch trial type 1 to n
'''
time = self.block_length * 60
trialtype_n = len(self.conditions[0]) - 1
go_n = [self.block_go_n / trialtype_n] * trialtype_n
trial_library_n = len(self.conditions[0]) - 1
go_n = [self.block_go_n / trial_library_n] * trial_library_n
return time, go_n
......@@ -98,6 +98,7 @@ class trial_finder(object):
reader = csv.DictReader(f)
#loop through csv list
for row in reader:
# first convert strings to float
for item in row.keys():
row[item] = str2float(row[item])
......@@ -105,8 +106,7 @@ class trial_finder(object):
# if current rows trial type is equal to input, print that row
if trial_type == row[self.trialspec_col]:
trial_spec = row
trial_mod = getattr(trialtype, trial_type)
trial_mod = getattr(trial_library, trial_type)
return trial_mod(trial_spec=trial_spec, lst_header=None)
else:
......@@ -161,10 +161,10 @@ class trial_builder(object):
the csv file entries should not use numbers (i.e.1 and 0)
otherwise the behaviour will not work as expected
block: None, '0', '1'
no sequence assigned, starting from 1 back, starting from 0 back
block: '0', '1'
starting from 1 back, starting from 0 back
return
condition, shuffled: lst
conditions, shuffled: lst
'''
if block == '1':
# use Ordereddict form python in-built library `collections`
......@@ -174,7 +174,8 @@ class trial_builder(object):
conditions = sorted(conditions,
reverse=True, key=lambda t: t['Condition'])
else:
shuffle(conditons)
pass # low priority to-do: shuffle the conditions
return conditions
def block_trials(self, trial_finder, block, trial_headers):
......@@ -196,10 +197,10 @@ class trial_builder(object):
trial_NoGo = trial_finder.get(trial_type='NoGo')
trial_NoGo.lst_header = trial_headers
trial_Go1 = trial_finder.get(trial_type=block['GoTrial_1'])
trial_Go1 = trial_finder.get(trial_type=block['GoTrial1'])
trial_Go1.lst_header = trial_headers
trial_Go2 = trial_finder.get(trial_type=block['GoTrial_2'])
trial_Go2 = trial_finder.get(trial_type=block['GoTrial2'])
trial_Go2.lst_header = trial_headers
trial_Go = [trial_Go1, trial_Go2]
......@@ -239,8 +240,11 @@ class trial_builder(object):
self.dict_trials.append(cur_trial)
self.last_trial = cur_trial
def build(self, experiment_parameters, trial_finder, stimulus_generator, block):
def build(self, experiment_parameters, trial_finder, \
stimulus_generator, expsampling_generator, block):
'''
This feature doesn't integrate experience sampling for now
now let's build the trial generator
experiment_parameters: obj
......@@ -268,13 +272,13 @@ class trial_builder(object):
init_task_t, init_go_n = experiment_parameters.create_counter()
for block in blocks:
self.initialise(init_task_t, [9, 9]) # HW- hard coding go_n this for now
self.initialise(init_task_t, [8, 8]) # HW- hard coding go_n this for now
# get the specific go trials according to the block you are in
trial_NoGo, trial_Go = self.block_trials(
trial_finder, block, experiment_parameters.headers)
self.trial_index = trial_idx_tmp
print self.trial_index
while self.task_t != 0: # start counting
for i in range(experiment_parameters.block_go_n):
# get no-go trial number
......@@ -287,19 +291,33 @@ class trial_builder(object):
last_trial=self.last_trial))
self.task_t -= t
self.save_trial(cur_trial, block['Condition'])
# generate the go trial
# go trial: type 1 or type 2
# see which go trial type were all used
# need to integrate experience sampling here
use_go = [i for i, e in enumerate(self.go_n) if e > 0]
if use_go:
# select a random one from the avalible ones
# select a random one from the available ones
idx = choice(use_go)
cur_trial, t = next(trial_Go[idx].generate_trial(
if trial_Go[idx].__class__.__name__=='ExpSample':
# if it's experience sampling
cur_trial, t = next(trial_Go[idx].generate_trial(
stimulus_generator=expsampling_generator,
last_trial=self.last_trial)) # n-back
for trial in cur_trial:
self.task_t -= t[0]
self.save_trial(trial, block['Condition'])
else:
cur_trial, t = next(trial_Go[idx].generate_trial(
stimulus_generator=stimulus_generator,
last_trial=self.last_trial)) # n-back
self.task_t -= t
self.task_t -= t
self.save_trial(cur_trial, block['Condition'])
self.go_n[idx] -= 1
self.save_trial(cur_trial, block['Condition'])
# add 1~ 2 no-go trials and then a switch screen to end this block
for k in range(randrange(1, 3, 1)):
......@@ -320,11 +338,11 @@ class trial_builder(object):
self.save_trial(cur_trial, 'Switch')
if self.task_t != 0:
# if this list of trials is not good for the block, restart
self.initialise(init_task_t, [9, 9])# HW- hard coding go_n this for now
self.initialise(init_task_t, [8, 8])# HW- hard coding go_n this for now
self.trial_index = trial_idx_tmp
else:
# if it's good save this block to the run
print 'save this block'
print('save this block')
run += self.dict_trials
trial_idx_tmp = self.trial_index
yield run
......
......@@ -7,10 +7,30 @@ stimulus feature generator
from random import shuffle, randint
from itertools import product
class stimulus_ExpSample(object):
'''
experience sampling stimulus generator
save features and generate stimuli
features: list, dictionaries of questions
'''
def __init__(self, features):
'''split questions into two sets'''
self.q_focus = [features[0]] # the focus question stays at the top
self.q_others = features[1:]
def generate(self):
'''yield self.stimuli'''
shuffle(self.q_others)
yield self.q_focus + self.q_others
class stimulus_twofeat(object):
'''
double feature stimulus generator
save features and genenrate stimuli pair
feature1, feature2 : list, features of stimulus
......@@ -32,11 +52,12 @@ class stimulus_twofeat(object):
yield [item_left, item_right]
class stimulus_twofeat_mix(object):
'''
double feature stimulus generator with mixed congurency
The stimulis pair can share one feature or no feature.
save features and genenrate stimuli pair
feature1, feature2 : list, features of stimulus
......@@ -58,16 +79,17 @@ class stimulus_twofeat_mix(object):
yield [item_left, item_right]
class stimulus_onefeat(object):
'''
single feature stimulus generator
save features and genenrate stimuli
feature1, feature2 : list, features of stimuli
features: list, features of stimuli
'''
def __init__(self, feature):
self.stimuli = feature
def __init__(self, features):
self.stimuli = features
def generate(self):
'''
......@@ -82,15 +104,15 @@ class stimulus_onefeat(object):
def tup2str(dir_path, tuple_stim, filesuffix):
'''
trun tuple to a string (filename)
the filename must look like:
the filename must look like:
feature1_feature2.png
dir_path: str
example: './stimulus/'
tuple_stim: tuple
stimulus, ('feature1', 'feature2')
filesuffix: str
expample '.png'
......
......@@ -12,6 +12,70 @@ from random import choice, shuffle, uniform
from ..fileIO import create_headers
class ExpSample(object):
'''
generate a experience sampling trial detail
trial_spec: dict
trial specification
lst_header: list
headers for generating dictionary to store trial details
'''
def __init__(self, trial_spec, lst_header):
self.trial_spec = trial_spec
self.lst_header = lst_header
def generate_trial(self, stimulus_generator, last_trial):
'''
a generater that creates trials
stimulus_generator: generator
stimulus generator
the output of the generator is a list of dictionaries
the header of the dictionaries are
"Item", "Question", "Scale_low", "Scale_high"
last_trial: dict
the previous trial; some trials need this information
if it's a experience sampling question,
zero-back or no-go trial, None type is accepted
output
dict_rows: a list of dict
a list of trials in dictionary
trial_time: a list of float
total time of each trial, for counter
'''
items = next(stimulus_generator.generate())
dict_rows = []
trial_time = []
for item in items:
dict_row = {key: None for key in self.lst_header}
dict_row['TrialIndex'] = None
dict_row['Condition'] = None
dict_row['TrialType'] = self.trial_spec['trial_type']
dict_row['fix_duration'] = uniform(self.trial_spec['fix_t_min'], self.trial_spec['fix_t_max'])
dict_row['stim_duration'] =self.trial_spec['trial_t_total'] - dict_row['fix_duration']
dict_row['stimPicLeft'] = item['Scale_low']
dict_row['stimPicRight'] = item['Scale_high']
dict_row['Ans'] = None
dict_row['stimPicMid'] = item['Item']
dict_rows.append(dict_row)
trial_time.append(self.trial_spec['trial_t_total'])
yield dict_rows, trial_time
class NoGo(object):
'''
generate a one back trial detail
......
......@@ -4,6 +4,9 @@
experiemnt stimulus here
'''
from psychopy import core, data, gui, visual, event, logging
from pyglet.window import key
import os
from src.fileIO import *
from random import uniform, shuffle
......@@ -136,6 +139,7 @@ class responsescreen(object):
if 'NoGo'in trial['TrialType']:
self.line.fillColor = 'black'
self.dash.fillColor = 'black'
elif 'Recog' in trial['TrialType']:
self.line.fillColor = self.version['rec_color']
self.dash.fillColor = self.version['rec_color']
......@@ -143,11 +147,19 @@ class responsescreen(object):
self.keyans = self.version['rec_keyans']
elif 'Back' in trial['TrialType']:
self.line.fillColor = self.version['loc_color']
self.dash.fillColor = self.version['loc_color']
if 'Zero' in trial['TrialType']:
self.line.fillColor = self.version['0_back_color']
self.dash.fillColor = self.version['0_back_color']
elif 'One' in trial['TrialType']:
self.line.fillColor = self.version['1_back_color']
self.dash.fillColor = self.version['1_back_color']
else:
self.line.fillColor = self.version['loc_color']
self.dash.fillColor = self.version['loc_color']
self.keylist = self.version['loc_keys']
self.keyans = self.version['loc_keyans']
if '?' == trial['stimPicLeft']:
self.present_left = self.quest_left
self.present_right = self.quest_right
......@@ -211,10 +223,85 @@ class responsescreen(object):
return start_trial, KeyResp, Resp, KeyPressTime, respRT, correct
# class question(object):
# '''
# collect mind wandering report
# '''
class Question(object):
'''
collect mind wandering report
'''
def __init__(self, window, questions, color):
'''Initialize a question stimulus.
Args:
window - The window object
questions - a list of dictionaries
keys - list of keys to press to continue to next stimulus. If None,
will automatically go to the next stimulus.
Additional args and kwargs are passed to the visual.TextStim
constructor.
'''
self.window = window
self.description = visual.TextStim(self.window, text=None, height=34,
wrapWidth=1100, color=color, font=sans)
self.scale_l = visual.TextStim(self.window, text=None, height=34,
wrapWidth=1100, pos=[-300,-150],color=color, font=sans)
self.scale_h = visual.TextStim(self.window, text=None, height=34,
wrapWidth=1100, pos=[300,-150],color=color, font=sans)
self.questions = questions
self.rating = visual.RatingScale(self.window, low=1, high=10, markerStart=5,
precision=10, tickMarks=[1, 10],
leftKeys='1', rightKeys='2', acceptKeys='4')
def set(self, trial):
self.description.setText(trial['stimPicMid'])
self.scale_l.setText(trial['stimPicLeft'])
self.scale_h.setText(trial['stimPicRight'])
if trial['stim_duration']:
self.scale_max_time = trial['stim_duration']
else:
self.scale_max_time = 90
def show(self, clock):
keyState=key.KeyStateHandler()
self.window.winHandle.push_handlers(keyState)
self.description.draw()
self.scale_l.draw()
self.scale_h.draw()
self.rating.draw()
self.window.flip()
start_trial = clock.getTime()
pos = self.rating.markerStart
inc = 0.1
while (self.rating.noResponse
and clock.getTime() - start_trial < self.scale_max_time):
if event.getKeys(keyList=['escape']):
print('user quit')
core.quit()
if keyState[key._1] is True:
pos -= inc
elif keyState[key._2] is True:
pos += inc
if pos > 9:
pos = 9
elif pos < 0:
pos = 0
self.rating.setMarkerPos(pos)
self.description.draw()
self.scale_l.draw()
self.scale_h.draw()
self.rating.draw()
self.window.flip()
score = self.rating.getRating()
rt = self.rating.getRT()
self.rating.reset()
return start_trial, score, rt
def get_keyboard(timer, respkeylist, keyans):
'''
......@@ -263,19 +350,24 @@ class instructions(object):
I hard coded the part with text needs changing.
Will need to change this in the future
'''
self.instruction_txt[2] = self.instruction_txt[2].replace(
'{COLOR_REC}', self.settings['rec_color'].upper())
self.instruction_txt[2] = self.instruction_txt[2].replace(
'{COLOR_LOC}', self.settings['loc_color'].upper())
self.instruction_txt[2] = self.instruction_txt[2].replace(
'{KEY_REC_0}', self.settings['rec_keys'][0].upper())
self.instruction_txt[2] = self.instruction_txt[2].replace(
'{KEY_REC_1}', self.settings['rec_keys'][1].upper())
self.instruction_txt[2] = self.instruction_txt[2].replace(
'{KEY_LOC_0}', self.settings['loc_keys'][0].upper())
self.instruction_txt[2] = self.instruction_txt[2].replace(
'{KEY_LOC_1}', self.settings['loc_keys'][1].upper())
# self.instruction_txt[2] = self.instruction_txt[2].replace(
# '{COLOR_REC}', self.settings['rec_color'].upper())
# self.instruction_txt[2] = self.instruction_txt[2].replace(
# '{COLOR_LOC}', self.settings['loc_color'].upper())
# self.instruction_txt[2] = self.instruction_txt[2].replace(
# '{KEY_REC_0}', self.settings['rec_keys'][0].upper())
# self.instruction_txt[2] = self.instruction_txt[2].replace(
# '{KEY_REC_1}', self.settings['rec_keys'][1].upper())
# self.instruction_txt[2] = self.instruction_txt[2].replace(
# '{KEY_LOC_0}', self.settings['loc_keys'][0].upper())
# self.instruction_txt[2] = self.instruction_txt[2].replace(
# '{KEY_LOC_1}', self.settings['loc_keys'][1].upper())
self.instruction_txt[1] = self.instruction_txt[1].replace(
'{0_back_color}', self.settings['0_back_color'].upper())
self.instruction_txt[1] = self.instruction_txt[1].replace(
'{1_back_color}', self.settings['1_back_color'].upper())
return self.instruction_txt
def show(self):
......
Item,Question,Scale_low,Scale_high
My thought was on task:,Focus,Not at all,Completely
My thoughts involved future events:,Future,Not at all,Completely
My thoughts involved past events:,Past,Not at all,Completely
My thoughts involved myself:,Self,Not at all,Completely
My thoughts involved other people:,Other,Not at all,Completely
The emotion of my thoughts was:,Emotion,Negative,Positive
My thoughts were in the form of:,Modality,Images,Words
My thoughts were detailed and specific:,Detailed,Not at all,Completely
My thoughts were:,Deliberate,Spontaneous,Deliberate
I was thinking about solutions to problems (or goals):,Problem,Not at all,Completely
My thoughts were:,Diversity,One topic,Many topics
My thoughts were intrusive:,Intrusive,Not at all,Completely
My thoughts were linked to information from:,Source,Environment,Memory