Doc_code
 
Cargando...
Buscando...
Nada coincide
gonogo_test.py
Ir a la documentación de este archivo.
1# Importación de librerías necesarias
2import random # Para seleccionar aleatoriamente condiciones
3import pygame # Librería gráfica para mostrar estímulos
4import time # Para medir tiempos y controlar la secuencia temporal
5from pygaze import libscreen, liblog, libinput, eyetracker # Módulos clave de PyGaze
6import constants # Constantes como tamaño de pantalla, etc.
7
8# Inicialización de Pygame (motor gráfico)
9pygame.init()
10
11# Crear una pantalla para mostrar los estímulos
12disp = libscreen.Display()
13
14# Inicializar el eye tracker conectado
15tracker = eyetracker.EyeTracker(disp)
16
17# Crear un detector de teclado para capturar pulsaciones como 'space' y 'escape'
18keyboard = libinput.Keyboard(keylist=['space', 'escape'], timeout=None)
19
20# Crear el archivo de log para guardar los datos del experimento
21log = liblog.Logfile()
22log.write(["trialnr", "trialtype", "targetside", "gaze_endpos", "latency", "correct"])
23
24# Definición de dimensiones y posiciones clave en pantalla
25SCREEN_WIDTH, SCREEN_HEIGHT = 1920, 1800
26CENTER = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
27CENTER1 = (constants.DISPSIZE[0] // 2, constants.DISPSIZE[1] // 2)
28
29# Offset horizontal para colocar los estímulos a izquierda y derecha del centro
30TARGET_OFFSET = 382
31
32# Elegir aleatoriamente un desplazamiento vertical para evitar que el sujeto anticipe la posición
33vertical_offset = random.choice([386, -386])
34
35# Posiciones de los estímulos en la pantalla
36left_pos = (CENTER[0] - TARGET_OFFSET, CENTER[1] + vertical_offset)
37right_pos = (CENTER[0] + TARGET_OFFSET, CENTER[1] + vertical_offset)
38
39# Crear pantalla con instrucciones iniciales
40inscreen = libscreen.Screen()
41inscreen.draw_text(
42 text="Pulsa la tecla ESPACIO para comenzar.",
43 fontsize=40,
44 pos=CENTER,
45 colour=(255, 255, 255),
46)
47
48# Pantalla con la cruz de fijación para centrar la vista del participante
49fixscreen = libscreen.Screen()
50fixscreen.draw_fixation(fixtype='cross', colour=(255, 255, 255), pw=2)
51
52# Crear pantallas para los diferentes tipos de estímulo de inicio (Go, Anti-Go, NoGo)
53signal_screens = {
54 'PS': libscreen.Screen(), # Pro-sácadico → círculo verde
55 'AS': libscreen.Screen(), # Anti-sácadico → círculo rojo
56 'NoGo': libscreen.Screen(), # No mirar → círculo naranja
57}
58signal_screens['PS'].draw_circle(colour=(0, 255, 0), pos=CENTER, r=50)
59signal_screens['AS'].draw_circle(colour=(255, 0, 0), pos=CENTER, r=50)
60signal_screens['NoGo'].draw_circle(colour=(255, 165, 0), pos=CENTER, r=50)
61
62# Crear pantallas para feedback (acierto o error)
63feedbackscreens = {
64 True: libscreen.Screen(),
65 False: libscreen.Screen(),
66}
67feedbackscreens[True].draw_text(text="¡Correcto!", fontsize=40, pos=CENTER, colour=(0, 255, 0))
68feedbackscreens[False].draw_text(text="Incorrecto", fontsize=40, pos=CENTER, colour=(255, 0, 0))
69
70# Mostrar la pantalla de instrucciones y esperar a que se pulse la tecla espacio
71disp.fill(inscreen)
72disp.show()
73keyboard.get_key()
74
75# Número de bloques (con 3 ensayos cada uno: PS, AS, NoGo)
76max_blocks = 30
77
78for block in range(1, max_blocks + 1):
79
80 # Lista con los tres tipos de ensayo
81 trials = ['PS', 'AS', 'NoGo']
82 random.shuffle(trials) # Aleatorizar orden
83
84 for trialnr, trialtype in enumerate(trials, 1):
85
86 # Mostrar cruz de fijación durante 0.5 segundos
87 disp.fill(fixscreen)
88 disp.show()
89 time.sleep(0.5)
90
91 # Mostrar el estímulo de inicio (círculo de color) durante 0.8 segundos
92 disp.fill(signal_screens[trialtype])
93 disp.show()
94 time.sleep(0.8)
95
96 # Determinar aleatoriamente si el estímulo aparecerá a la izquierda o derecha
97 targetside = random.choice(['left', 'right'])
98 target_pos = left_pos if targetside == 'left' else right_pos
99 nontarget_pos = right_pos if targetside == 'left' else left_pos
100
101 # Crear la pantalla con los estímulos en los laterales
102 dualsim_screen = libscreen.Screen()
103
104 # Estímulo objetivo → círculo blanco
105 dualsim_screen.draw_circle(colour=(255, 255, 255), pos=target_pos, r=50)
106
107 # Estímulo distractor → blanco-negro-blanco (como en tareas anti-sácadicas)
108 dualsim_screen.draw_circle(colour=(255, 255, 255), pos=nontarget_pos, r=60)
109 dualsim_screen.draw_circle(colour=(0, 0, 0), pos=nontarget_pos, r=40)
110 dualsim_screen.draw_circle(colour=(255, 255, 255), pos=nontarget_pos, r=20)
111
112 # Mostrar los estímulos y empezar grabación
113 disp.fill(dualsim_screen)
114 disp.show()
115
116 # Comenzar grabación del eye tracker y medir el tiempo
117 tracker.start_recording()
118 t0 = time.time()
119 time.sleep(1.0) # Tiempo disponible para responder
120 tracker.stop_recording()
121
122 # Obtener la última muestra del eye tracker (posición final de la mirada)
123 sample = tracker.sample()
124 endpos = sample[:2] if sample else (CENTER[0], CENTER[1]) # Si no hay muestra, usar centro
125
126 # Calcular la latencia de la respuesta
127 latency = time.time() - t0
128
129 # Verificar si se ha pulsado la tecla escape para salir del experimento
130 key_pressed = keyboard.get_key()
131 if key_pressed == 'escape':
132 tracker.close()
133 disp.close()
134 log.close()
135 exit()
136
137 # Calcular distancia euclidiana entre mirada y los estímulos
138 def euclidean(p1, p2):
139 return ((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2) ** 0.5
140
141 dist_target = euclidean(endpos, target_pos)
142 dist_nontarget = euclidean(endpos, nontarget_pos)
143
144 # Determinar si la respuesta fue correcta
145 if trialtype == 'PS': # Pro-sácadico: mirar al estímulo blanco
146 correct = dist_target < dist_nontarget
147 elif trialtype == 'AS': # Anti-sácadico: mirar al estímulo distractor (opuesto al target)
148 correct = dist_nontarget < dist_target
149 elif trialtype == 'NoGo': # NoGo: no mirar a ninguno
150 correct = dist_target > 150 and dist_nontarget > 150
151
152 # Mostrar feedback de acierto/error durante 0.5 segundos
153 disp.fill(feedbackscreens[correct])
154 disp.show()
155 time.sleep(0.5)
156
157 # Registrar datos del ensayo en el archivo de log
158 log.write([trialnr, trialtype, targetside, endpos, latency, correct])
159
160# Al terminar todos los bloques, cerrar el log y el eye tracker correctamente
161log.close()
162tracker.close()
163disp.close()
euclidean(p1, p2)