Commit 657966b4 by Laura Rodríguez

16 jun 2

parent 8d5ca3d0
...@@ -654,176 +654,155 @@ def open_results_file(): ...@@ -654,176 +654,155 @@ def open_results_file():
# ============ TEST BATERIA =================== # ============ TEST BATERIA ===================
def run_bateria_test(self): def run_bateria_test(self):
pygame.init() import pygame
self.disp = libscreen.Display(bgcolor=(0, 0, 0)) # abro display de nuevo from random import choice
log = liblog.Logfile() from pygaze import libscreen, liblog
log.write(["trialnr", "trialtype", "targetside", "gaze_endpos", "latency", "correct"]) from pygaze.keyboard import Keyboard
import constants
SCREEN_WIDTH, SCREEN_HEIGHT = constants.DISPSIZE from pygaze.display import Display
CENTER = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2) from pygaze.eyetracker import EyeTracker
TARGET_OFFSET = 382
left_pos = (CENTER[0] - TARGET_OFFSET, CENTER[1])
right_pos = (CENTER[0] + TARGET_OFFSET, CENTER[1])
blackscreen = libscreen.Screen() pygame.init()
blackscreen.clear(colour=(0, 0, 0))
inscreen = libscreen.Screen()
inscreen.clear(colour=(0, 0, 0))
fixscreen = libscreen.Screen()
fixscreen.clear(colour=(0, 0, 0))
fixscreen.draw_fixation(fixtype='cross', diameter=57, pos=CENTER, colour=(255, 255, 255))
signal_screens = {
'PS': libscreen.Screen(),
'AS': libscreen.Screen(),
'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) while True:
self.disp.show() self.disp = libscreen.Display(bgcolor=(0, 0, 0)) # Abrir pantalla
log = liblog.Logfile()
log.write(["trialnr", "trialtype", "targetside", "gaze_endpos", "latency", "correct"])
kb = Keyboard()
tracker = EyeTracker(self.disp)
waiting = True # Constantes
while waiting: SCREEN_WIDTH, SCREEN_HEIGHT = constants.DISPSIZE
for event in pygame.event.get(): CENTER = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
if event.type == pygame.KEYDOWN: TARGET_OFFSET = 382
if event.key == pygame.K_SPACE: left_pos = (CENTER[0] - TARGET_OFFSET, CENTER[1])
waiting = False right_pos = (CENTER[0] + TARGET_OFFSET, CENTER[1])
elif event.key == pygame.K_e: center = CENTER
pygame.quit() arrow_length = 100
return arrow_color = (255, 255, 255)
n_trials = 5
# Orden fijo de las pruebas:
fixed_trialtypes = ['PS', 'AS', 'NoGo', 'AS', 'NoGo'] # Pantalla de instrucciones
results = [] inscreen = libscreen.Screen()
inscreen.clear(colour=(0, 0, 0))
ins_text = (
"INSTRUCCIONES DETALLADAS:\n\n"
"🟢 Círculo VERDE: mira al CÍRCULO GRANDE en la dirección que indica la flecha.\n"
"🔴 Círculo ROJO: mira al CÍRCULO PEQUEÑO, en dirección contraria a la flecha.\n"
"🟠 Círculo NARANJA: NO muevas la vista, mantén la mirada en el centro.\n\n"
"Pulsa ESPACIO para comenzar la prueba.\n"
"Pulsa E para salir."
)
inscreen.draw_text(text=ins_text, fontsize=30, pos=CENTER, colour=(255, 255, 255), center=True)
self.disp.fill(inscreen)
self.disp.show()
try: waiting = True
for trialnr, trialtype in enumerate(fixed_trialtypes, start=1): while waiting:
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:
raise KeyboardInterrupt if event.key == pygame.K_SPACE:
waiting = False
# Mostrar instrucción previa según tipo de prueba elif event.key == pygame.K_e:
instruction_text = "" pygame.quit()
if trialtype == 'PS': return
instruction_text = "Mira al círculo GRANDE"
elif trialtype == 'AS':
instruction_text = "Mira al círculo PEQUEÑO"
elif trialtype == 'NoGo':
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 screen = libscreen.Screen()
self.disp.fill(fixscreen)
self.disp.show()
libtime.pause(random.randint(750, 1250))
# Esperar que el usuario presione espacio def wait_with_exit(seconds):
waiting = True start = pygame.time.get_ticks()
while waiting: 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: if event.type == pygame.KEYDOWN and event.key == pygame.K_e:
if event.key == pygame.K_SPACE: pygame.quit()
waiting = False exit()
elif event.key == pygame.K_e:
raise KeyboardInterrupt for trial in range(n_trials):
# Mensaje previo
time.sleep(0.2) screen.clear(colour=(0, 0, 0))
screen.draw_text(f"Trial {trial + 1} de {n_trials}\nPulsa E para salir o espera para comenzar...",
fontsize=30, colour=(255, 255, 255))
self.disp.fill(screen)
self.disp.show()
wait_with_exit(2.0)
self.tracker.start_recording() # Dirección y condición
direction = choice(["left", "right"])
condition = choice(["pro", "anti", "nogo"])
# Mostrar señal central de color if condition == "pro":
self.disp.fill(signal_screens[trialtype]) central_color = (0, 255, 0)
self.disp.show() elif condition == "anti":
time.sleep(0.8) central_color = (255, 0, 0)
else:
central_color = (255, 165, 0)
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'])
target_pos = left_pos if targetside == 'left' else right_pos
nontarget_pos = right_pos if targetside == 'left' else left_pos
dualstim_screen = libscreen.Screen() # Flechas y círculos
dualstim_screen.clear(colour=(0, 0, 0)) screen.clear(colour=(0, 0, 0))
dualstim_screen.draw_circle(pos=nontarget_pos, r=28, fill=True, colour=(255, 255, 255)) screen.draw_circle(colour=central_color, pos=center, r=28, fill=True)
dualstim_screen.draw_circle(pos=target_pos, r=38, fill=True, colour=(255, 255, 255))
dualstim_screen.draw_circle(pos=target_pos, r=32, fill=True, colour=(0, 0, 0))
dualstim_screen.draw_circle(pos=target_pos, r=28, fill=True, colour=(255, 255, 255))
self.disp.fill(dualstim_screen) if direction == "left":
big_circle_pos = left_pos
small_circle_pos = right_pos
else:
big_circle_pos = right_pos
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)
# 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.fill(feedbackscreens[correct])
self.disp.show() self.disp.show()
time.sleep(0.5) wait_with_exit(0.8)
results.append([trialnr, trialtype, targetside, endpos, round(latency, 3), 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()
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
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