-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathdebug_main.py
155 lines (123 loc) · 4.42 KB
/
debug_main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
"""
Jobs:
Job list curated below:
1. Previous display jobs:
1. Move to window-relative rather than absolute units approach
2. Position grids using normalized, window-relative units
3. Specify stimuli in either pixels or visual angle approach
2. Task jobs:
1. Tidy up spatial rotation task
1. Restructure to use sensible parameter assumptions/passing
2. There's a bug in the algorithm which needs fixing
2. Add the task-switching parameters
1. All stimuli are presented for 500 ms
2. Participants have 2000 ms to answer, before the next trial begins (nonanswered trials count as incorrect)
3. For now, each task should consist of 10 trials before switching
4. The “Next Task:__” cues are either 500 ms or 4000 ms
3. Add instruction slides
4. SAVE the data!
1. Save a CSV representation of the key variables
3. Other
1. Content unit test
2. Package unit test
3. DRY
4. Reorder files
5. Add EEG/fMRI cues (Tibor is on it!)
6. Add an ability to quit the task midway. Tibor and I tried to exit early by pressing esc or exiting the screen, but it would not disappear unless we finished the task.
__________________________________________
"""
import taskSwitching as tS
from psychopy import visual
from pyniexp import scannersynch
import enum
# Set some useful constants
class Config(enum.Enum):
SYNCH_CONFIG = 'config.json'
IN_SCANNER = False
TR = 2 # seconds
MIN_LOG_LEVEL = 'INFO'
class TrialTypes(enum.Enum):
DIGIT_SPAN = "Digit Span"
SPATIAL_SPAN = "Spatial Span"
SPATIAL_ROTATION = "Spatial Rotation"
class InfoCardDurations(enum.Enum):
SHORT = .5
LONG = 4
class RunLength(enum.IntEnum):
MIN = 1
MAX = 3
class Block(enum.IntEnum):
COUNT = 1
TRIAL_COUNT = 9 # if this is not divisible by the number of task types things will go wrong
BREAK_TIME = 5
if __name__ == '__main__':
# Create the window we'll display the experiment in
win = visual.Window(
size=[800, 800],
units="pix",
fullscr=False,
color=[0, 0, 0],
gammaErrorPolicy="warn"
)
# Create interface for scanner pulse and response box
SSO = scannersynch.scanner_synch(
config=Config.SYNCH_CONFIG.value,
emul_synch=not Config.IN_SCANNER.value,
emul_buttons=not Config.IN_SCANNER.value
)
SSO.set_synch_readout_time(0.5)
SSO.TR = Config.TR.value
SSO.set_buttonbox_readout_time(0.5)
if not SSO.emul_buttons:
SSO.add_buttonbox('Nata')
else:
SSO.buttons = ['1','2','3']
SSO.start_process()
# Create the experiment object
exp = tS.Experiment(
window=win,
synch=SSO,
log_level=Config.MIN_LOG_LEVEL.value
)
# Create stimuli. Expect this whole process will eventually be wrapped into the Experiment class
n = Block.TRIAL_COUNT * Block.COUNT
stimuli = {
"SpatialRotation": tS.get_spatial_rotation_stimuli(n)
}
# Define experimental trials using stimuli
sr = [
tS.TrialSpatialRotation(
experiment=exp,
stimulus=stimuli["SpatialRotation"][i]
) for i in range(len(stimuli["SpatialRotation"]))
]
# Currently these need to be in the same order as the magazines defined below.
trials = []
# Construct experimental trial order
for b in range(Block.COUNT): # Blocks
# Stack up the trials into a queue by type
magazines = [[], [], []]
for i in range(int(Block.TRIAL_COUNT)):
magazines[2].insert(i, sr.pop())
t = 0
magazine = 2
while t < Block.TRIAL_COUNT: # Trials
# Create a new run of trials of a random length
# Guard against too large a minimum run length (orphan trials)
run_length = RunLength.MAX
# Create run
# Pop trials from magazine into the block definition
for r in range(run_length): # Runs
trials.append(magazines[magazine].pop())
trials.append(tS.ComponentTrialGap(experiment=exp))
t += run_length
# Add a block break
if b < Block.COUNT - 1:
trials.append(tS.ComponentRest(experiment=exp, break_duration=Block.BREAK_TIME))
# Load trials into the experiment
exp.trials = trials
for t in exp.trials:
t.prepare()
# Run the experiment
exp.synch.wait_for_synch()
exp.run()