-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathsubitize.py
More file actions
227 lines (160 loc) · 7.17 KB
/
Copy pathsubitize.py
File metadata and controls
227 lines (160 loc) · 7.17 KB
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# ACT-R tutorial unit3 subitize experiment.
# This experiment displays a number of Xs on
# the screen and the participant must respond
# with how many are there. A human participant
# must press a key from 0-9 (where 0 represents
# 10 items) but a model must speak the count
# (which is how the original experiment was
# performed). The time of the response and its
# correctness are recorded.
# Import the actr module for tutorial tasks
import actr
# Load the corresponding ACT-R starting model.
actr.load_act_r_model("ACT-R:tutorial;unit3;subitize-model.lisp")
# Create some global variables to hold the response
# given and the time it occurred
response = False
response_time = False
# A variable holding the data from the original experiment
exp_data = [.6,.65,.7,.86, 1.12,1.5,1.79,2.13,2.15,2.58]
# Two functions for converting an integer to a string
# as either the word e.g. "one" or the digits e.g. "1"
# for comparison to the response given by a model (spoken)
# or a person (keypress).
def number_to_word (n):
map = ['','one','two','three','four','five','six','seven','eight','nine','ten']
return map[n]
def number_to_string (n):
if n == 10:
return "0"
else:
return str(n)
# The trial function presents one trial of the task.
# It requires one parameter which is the number of items to
# present (should be an integer from 1-10), and has an optional
# parameter which indicates whether it is the model or a person
# performing the task. It returns a list with the time it took
# the participant to respond and True if the response was correct
# or the list [30, False] if the response was incorrect or no
# response was provided.
def trial (n,human=False):
# Reset ACT-R and all models to initial state
actr.reset()
# create some local variables to perform the trial:
# points: is a list of randomized x,y coordinates to display the Xs
# from the generate_points function
# window: an experiment window created to display the task
# start: the current time at the start of the trial
# as given by the ACT-R get_time function which
# needs to be provided whether it is the model or
# a person doing the task to get the appropriate time
points = generate_points(n)
window = actr.open_exp_window("Subitizing Experiment")
start = actr.get_time(not(human))
# Display an x at each of the points
for point in points:
actr.add_text_to_exp_window(window, "x", x=point[0], y=point[1])
# clear the response variables
global response,response_time
response = ''
response_time = False
# Run the trial
if human:
if actr.visible_virtuals_available():
# If a human is doing the task and there is a visible
# window available for them to interact with then
# add a command and monitor the output-key action
actr.add_command("subitize-response",respond_to_key_press,
"Subitize task human response")
actr.monitor_command("output-key","subitize-response")
# Set the correct answer string for a key press
answer = number_to_string(n)
# Wait until there is a response
while response == '':
actr.process_events()
# Stop monitoring output-key and remove the command
actr.remove_command_monitor("output-key","subitize-response")
actr.remove_command("subitize-response")
else:
# If a model is doing the task add a command and
# monitor the output-speech action
actr.add_command("subitize-response",record_model_speech,
"Subitize task model response")
actr.monitor_command("output-speech","subitize-response")
# Set the correct answer string for a spoken response
answer = number_to_word(n)
# Tell the model to interact with the created window
actr.install_device(window)
# Run the model for up to 30 seconds in real time mode
actr.run(30,True)
# Stop monitoring output-speech and remove the command
actr.remove_command_monitor("output-speech","subitize-response")
actr.remove_command("subitize-response")
# If a response is given and it matches the correct answer
# then return a list with the time since the trial started
# in seconds and True, otherwise return a list of 30 and False
if response != '' and response.lower() == answer.lower():
return [(response_time - start) / 1000.0, True]
else:
return [30, False]
# experiment takes one optional parameter which indicates
# whether it is a human or model performing the task. Then it
# presents a trial for each of the counts from 1-10 in a randomized
# order, and passes the results to report_data sorted by item count.
def experiment(human=False):
results = []
for items in actr.permute_list([10,9,8,7,6,5,4,3,2,1]):
results.append((items,trial(items,human)))
results.sort()
report_data(list(map(lambda x: x[1],results)))
# report-data compares the times in the provided data to
# the original experiment data and then passes it to print_results
# for output.
def report_data(data):
rts = list(map(lambda x: x[0],data))
actr.correlation(rts,exp_data)
actr.mean_deviation(rts,exp_data)
print_results(data)
# print_results outputs a table with the times and correctness
# values from the current experiment along with the data from
# the origial experiment.
def print_results(data):
print("Items Current Participant Original Experiment")
for count, d, original in zip(range(len(data)),data,exp_data):
print("%3d %5.2f (%-5s) %5.2f" %
(count+1,d[0],d[1],original))
# The next three functions: generate_points, new_distinct_point, and
# too_close are used to generate a list of random x,y lists for the
# coordinates to display the Xs so that they are within the bounds of
# the window and non-overlapping.
def generate_points(n):
p=[]
for i in range(n):
p.append(new_distinct_point(p))
return p
def new_distinct_point(points):
while True:
x = actr.random(240)+20
y = actr.random(240)+20
if not(any(too_close(x,y,p) for p in points)):
break;
return [x,y]
def too_close (x,y,p):
if (abs(x-p[0]) < 40) and (abs(y-p[1]) < 40):
return True
else:
return False
# respond_to_key_press is monitoring output-key to record
# the current time and key pressed when a human is performing
# the task.
def respond_to_key_press (model,key):
global response,response_time
response_time = actr.get_time(False)
response = key
# record_model_speech is monitoring output-speech to record
# the current time and word spoken when a model is performing
# the task.
def record_model_speech (model,string):
global response,response_time
response_time = actr.get_time(True)
response = string