Commit 657966b4 by Laura Rodríguez

16 jun 2

parent 8d5ca3d0
...@@ -654,49 +654,47 @@ def open_results_file(): ...@@ -654,49 +654,47 @@ def open_results_file():
# ============ TEST BATERIA =================== # ============ TEST BATERIA ===================
def run_bateria_test(self): def run_bateria_test(self):
import pygame
from random import choice
from pygaze import libscreen, liblog
from pygaze.keyboard import Keyboard
import constants
from pygaze.display import Display
from pygaze.eyetracker import EyeTracker
pygame.init() pygame.init()
self.disp = libscreen.Display(bgcolor=(0, 0, 0)) # abro display de nuevo
while True:
self.disp = libscreen.Display(bgcolor=(0, 0, 0)) # Abrir pantalla
log = liblog.Logfile() log = liblog.Logfile()
log.write(["trialnr", "trialtype", "targetside", "gaze_endpos", "latency", "correct"]) log.write(["trialnr", "trialtype", "targetside", "gaze_endpos", "latency", "correct"])
kb = Keyboard()
tracker = EyeTracker(self.disp)
# Constantes
SCREEN_WIDTH, SCREEN_HEIGHT = constants.DISPSIZE SCREEN_WIDTH, SCREEN_HEIGHT = constants.DISPSIZE
CENTER = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2) CENTER = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
TARGET_OFFSET = 382 TARGET_OFFSET = 382
left_pos = (CENTER[0] - TARGET_OFFSET, CENTER[1]) left_pos = (CENTER[0] - TARGET_OFFSET, CENTER[1])
right_pos = (CENTER[0] + TARGET_OFFSET, CENTER[1]) right_pos = (CENTER[0] + TARGET_OFFSET, CENTER[1])
center = CENTER
arrow_length = 100
arrow_color = (255, 255, 255)
n_trials = 5
blackscreen = libscreen.Screen() # Pantalla de instrucciones
blackscreen.clear(colour=(0, 0, 0))
inscreen = libscreen.Screen() inscreen = libscreen.Screen()
inscreen.clear(colour=(0, 0, 0)) inscreen.clear(colour=(0, 0, 0))
ins_text = (
"INSTRUCCIONES DETALLADAS:\n\n"
fixscreen = libscreen.Screen() "🟢 Círculo VERDE: mira al CÍRCULO GRANDE en la dirección que indica la flecha.\n"
fixscreen.clear(colour=(0, 0, 0)) "🔴 Círculo ROJO: mira al CÍRCULO PEQUEÑO, en dirección contraria a la flecha.\n"
fixscreen.draw_fixation(fixtype='cross', diameter=57, pos=CENTER, colour=(255, 255, 255)) "🟠 Círculo NARANJA: NO muevas la vista, mantén la mirada en el centro.\n\n"
"Pulsa ESPACIO para comenzar la prueba.\n"
signal_screens = { "Pulsa E para salir."
'PS': libscreen.Screen(), )
'AS': libscreen.Screen(), inscreen.draw_text(text=ins_text, fontsize=30, pos=CENTER, colour=(255, 255, 255), center=True)
'NoGo': libscreen.Screen()
}
for key, color in [('PS', (0, 255, 0)), ('AS', (255, 0, 0)), ('NoGo', (255, 165, 0))]:
signal_screens[key].clear(colour=(0, 0, 0))
signal_screens[key].draw_circle(pos=CENTER, r=38, fill=True, colour=color)
feedbackscreens = {
1: libscreen.Screen(),
0: libscreen.Screen()
}
feedbackscreens[1].clear(colour=(0, 0, 0))
feedbackscreens[1].draw_text(text='Correcto', fontsize=30, pos=CENTER, colour=(0, 255, 0), center=True)
feedbackscreens[0].clear(colour=(0, 0, 0))
feedbackscreens[0].draw_text(text='Incorrecto', fontsize=30, pos=CENTER, colour=(255, 0, 0), center=True)
self.disp.fill(inscreen) self.disp.fill(inscreen)
self.disp.show() self.disp.show()
...@@ -710,120 +708,101 @@ def run_bateria_test(self): ...@@ -710,120 +708,101 @@ def run_bateria_test(self):
pygame.quit() pygame.quit()
return return
# Orden fijo de las pruebas: screen = libscreen.Screen()
fixed_trialtypes = ['PS', 'AS', 'NoGo', 'AS', 'NoGo']
results = []
try: def wait_with_exit(seconds):
for trialnr, trialtype in enumerate(fixed_trialtypes, start=1): start = pygame.time.get_ticks()
while (pygame.time.get_ticks() - start) < seconds * 1000:
for event in pygame.event.get(): for event in pygame.event.get():
if event.type == pygame.KEYDOWN and event.key == pygame.K_e: if event.type == pygame.KEYDOWN and event.key == pygame.K_e:
raise KeyboardInterrupt pygame.quit()
exit()
# Mostrar instrucción previa según tipo de prueba
instruction_text = "" for trial in range(n_trials):
if trialtype == 'PS': # Mensaje previo
instruction_text = "Mira al círculo GRANDE" screen.clear(colour=(0, 0, 0))
elif trialtype == 'AS': screen.draw_text(f"Trial {trial + 1} de {n_trials}\nPulsa E para salir o espera para comenzar...",
instruction_text = "Mira al círculo PEQUEÑO" fontsize=30, colour=(255, 255, 255))
elif trialtype == 'NoGo': self.disp.fill(screen)
instruction_text = "NO mires ningún círculo\nMantente en el centro"
trial_instruction = libscreen.Screen()
trial_instruction.clear(colour=(0, 0, 0))
trial_instruction.draw_text(text=instruction_text, fontsize=40, pos=CENTER, colour=(255, 255, 255), center=True)
self.disp.fill(trial_instruction)
self.disp.show()
time.sleep(1.5)
# Mostrar cruz de fijación
self.disp.fill(fixscreen)
self.disp.show() self.disp.show()
libtime.pause(random.randint(750, 1250)) wait_with_exit(2.0)
# Esperar que el usuario presione espacio # Dirección y condición
waiting = True direction = choice(["left", "right"])
while waiting: condition = choice(["pro", "anti", "nogo"])
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
waiting = False
elif event.key == pygame.K_e:
raise KeyboardInterrupt
time.sleep(0.2) if condition == "pro":
central_color = (0, 255, 0)
self.tracker.start_recording() elif condition == "anti":
central_color = (255, 0, 0)
# Mostrar señal central de color else:
self.disp.fill(signal_screens[trialtype]) central_color = (255, 165, 0)
self.disp.show()
time.sleep(0.8)
self.disp.fill(blackscreen) # Estímulo central
screen.clear(colour=(0, 0, 0))
screen.draw_circle(colour=central_color, pos=center, r=28, fill=True)
self.disp.fill(screen)
self.disp.show() self.disp.show()
time.sleep(0.2) wait_with_exit(1.0)
targetside = random.choice(['left', 'right']) # Flechas y círculos
target_pos = left_pos if targetside == 'left' else right_pos screen.clear(colour=(0, 0, 0))
nontarget_pos = right_pos if targetside == 'left' else left_pos screen.draw_circle(colour=central_color, pos=center, r=28, fill=True)
dualstim_screen = libscreen.Screen() if direction == "left":
dualstim_screen.clear(colour=(0, 0, 0)) big_circle_pos = left_pos
dualstim_screen.draw_circle(pos=nontarget_pos, r=28, fill=True, colour=(255, 255, 255)) small_circle_pos = right_pos
dualstim_screen.draw_circle(pos=target_pos, r=38, fill=True, colour=(255, 255, 255)) else:
dualstim_screen.draw_circle(pos=target_pos, r=32, fill=True, colour=(0, 0, 0)) big_circle_pos = right_pos
dualstim_screen.draw_circle(pos=target_pos, r=28, fill=True, colour=(255, 255, 255)) small_circle_pos = left_pos
screen.draw_circle(colour=(255, 255, 255), pos=big_circle_pos, r=52, fill=True)
screen.draw_circle(colour=(255, 255, 255), pos=small_circle_pos, r=38, fill=True)
# Dibujar flecha
if condition != "nogo":
arrow_dir = direction if condition == "pro" else ("left" if direction == "right" else "right")
if arrow_dir == "right":
end = (center[0] + arrow_length, center[1])
screen.draw_line(colour=arrow_color, spos=center, epos=end, pw=6)
screen.draw_line(colour=arrow_color, spos=end, epos=(end[0] - 30, end[1] - 30), pw=6)
screen.draw_line(colour=arrow_color, spos=end, epos=(end[0] - 30, end[1] + 30), pw=6)
else:
end = (center[0] - arrow_length, center[1])
screen.draw_line(colour=arrow_color, spos=center, epos=end, pw=6)
screen.draw_line(colour=arrow_color, spos=end, epos=(end[0] + 30, end[1] - 30), pw=6)
screen.draw_line(colour=arrow_color, spos=end, epos=(end[0] + 30, end[1] + 30), pw=6)
self.disp.fill(dualstim_screen) # Mostrar y grabar
self.disp.fill(screen)
tracker.start_recording()
tracker.log("TRIAL_%d_COND_%s_DIR_%s" % (trial + 1, condition.upper(), direction.upper()))
self.disp.show() self.disp.show()
wait_with_exit(1.5)
tracker.stop_recording()
t0 = pygame.time.get_ticks() # Cruz entre trials
self.tracker.log(f"target {targetside}") screen.clear(colour=(0, 0, 0))
screen.draw_text("+", fontsize=40)
t1, startpos = self.tracker.wait_for_saccade_start() self.disp.fill(screen)
endtime, startpos, endpos = self.tracker.wait_for_saccade_end()
latency = (t1 - t0) / 1000
self.tracker.stop_recording()
if trialtype == 'PS':
correct = int(
(targetside == 'left' and endpos[0] <= constants.DISPSIZE[0]/2) or
(targetside == 'right' and endpos[0] >= constants.DISPSIZE[0]/2)
)
elif trialtype == 'AS':
correct = int(
(targetside == 'left' and endpos[0] >= constants.DISPSIZE[0]/2) or
(targetside == 'right' and endpos[0] <= constants.DISPSIZE[0]/2)
)
elif trialtype == 'NoGo':
# Para NoGo: el correcto es no mover la mirada fuera del centro
correct = int(constants.DISPSIZE[0]/2 - 100 < endpos[0] < constants.DISPSIZE[0]/2 + 100)
if correct >= 0:
dualstim_screen.clear(colour=(0, 0, 0))
self.disp.show() self.disp.show()
wait_with_exit(0.8)
self.disp.fill(feedbackscreens[correct]) # Preguntar si repetir
screen.clear(colour=(0, 0, 0))
screen.draw_text("Test completado. ¿Quieres volver a intentarlo?\n\nPulsa S para repetir o N para salir.",
fontsize=30, colour=(255, 255, 255))
self.disp.fill(screen)
self.disp.show() self.disp.show()
time.sleep(0.5) while True:
key, _ = kb.get_key(keylist=['s', 'n', 'e'])
if key == 's':
break # vuelve al inicio del while True
elif key in ['n', 'e']:
pygame.quit()
return
results.append([trialnr, trialtype, targetside, endpos, round(latency, 3), correct])
except KeyboardInterrupt:
print("Test interrumpido por el usuario con la tecla 'E'.")
finally:
log.close()
self.tracker.close()
self.disp.close()
print("Test Go/NoGo finalizado.")
df = pd.DataFrame(results, columns=["trialnr", "trialtype", "targetside", "gaze_endpos", "latency", "correct"])
df.to_excel("gonogo_results.xlsx", index=False)
print("Resultados guardados en 'gonogo_results.xlsx'.")
# ============ INTERFAZ PYQT =================== # ============ INTERFAZ PYQT ===================
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment