[PYTHON] Obtenez un temps de réaction négatif avec psychopy.event.getKeys ()

introduction

Dans cet article, comme le titre l'indique, lorsque vous utilisez psychopy.event.getKeys (), je vais vous présenter que vous pouvez obtenir un temps de réaction négatif si ** les conditions sont remplies. Fondamentalement, le temps de réaction négatif n'est pas ce que le créateur de l'expérience souhaite, alors j'espère qu'il vous sera utile lorsque vous l'obtiendrez et que vous direz "Est-ce un bug? J'ai des problèmes". Quelquefois). Le fait est de ne pas oublier ʻevent.clearEvents () `si vous ne voulez pas de temps de réaction négatif.

** (Mise à jour 20191119) ** [win.flip () semble être important](#winflip semble également être important ajouté 20191119) a été ajouté. Apparemment, obtenir un temps de réaction négatif n'est pas simple.

Méthode

Après avoir appuyé sur la touche, exécutez .reset () sur l'objet core.Clock pour mesurer le temps de réaction (par exemple, le nom de la variable stopwatch), et psychopoy.event.getKeys (timeStamped = chronomètre). Vous obtenez un temps de réaction négatif. Regardons le code qui donne en fait un temps de réaction négatif.

Exemple de code 1

get-neg-rt_1.py


from psychopy import visual, core, event

win = visual.Window()
stopwatch = core.Clock()
stim = visual.TextStim(win)
l_letter = ['a','b','c']

for letter in l_letter:
    stim.setText(letter)
    stim.draw()
    win.flip()
    core.wait(2) #Entrez la clé tout en présentant le stimulus
    stopwatch.reset() #Réinitialiser l'horloge après une frappe
    resp = event.getKeys(timeStamped=stopwatch) #Traitement des entrées clés
    print(resp)

win.close()

#Exemple de sortie
# [['space', -0.17376430198783055], ['space', -0.16929624899057671]]
# [['space', -0.19804733199998736]]
# [['space', -0.19725568499416113]]

Si vous inversez core.wait () et stopwatch.reset (), vous n'obtiendrez pas un temps de réaction négatif (même s'il s'agit d'une valeur positive, vous ne pouvez toujours pas obtenir la réaction correctement. Comment l'obtenir correctement) Est présenté dans cet article). Cependant, je ne pense pas que quiconque écrit un tel code. Il devrait réinitialiser l'horloge avant ou immédiatement après la présentation du stimulus (c'est-à-dire avant core.wait ()). Cependant, l'exemple suivant est une erreur honteuse que j'ai réellement commise.

Exemple de code 2

get-neg-rt_2.py


from psychopy import visual, core, event

win = visual.Window()
stopwatch = core.Clock()
stim = visual.TextStim(win)
l_letter = ['a','b','c']

for letter in l_letter:
    stim.setText(letter)
    resp = []
    # event.clearEvents()
    stopwatch.reset()
    for n_frame in range(120): # 120f(2 secondes si le taux de rafraîchissement est de 60 Hz)
        stim.draw()
        win.flip()
        if not resp:
            resp = event.getKeys(timeStamped=stopwatch) #Traitement des entrées clés

    print(resp)

win.close()

#Exemple de sortie
# [['space', 0.8996025759843178]]
# [['space', -0.34911786299198866]]
# [['space', -1.4165731929824688], ['space', -0.6160959279804956]]

Ce code, comme le code ci-dessus, obtient la réponse tout en présentant le stimulus pendant 2 secondes. La différence est que nous avons l'intention de capturer uniquement la toute première réaction de chaque essai. Si resp = [] est défini avant que le stimulus ne soit présenté et que resp reste une liste vide, not resp devient True, donc ʻevent.getKeys ()est exécuté. S'il y a une entrée clé,[[key, rt]] est assignée à resp, et dans les boucles suivantes, not resp devient Falseet l'entrée clé n'est pas traitée. De plus, contrairement à l'exemple 1,stopwatch.reset ()est exécuté avant le bloc présenté, donc à première vue, il ne semble y avoir aucun problème (je pensais que je n'étais pas là). Cependant, si vous appuyez plusieurs fois sur la touche tout en présentant un certain stimulus, vous obtiendrez un temps de réaction négatif comme indiqué dans l'exemple de sortie. La solution est d'activer ʻevent.clearEvents (), qui est commenté dans le code.

Pourquoi cela arrive

Je n'ai remarqué que récemment que (au moins) psychopy a un «tampon d'événement» qui correspond à chaque entrée de touche (ou souris, joystick), et il semble que l'entrée y est conservée. Ceci est également fait lors de l'exécution de core.wait (). L'exécution de ʻevent.getKeys () récupère toutes les entrées contenues dans le ** clavier ** tampon à ce moment-là ([Référence officielle](https://www.psychopy.org/api/event.html). # psychopy.event.getKeys)). Et si timeStamped est spécifié, la différence entre l'heure enregistrée dans le tampon (heure unix) et l'heure indiquée par l'objet core.Clock spécifié ( chronomètre dans l'exemple de code) est Il renvoie la valeur recalculée avec le timing de .reset () ʻa 0. Cela donne le temps de réaction. Pour ces raisons, si ".reset ()" est pris en sandwich entre l'entrée de clé et "getKeys ()" comme dans l'exemple 1, un temps de réaction négatif sera obtenu, et comme dans l'exemple 2, un sera obtenu. Même s'il semble que seule la réaction de l'œil soit supprimée, la deuxième et les suivantes réactions du même essai sont conservées dans le tampon, elles seront donc traitées par getKeys () de la boucle suivante. Devenir. La frappe elle-même est avant .reset (), donc l'heure retournée sera négative. Le clearEvents () présenté comme la solution dans l'exemple 2 supprime l'entrée contenue dans le tampon. En faisant cela juste avant le début de chaque essai, la deuxième réaction et les suivantes qui se sont produites dans l'essai précédent n'affecteront pas l'essai suivant. Même si getKeys () est exécuté, l'entrée de touche jusqu'à ce point disparaîtra du tampon.

Dans l'exemple 1, vous pouvez simplement trier core.wait () et .reset (), mais cela ne signifie pas qu'il est toujours sûr d'utiliser core.wait (). Comme indiqué dans le code ci-dessous, si vous définissez un blanc entre les essais et appuyez sur une touche avec ce blanc, vous obtiendrez un temps de réaction négatif. Encore une fois, vous pouvez éviter les temps de réaction négatifs en exécutant ʻevent.clearEvents () avant core.wait () (ou win.flip () ). Dans tous les cas, il est important de se souvenir de ʻevent.clearEvents () .

get-neg-rt_3.py


from psychopy import visual, core, event

win = visual.Window()
stopwatch = core.Clock()
stim = visual.TextStim(win)
l_letter = ['a','b','c']

for letter in l_letter:
    # event.clearEvents()
    stim.setText(letter)
    stim.draw()
    win.flip()
    stopwatch.reset() #Réinitialiser l'horloge après une frappe
    core.wait(2) #Entrez la clé tout en présentant le stimulus
    resp = event.getKeys(timeStamped=stopwatch) #Traitement des entrées clés
    print(resp)
    # ITI
    win.flip()
    core.wait(1) #Si vous appuyez sur la touche ici, vous obtiendrez une valeur négative

win.close()

Au fait, ʻevent.waitKeys () est configuré pour exécuter ʻevent.clearEvents () en interne par défaut au moment de l'exécution, il n'est donc pas nécessaire de le spécifier ([Référence officielle](https: /). /www.psychopy.org/api/event.html#psychopy.event.waitKeys)).

win.flip () semble également être important (20191119 postscript)

Après avoir essayé diverses choses, j'ai trouvé que l'histoire n'était pas si simple et que win.flip () affectait également le calcul du temps de réaction avec getKeys (). Si vous exécutez le code suivant, le temps de réponse de la pression de touche reportée de la boucle précédente sera inférieur à 10ms.

get-neg-rt_4.py


from psychopy import visual, core, event

win = visual.Window()
stopwatch = core.Clock()
stim = visual.TextStim(win)
l_letter = ['a','b','c']

for letter in l_letter:
    stim.setText(letter)
    resp = []
    # event.clearEvents()
    stopwatch.reset()
    stim.draw()
    win.flip()
    while stopwatch.getTime() < 2:
        if not resp:
            resp = event.getKeys(timeStamped=stopwatch) #Traitement des entrées clés

    print(resp)

win.close()

#Exemple de sortie
# [['down', 0.5086547629907727]]
# [['down', 0.0033315849723294377], ['down', 0.0070590279647149146]]
# [['down', 0.004310511983931065], ['down', 0.009222752996720374]]

En entrant dans la boucle de «while stopwatch.getTime () <2» après avoir présenté le stimulus, le processus d'acquisition du temps de réaction pendant 2 secondes continuera à être répété. Le stimulus reste visible car l'écran n'est pas rafraîchi tant que la boucle «while» n'est pas terminée et que le «win.flip ()» suivant n'est pas exécuté. Cela devrait être le même que le deuxième exemple sauf que stim.draw () et win.flip () ne sont pas répétés, mais je ne peux plus obtenir un temps de réaction négatif. Cependant, il ne semble pas approprié comme temps de réaction. En mettant draw () et flip () dans la boucle while, vous pouvez obtenir un temps de réaction négatif comme dans le deuxième exemple. Apparemment, il semble que la synchronisation d'entrée de la clé soit réinitialisée par win.flip () [^ 1], et dans cet exemple, getKeys () est exécuté immédiatement après cela, donc une valeur d'environ 10 ms est obtenue. Semble pouvoir. Le code ci-dessous est la justification pour supposer que le timing d'entrée est "re" réglé, c'est-à-dire qu'il conserve le timing d'entrée avant win.flip ().

[^ 1]: Cependant, il est probablement fixé à la valeur mise à jour par le premier win.flip (). Dans le deuxième exemple, win.flip () est répété plusieurs fois avec l'entrée clé restant dans le tampon d'événements, mais un temps de réaction négatif comme celui-ci est obtenu. Je ne sais pas si cette hypothèse est correcte car je ne l'ai pas vérifiée.

get-multi-rt_4.py


from psychopy import visual, core, event

win = visual.Window()
stopwatch = core.Clock()
stim = visual.TextStim(win)
l_letter = ['a','b','c']

for letter in l_letter:
    stim.setText(letter)
    resp = []
    stopwatch.reset()
    stim.draw()
    win.flip()
    while stopwatch.getTime() < 2:
        resp += event.getKeys(timeStamped=stopwatch) #Traitement des entrées clés

    print(resp)

win.close()

Dans ce code, comme dans l'exemple précédent, l'entrée de touche est détectée pendant 2 secondes sans mettre à jour l'écran, mais la différence est que plusieurs réactions sont acceptées dans un essai. Dans ce cas, win.flip () n'a pas été exécuté pendant 2 secondes, mais la synchronisation de chaque entrée de touche semble être mesurée correctement. Je ne sais pas pourquoi utiliser win.flip () met à jour les informations contenues dans le ʻevent buffer, et que la mise à jour se produit probablement une seule fois. Si quelqu'un le sait, je l'apprécierais si vous pouviez m'apprendre. Dans tous les cas, à moins que vous n'ayez vraiment besoin d'un temps de réaction négatif, nous vous recommandons d'utiliser ʻevent.clearEvents () .

en conclusion

Dans cet article, nous avons présenté le cas où psychopy.event.getKeys () renvoie un temps de réaction négatif. Il semble que le temps de réaction négatif était un bug né de ma fierté et de ma fierté que ce serait bien parce que j'ai essayé de n'obtenir que la première réaction avec l'expression conditionnelle de «si non resp:». J'ai l'impression que le tampon d'événement a été expliqué partout (livre du professeur Togawa?), Mais je pense qu'il n'y avait pas d'article qui l'expliquait du point de vue d'un tel bug. Des temps de réaction négatifs peuvent également être utiles dans certaines expériences. Dans ce cas, veuillez consulter votre propre procédure expérimentale et bien gérer win.flip (). ʻEvent.clearEvents () `est le" ki "de base pour obtenir une réaction. N'oubliez pas quand vous vous y habituez.

Recommended Posts

Obtenez un temps de réaction négatif avec psychopy.event.getKeys ()
Obtenez une sortie standard en temps réel avec le sous-processus Python
Démarrez avec MicroPython
Recevez des tweets avec Tweepy
Obtenez date avec python
Démarrez avec Mezzanine
python Obtenir l'heure actuelle
Obtenez des champs de chat en direct YouTube en temps réel avec l'API
Obtenez le code du pays avec python
Obtenez la table dynamiquement avec sqlalchemy
Lancez-vous avec Django! ~ Tutoriel ⑤ ~
Obtenez la chronologie Twitter avec Python
Entrée standard avec limite de temps
Commencez avec influxDB + Grafana
Obtenez des données Youtube avec python
Obtenir des informations avec l'API Zabbix
Lancez-vous avec Django! ~ Tutoriel ④ ~
Lancez-vous avec Django! ~ Tutoriel ⑥ ~
Mesure du temps d'exécution avec Python avec
Obtenir l'ID de thread avec python
Commencez avec Python! ~ ② Grammaire ~
Obtenez des fonctionnalités d'image avec OpenCV
Obtenez des stocks avec Python
Obtenir le répertoire personnel avec python
Obtenir un événement de clavier avec python
Synchronisation de l'heure (Windows) avec Python
Obtenez des informations sur l'alambic avec Python
Obtenez un classement avec l'API Rakuten