-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathexample_tachypy.py
210 lines (159 loc) · 6.04 KB
/
example_tachypy.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
import os
import time
import numpy as np
from tachypy import (
Audio,
Screen,
Texture,
Circle,
Rectangle,
FixationCross,
Text,
center_rect_on_point,
ResponseHandler,
fabriquer_gabor,
noisy_bit_dithering
)
# which screen should we draw to?
screen_number = 1
screen = Screen(screen_number=screen_number, fullscreen=True, desired_refresh_rate=60)
# get some relevant screen properties
center_x = screen.width//2
center_y = screen.height//2
# let's initialise our FixationCross
fixation_cross = FixationCross(center=[center_x, center_y], half_width=50, half_height=50, thickness=2.0, color=(255, 0, 0)) # Red cross
# let's add a white circle
circle = Circle(center=(320, 240), radius=50, fill=True, color=(255, 255, 255)) # Green circle
# let's add a nice blue rectangle
# first we can define the rectangle it will strecth to:
a_rect = [center_x+500, 190, center_x+1000, 290]
rectangle = Rectangle(a_rect, fill=True, thickness=1.0, color=(20.0, 50.0, 255.0))
# let's start our audio player
audio_player = Audio(sample_rate=44100, channels=1)
# make a sinewave for the sound
duration = 1.0 # seconds
frequency = 440.0 # Hz (A4 note)
sample_rate = 44100
t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
amplitude = 0.5
waveform = amplitude * np.sin(2 * np.pi * frequency * t).astype(np.float32)
# set the screen's background colour to gray
screen.fill([128, 128, 128])
# flip the screen to make the background color visible
screen.flip()
# check for the screen's actual refresh rate
frame_rate_actual = 1/screen.test_flip_intervals(num_frames=100)
print(frame_rate_actual)
# Initialize ResponseHandler
response_handler = ResponseHandler()
# create a moving Gabor patch animation
nx = 750
frequency_per_im = 10
speed_in_cycles_per_s = 3
nb_frames_per_cycle = int(frame_rate_actual / speed_in_cycles_per_s)
rms_target = 0.08
film = []
for ii in range(nb_frames_per_cycle):
phase = 2 * np.pi * ii / nb_frames_per_cycle
gabor = fabriquer_gabor(nx, frequence=frequency_per_im, phase=phase, angle=np.pi/4, ecart_type=0.2)
gabor = rms_target / np.std(gabor) * (gabor - 0.5) + 0.5
gabor_dithered = noisy_bit_dithering(gabor)
gabor_rgb = np.stack((gabor_dithered,)*3, axis=-1) # could be done in the OpenGL functions, like the colors
# gabor_rgb[:,:,2] = 255 - gabor_rgb[:,:,2]
film.append(gabor_rgb)
# Load stimuli (example: red, green, blue squares)
textures = [Texture(stimulus) for stimulus in film]
# define the position in which the Texture will be mapped.
dest_rect = center_rect_on_point([0, 0, nx-1, nx-1], [center_x, center_y])
# Main loop
running = True
# Track frame timestamps to measure interval consistency
frame_intervals = []
# flip an initial screen and set initial time
start_time = screen.flip()
while running:
for current_trial, texture in enumerate(textures):
screen.fill([128, 128, 128])
# draw a circle
circle.draw()
# draw a rectangle
rectangle.draw()
# draw the texture
texture.draw(dest_rect)
# draw the fixation cross
fixation_cross.draw()
time_stamp = screen.flip()
frame_intervals.append(screen.get_flip_interval())
# Handle events
response_handler.get_events()
if response_handler.should_quit():
running = False
break
# Example: Check if the a key was pressed
if response_handler.is_key_down('a'):
print("a key pressed!")
audio_player.play(waveform)
# Do something in response to the spacebar press
#time.sleep(0.01)
# Create a Text object
dest_rect = center_rect_on_point([0, 0, .85*screen.width, .2*screen.height], [center_x, center_y])
text = Text("Thanks for using tachypy. Here is a long sentence that should be rendered on multiple lines. Only if that is necessary, of course. Press spacebar to continue with this demonstration.",
dest_rect=dest_rect,
font_name='Arial',
font_size=36,
color=(25, 50, 255))
# Clear events before the text is drawn
response_handler.clear_events()
# Draw the text
running = True
while running:
screen.fill((128, 128, 128)) # Gray background
text.draw() # Draw the text
screen.flip()
# Handle events
response_handler.get_events()
if response_handler.should_quit():
running = False
break
# Example: Check if the spacebar was pressed
elif response_handler.is_key_down('space'):
print("Spacebar pressed!")
running = False
break
# Create a Text object
dest_rect = center_rect_on_point([0, 0, .85*screen.width, .2*screen.height], [center_x, center_y])
text = Text("Here is a shorter instruction. Press spacebar to quit.",
dest_rect=dest_rect,
font_name='Arial',
font_size=36,
color=(25, 50, 255))
# Clear events before the text is drawn
response_handler.clear_events()
# Draw the text
running = True
while running:
screen.fill((128, 128, 128)) # Gray background
text.draw() # Draw the text
screen.flip()
# Handle events
response_handler.get_events()
if response_handler.should_quit():
running = False
break
# Example: Check if the spacebar was pressed
elif response_handler.is_key_down('space'):
print("Spacebar pressed!")
running = False
break
# Analyze frame intervals after the loop ends
frame_intervals = np.array(frame_intervals)
average_interval = np.mean(frame_intervals) * 1000 # Convert to milliseconds
std_deviation = np.std(frame_intervals) * 1000 # Convert to milliseconds
print(f"Average frame interval: {average_interval:.4f} ms")
print(f"Standard deviation: {std_deviation:.4f} ms")
# one last flip
screen.flip()
# close the audio player
audio_player.close()
# close the screen
screen.close()