Commit 25dc3da8 by Laura Rodríguez

17 jun

parent 657966b4
...@@ -103,7 +103,7 @@ def calibrate_tobii(self): ...@@ -103,7 +103,7 @@ def calibrate_tobii(self):
# ============ TEST PRO/NOGO ====================== # ============ TEST PS/NOGO ======================
def run_pro_nogo_test(self): def run_pro_nogo_test(self):
pygame.init() pygame.init()
...@@ -283,7 +283,7 @@ def run_pro_nogo_test(self): ...@@ -283,7 +283,7 @@ def run_pro_nogo_test(self):
print("Resultados guardados en 'gonogo_results.xlsx'.") print("Resultados guardados en 'gonogo_results.xlsx'.")
# ============ TEST PR/AS =================== # ============ TEST PS/AS ===================
def run_pr_as_test(self): def run_pr_as_test(self):
...@@ -353,6 +353,7 @@ def run_pr_as_test(self): ...@@ -353,6 +353,7 @@ def run_pr_as_test(self):
max_blocks = 30 max_blocks = 30
results = [] results = []
try: try:
self.tracker.start_recording()
for block in range(max_blocks): for block in range(max_blocks):
trials = ['PS', 'AS'] trials = ['PS', 'AS']
fixation_duration = random.choice([1000, 2000, 3000]) # milisegundos fixation_duration = random.choice([1000, 2000, 3000]) # milisegundos
...@@ -367,7 +368,7 @@ def run_pr_as_test(self): ...@@ -367,7 +368,7 @@ def run_pr_as_test(self):
# Mostrar cruz de fijación # Mostrar cruz de fijación
self.disp.fill(fixscreen) self.disp.fill(fixscreen)
self.disp.show() self.disp.show()
libtime.pause(random.randint(750, 1250)) #libtime.pause(random.randint(750, 1250))
libtime.pause(fixation_duration) # Usamos la duración fija del bloque libtime.pause(fixation_duration) # Usamos la duración fija del bloque
# # Esperar que el usuario presione espacio # # Esperar que el usuario presione espacio
...@@ -382,7 +383,6 @@ def run_pr_as_test(self): ...@@ -382,7 +383,6 @@ def run_pr_as_test(self):
time.sleep(0.2) time.sleep(0.2)
self.tracker.start_recording()
# Mostrar señal central de color # Mostrar señal central de color
self.disp.fill(signal_screens[trialtype]) self.disp.fill(signal_screens[trialtype])
...@@ -416,7 +416,6 @@ def run_pr_as_test(self): ...@@ -416,7 +416,6 @@ def run_pr_as_test(self):
latency = (t1 - t0) / 1000 latency = (t1 - t0) / 1000
self.tracker.stop_recording()
# midpoint = SCREEN_WIDTH / 2 # midpoint = SCREEN_WIDTH / 2
# margin = 100 # margin = 100
...@@ -444,6 +443,7 @@ def run_pr_as_test(self): ...@@ -444,6 +443,7 @@ def run_pr_as_test(self):
results.append([trialnr, trialtype, targetside, endpos, round(latency, 3), correct]) results.append([trialnr, trialtype, targetside, endpos, round(latency, 3), correct])
self.tracker.stop_recording()
except KeyboardInterrupt: except KeyboardInterrupt:
print("Test interrumpido por el usuario con la tecla 'E'.") print("Test interrumpido por el usuario con la tecla 'E'.")
finally: finally:
...@@ -655,154 +655,207 @@ def open_results_file(): ...@@ -655,154 +655,207 @@ 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.test_window.disp = self.disp
self.disp = libscreen.Display(bgcolor=(0, 0, 0))#abro display de nuevo
# self.tracker = eyetracker.EyeTracker(self.disp)
log = liblog.Logfile()
log.write(["trialnr", "trialtype", "targetside", "gaze_endpos", "latency", "correct"])
while True: SCREEN_WIDTH, SCREEN_HEIGHT = constants.DISPSIZE
self.disp = libscreen.Display(bgcolor=(0, 0, 0)) # Abrir pantalla CENTER = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
log = liblog.Logfile() TARGET_OFFSET = 382
log.write(["trialnr", "trialtype", "targetside", "gaze_endpos", "latency", "correct"]) left_pos = (CENTER[0] - TARGET_OFFSET, CENTER[1])
kb = Keyboard() right_pos = (CENTER[0] + TARGET_OFFSET, CENTER[1])
tracker = EyeTracker(self.disp)
# Constantes blackscreen = libscreen.Screen()
SCREEN_WIDTH, SCREEN_HEIGHT = constants.DISPSIZE blackscreen.clear(colour=(0, 0, 0))
CENTER = (SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
TARGET_OFFSET = 382 inscreen = libscreen.Screen()
left_pos = (CENTER[0] - TARGET_OFFSET, CENTER[1]) inscreen.clear(colour=(0, 0, 0))
right_pos = (CENTER[0] + TARGET_OFFSET, CENTER[1]) ins_text = (
center = CENTER "INSTRUCCIONES DETALLADAS:\n\n"
arrow_length = 100 "🟢 Círculo VERDE: mira al CÍRCULO GRANDE en la dirección que indica la flecha.\n"
arrow_color = (255, 255, 255) "🔴 Círculo ROJO: mira al CÍRCULO PEQUEÑO, en dirección contraria a la flecha.\n"
n_trials = 5 "🟠 Círculo NARANJA: NO muevas la vista, mantén la mirada en el centro.\n\n"
"Pulsa ESPACIO para comenzar la prueba.\n"
# Pantalla de instrucciones "Pulsa E para salir."
inscreen = libscreen.Screen() )
inscreen.clear(colour=(0, 0, 0)) time.sleep(0.7)
ins_text = ( inscreen.draw_text(text=ins_text, fontsize=30, pos=CENTER, colour=(255, 255, 255), center=True)
"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()
waiting = True fixscreen = libscreen.Screen()
while waiting: fixscreen.clear(colour=(0, 0, 0))
for event in pygame.event.get(): fixscreen.draw_fixation(fixtype='cross', diameter=57, pos=CENTER, colour=(255, 255, 255))
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE: signal_screens = {
waiting = False 'PS': libscreen.Screen(),
elif event.key == pygame.K_e: 'AS': libscreen.Screen(),
pygame.quit() 'NoGo': libscreen.Screen()
return }
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)
screen = libscreen.Screen() 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.show()
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
total_trials = 5
results = []
try:
trials = ['PS', 'AS', 'NoGo'] * 2 # Para asegurar que haya variedad
random.shuffle(trials)
selected_trials = trials[:total_trials]
for trialnr, trialtype in enumerate(selected_trials, start=1):
def wait_with_exit(seconds):
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:
pygame.quit() raise KeyboardInterrupt
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)
# Dirección y condición
direction = choice(["left", "right"])
condition = choice(["pro", "anti", "nogo"])
if condition == "pro":
central_color = (0, 255, 0)
elif condition == "anti":
central_color = (255, 0, 0)
else:
central_color = (255, 165, 0)
# 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()
wait_with_exit(1.0)
# Flechas y círculos
screen.clear(colour=(0, 0, 0))
screen.draw_circle(colour=central_color, pos=center, r=28, fill=True)
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()
# Cruz entre trials # Mostrar cruz de fijación
screen.clear(colour=(0, 0, 0)) self.disp.fill(fixscreen)
screen.draw_text("+", fontsize=40) self.disp.show()
self.disp.fill(screen) libtime.pause(random.randint(750, 1250))
self.disp.show()
wait_with_exit(0.8) # Esperar que el usuario presione espacio
# waiting = True
# Preguntar si repetir # while waiting:
screen.clear(colour=(0, 0, 0)) # for event in pygame.event.get():
screen.draw_text("Test completado. ¿Quieres volver a intentarlo?\n\nPulsa S para repetir o N para salir.", # if event.type == pygame.KEYDOWN:
fontsize=30, colour=(255, 255, 255)) # if event.key == pygame.K_SPACE:
self.disp.fill(screen) # waiting = False
self.disp.show() # elif event.key == pygame.K_e:
while True: # raise KeyboardInterrupt
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
time.sleep(0.2)
self.tracker.start_recording()
# Mostrar señal central de color
self.disp.fill(signal_screens[trialtype])
self.disp.show()
time.sleep(0.8)
self.disp.fill(blackscreen)
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
# Mostrar flecha de dirección según la condición (PS, AS, NoGo)
arrow_screen = libscreen.Screen()
arrow_screen.clear(colour=(0, 0, 0))
arrow_offset = 100 # desplazamiento vertical para colocar la flecha por encima
arrow_color = (255, 255, 255)
if trialtype == 'PS':
arrow_pos = target_pos
elif trialtype == 'AS':
arrow_pos = nontarget_pos
else: # NoGo
arrow_pos = CENTER
arrow_pos_above = (arrow_pos[0], arrow_pos[1] - arrow_offset)
arrow_screen.draw_text(text='↑', fontsize=60, pos=arrow_pos_above, colour=arrow_color, center=True)
self.disp.fill(arrow_screen)
self.disp.show()
time.sleep(0.8)
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))
self.disp.fill(dualstim_screen)
self.disp.show()
t0 = pygame.time.get_ticks()
self.tracker.log(f"target {targetside}")
# try:
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()
# midpoint = SCREEN_WIDTH / 2
# margin = 100
# endpos=None
if trialtype == 'PS':
correct = int(
(targetside == 'left' and endpos[0] <= constants.DISPSIZE[0] / 2) or
(targetside == 'right' and endpos[0] >= constants.DISPSIZE[0] / 2)
)
print(correct)
elif trialtype == 'AS':
correct = int(
(targetside == 'left' and endpos[0] >= constants.DISPSIZE[0] / 2) or
(targetside == 'right' and endpos[0] <= constants.DISPSIZE[0] / 2)
)
print(correct)
elif trialtype == 'NoGo':
# En NoGo siempre se considera incorrecto
try:
t1, startpos = self.tracker.wait_for_saccade_start(latency=200)
endtime, _, endpos = self.tracker.wait_for_saccade_end()
latency = (t1 - t0) / 1000
print("Incorrecto - Sacada detectada")
except Exception:
latency = 0
endpos = None
print("Incorrecto - No se detectó sacada")
correct = 0
self.disp.fill(feedbackscreens[correct])
self.disp.show()
time.sleep(0.5)
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