Commit 657966b4 by Laura Rodríguez

16 jun 2

parent 8d5ca3d0
......@@ -654,176 +654,155 @@ def open_results_file():
# ============ TEST BATERIA ===================
def run_bateria_test(self):
pygame.init()
self.disp = libscreen.Display(bgcolor=(0, 0, 0)) # abro display de nuevo
log = liblog.Logfile()
log.write(["trialnr", "trialtype", "targetside", "gaze_endpos", "latency", "correct"])
SCREEN_WIDTH, SCREEN_HEIGHT = constants.DISPSIZE
CENTER = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
TARGET_OFFSET = 382
left_pos = (CENTER[0] - TARGET_OFFSET, CENTER[1])
right_pos = (CENTER[0] + TARGET_OFFSET, CENTER[1])
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
blackscreen = libscreen.Screen()
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)
pygame.init()
self.disp.fill(inscreen)
self.disp.show()
while True:
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
while waiting:
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:
pygame.quit()
return
# Orden fijo de las pruebas:
fixed_trialtypes = ['PS', 'AS', 'NoGo', 'AS', 'NoGo']
results = []
# Constantes
SCREEN_WIDTH, SCREEN_HEIGHT = constants.DISPSIZE
CENTER = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
TARGET_OFFSET = 382
left_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
# Pantalla de instrucciones
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:
for trialnr, trialtype in enumerate(fixed_trialtypes, start=1):
waiting = True
while waiting:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN and event.key == pygame.K_e:
raise KeyboardInterrupt
# Mostrar instrucción previa según tipo de prueba
instruction_text = ""
if trialtype == 'PS':
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)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
waiting = False
elif event.key == pygame.K_e:
pygame.quit()
return
# Mostrar cruz de fijación
self.disp.fill(fixscreen)
self.disp.show()
libtime.pause(random.randint(750, 1250))
screen = libscreen.Screen()
# Esperar que el usuario presione espacio
waiting = True
while waiting:
def wait_with_exit(seconds):
start = pygame.time.get_ticks()
while (pygame.time.get_ticks() - start) < seconds * 1000:
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 event.type == pygame.KEYDOWN and event.key == pygame.K_e:
pygame.quit()
exit()
for trial in range(n_trials):
# Mensaje previo
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
self.disp.fill(signal_screens[trialtype])
self.disp.show()
time.sleep(0.8)
if condition == "pro":
central_color = (0, 255, 0)
elif condition == "anti":
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()
time.sleep(0.2)
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
wait_with_exit(1.0)
dualstim_screen = libscreen.Screen()
dualstim_screen.clear(colour=(0, 0, 0))
dualstim_screen.draw_circle(pos=nontarget_pos, r=28, fill=True, colour=(255, 255, 255))
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))
# Flechas y círculos
screen.clear(colour=(0, 0, 0))
screen.draw_circle(colour=central_color, pos=center, r=28, fill=True)
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()
wait_with_exit(1.5)
tracker.stop_recording()
t0 = pygame.time.get_ticks()
self.tracker.log(f"target {targetside}")
t1, startpos = self.tracker.wait_for_saccade_start()
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])
# Cruz entre trials
screen.clear(colour=(0, 0, 0))
screen.draw_text("+", fontsize=40)
self.disp.fill(screen)
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 ===================
......
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