-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlaunch.py
266 lines (225 loc) · 10.9 KB
/
launch.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
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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
import psutil
import platform
import psychopy
import wx
import traceback
from datetime import datetime
from psychopy import gui, core
from testlist import test_battery, TIME_LIMIT
from setup_console import setup_console
from multiprocessing import freeze_support
from psychopy import logging
VERSION = 'v0.1'
BATTERY_ID = '000000'
def launch():
"""Launch a test battery.
The test battery is stored in testlist.py.
This is to be called from the RT_test folder, otherwise some tests
may not be loaded when they contain a reference to other resources
(like the stimuli list in the VerbCRT).
"""
setup_console()
# This part aims to fix the problem with multitasking when making
# executable using pyinstaller
if getattr(sys, 'frozen', False):
# we are running in a bundle
HOME_FOLDER = os.path.dirname(sys.executable)
else:
# we are running in a normal Python environment
HOME_FOLDER = os.path.dirname(os.path.abspath(__file__))
os.chdir(HOME_FOLDER)
# Make folders and attach output table
if not os.access('data', os.F_OK):
os.mkdir('data')
if os.path.isfile('data/participants.csv'):
try:
out_file = open('data/participants.csv', mode='a')
except:
print('The directory is not writable, cannot write the data')
else:
out_file = open('data/participants.csv', mode='w')
out_file.write('test_mode;id;name;age;sex;status;start_time;end_time;')
for i in test_battery:
out_file.write(i + '_status;' + \
i + '_start_time;' + \
i + '_end_time;')
out_file.write('\n')
# Showing information dialog
intro = u'''
Спасибо, что согласились поучаствовать в исследовании времени реакции!
Предлагаю Вам пройти набор тестов, в которых нужно как можно быстрее и точнее
реагировать на стимулы (изображения или слова).
Время выполнения заданий составляет ~20 минут в демо-версии и ~50 минут в полной версии.
В тесте установлено общее ограничение времени 90 минут. Тест можно прервать во время демонстрации
или между тренировочной и основной сериями, нажав кнопку Y.\
Перед началом тестов программа соберет информацию о характеристиках Вашего компьютера:
- Название операционной системы
- Тип процессора
- Количество оперативной памяти
- Размер и частота обновления экрана
- Используемую версию Питона
Данные и логи записываются в папке data. \
В данный момент батарея находится на стадии тестирования, \
поэтому я буду очень благодарен любой обратной связи. \
Отправляйте обратную связь и результаты из папки data по адресу:
ivan.a.voronin@gmail.com
Страница проекта на гитхабе:
https://github.com/IvanVoronin/RT_tests
С уважением,
Иван Воронин'''
app = wx.App()
intro_dlg = wx.MessageDialog(None,
intro, u'Добро пожаловать',
wx.OK_DEFAULT | wx.CANCEL | wx.OK | wx.ALIGN_LEFT
| wx.ICON_INFORMATION)
resp = intro_dlg.ShowModal()
if resp != wx.ID_OK:
core.wait(1)
core.quit()
sys.exit(0)
# Show the ID questionnaire
info_dlg = gui.Dlg(title=u'Начать эксперимент')
info_dlg.addField(u'ID:', u'0001')
info_dlg.addField(u'Имя:', u'')
info_dlg.addField(u'Дата рождения:', u'01.01.1990')
info_dlg.addField(u'Пол:', choices=[u'Мужской',
u'Женский'])
info_dlg.addField(u'Режим теста:', choices=[u'Демо',
u'Полный'])
info_dlg.addField(u'Я согласен/согласна участвовать', True)
info_dlg.addText(u'\nВыберите тесты для выполнения')
for i in test_battery.keys():
info_dlg.addField(i, True)
# TODO: Make a separate window
info_dlg.addText(u'\nНе забудьте включить английскую расскладку клавиатуры!\n')
info_dlg.show()
if not info_dlg.OK:
core.wait(1)
core.quit()
sys.exit(0)
START_TIME = datetime.now()
(ID, name, age, sex, test_mode, agr), run_tests = \
info_dlg.data[0:6], info_dlg.data[6:]
if not agr:
core.wait(1)
core.quit()
sys.exit(0)
out_file.write(test_mode + ';' +
ID + ';' +
name + ';' +
str(age) + ';' +
sex + ';')
out_dir = START_TIME.strftime('%Y-%m-%d_%H%M__') + str(ID)
os.mkdir('data/' + out_dir)
for test, run in zip(test_battery.values(), run_tests):
if not run:
test.status = 'skipped'
# Log the warnings
# TODO: Log in-test warnings, log interruptions, pauses and demonstrations
logging.console.setLevel(logging.WARNING)
log = logging.LogFile('data/' + out_dir + '/log.log',
level=logging.INFO, filemode='w')
# The same window can be shared by tests
# Here you can put window specifications
test_screen = psychopy.visual.Window(size=(1024, 768),
fullscr=True,
units='pix',
monitor=0, winType='pyglet')
test_screen.winHandle.activate()
test_screen.mouseVisible = False
try:
screen_size = test_screen.size
fps = test_screen.getActualFrameRate()
frame_duration = test_screen.getMsPerFrame()
test_screen.flip()
# Gather system information
with open('data/' + out_dir + '/specs.txt', mode='w') as specs:
specs.write('Platform: %s\n' % platform.platform())
specs.write('Machine: %s\n' % platform.machine())
specs.write('Processor: %s\n' % platform.processor())
specs.write('Number of CPUs: %d\n' % psutil.cpu_count(logical=False))
specs.write('Available CPUs: %d\n' % len(psutil.Process().cpu_affinity()))
specs.write('Current CPU load: %0.1f%%\n' % psutil.cpu_percent())
specs.write('Total RAM: %dMb\n' % int(psutil.virtual_memory().total / (1024 * 1024)))
specs.write('Available RAM: %dMb\n' % int(psutil.virtual_memory().available / (1024 * 1024)))
specs.write('Screen size: %dx%d\n' % tuple(screen_size))
specs.write('FPS: %0.1f\n' % fps)
specs.write('Frame duration: mean=%0.1fms, SD=%0.1fms, median=%0.1fms\n' % frame_duration)
specs.write('Python version: %s\n' % platform.python_version())
specs.write('Python implementation: %s\n' % platform.python_implementation())
specs.write('PsychoPy version: %s\n' % psychopy.__version__)
specs.write('Battery version: %s\n' % VERSION)
specs.write('Battery ID: %s\n' % BATTERY_ID)
except Exception as e:
log.write('EXCEPTION: %s\n' % e)
logging.flush()
# Run the tests, collect stats
skip_the_rest = False
for test in test_battery.itervalues():
if skip_the_rest:
test.status = 'skipped'
if test.status != 'skipped':
log.write('\n======================================================================\n'
+ 'STARTING ' + test.name + '\n')
exc_info = sys.exc_info()
try:
test.start(out_dir, mode=test_mode,
test_screen=test_screen)
except Exception as e:
test.status = 'failed'
test.end_time = datetime.now()
log.write('SOMETHING HAPPENED!\n')
log.write('EXCEPTION: %s\n' % e)
logging.flush()
# If something went wrong we open the test screen again
# FIXME: Probably not working as expected
if test_screen not in locals() or test_screen._closed:
log.write('OPENING A NEW WINDOW\n')
test_screen = psychopy.visual.Window(size=(1024, 768),
fullscr=True,
units='pix',
monitor=0, winType='pyglet')
test_screen.winHandle.activate()
test_screen.mouseVisible = False
logging.flush()
finally:
log.write(traceback.format_exc(exc_info))
del exc_info
log.write('FINISHING ' + test.name
+ '\n======================================================================\n')
else:
test.start_time = datetime.now()
test.end_time = datetime.now()
log.write(test.name + ' SKIPPED\n')
current_dur = test.end_time - START_TIME
if current_dur.seconds/60.0 > TIME_LIMIT:
skip_the_rest = True
log.write('TIME LIMIT REACHED\n')
END_TIME = datetime.now()
BAT_STATUS = all([test.status == 'complete' for test in test_battery.values()])
# TODO: Ввести секретную комбинацию клавиш для определения набора тестов
out_file.write(('complete' if BAT_STATUS else 'incomplete') + ';' +
START_TIME.strftime('%Y-%m-%d %H:%M:%S') + ';' +
END_TIME.strftime('%Y-%m-%d %H:%M:%S') + ';')
for test in test_battery.itervalues():
out_file.write(test.status + ';' +
test.start_time.strftime('%Y-%m-%d %H:%M:%S') + ';' +
test.end_time.strftime('%Y-%m-%d %H:%M:%S') + ';')
out_file.write('\n')
out_file.close()
debriefing = psychopy.visual.TextStim(test_screen,
text=u'\
Благодарим за участие в эксперименте!\n\n\
Окно закроется автоматически')
debriefing.draw()
test_screen.flip()
core.wait(3)
test_screen.close()
core.quit()
if __name__ == '__main__':
freeze_support()
launch()