IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Résolution temporelle pour enregistrement de clavier


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Juin 2009
    Messages
    134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2009
    Messages : 134
    Par défaut Résolution temporelle pour enregistrement de clavier
    Bonjour à tous,

    je suis actuellement en train de mener une expérience de psychologie écrite en python, dans laquelle je mesure les temps de réponse de sujets devant appuyer sur la barre espace du clavier dès qu'un stimulus visuel a été présenté à l'écran.

    J'ai besoin d'enregistrer ce temps de réponse avec la plus grande précision possible.

    Pour l'instant, la meilleure résolution temporelle que j'arrive à obtenir est de 13 ms, avec ce type de code pour enregistrer les temps de réponse (j'utilise la librairie pygame très utilisée pour les jeux vidéos) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    response_time = None
    ticks0 = pygame.time.get_ticks()
    while response_time == None:
            draw_stimulus(grey,grey_side)
            pygame.display.flip()
            for event in pygame.event.get():
                 if event.key == K_SPACE: response_time = pygame.time.get_ticks() - ticks0
    Est-il possible d'avoir une meilleure résolution temporelle (une ou quelques millisecondes serait l'idéal) et comment ?

    A quoi est due la limite de 13 ms observée dans mon script ? La fonction pygame.time.get_ticks() ? Le fait d'utiliser un clavier ?

    Merci d'avance de vos réponses.

  2. #2
    Membre expérimenté
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    222
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 222
    Par défaut
    Bonjour,

    J'ai déjà remarqué qu'il y a une légère latence lors de la pression d'une touche. Lorsque tu appuis sur un touche l'évènement est envoyés dans une queue (une liste d'évènements). Les évènement sont alors traités dans l'ordre, d'où la latence.
    Petite question: comment fais-tu pour obtenir les 13ms?

  3. #3
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Juin 2009
    Messages
    134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2009
    Messages : 134
    Par défaut
    OK.

    Peu importe pour la latence, car pour être plus précis je mesure les temps de réponse dans deux conditions (par exemple, une condition avec un stimulus présenté à gauche de l'écran et une condition avec un stimulus présenté à droite). Donc si la latence est présente dans les deux conditions cela me permet quand même de comparer mes résultats.

    Et je ne pense pas que cela soit à l'origine des 13ms, si ?

    Pour obtenir cette résolution, j'ai tout simplement inséré un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    print(pygame.time.get_ticks() - ticks0)
    dans ma boucle while ci-dessus, et j'obtiens une mesure toutes les 13 ms en moyenne quand je fais tourner mon programme.

    Bon finalement après quelques recherches je crois savoir d'où vient cette limite : de la fréquence de rafraichissement de mon écran. Mon programme affiche le stimulus à chaque fois que l'écran est rafraîchi, et jamais plus vite, ce semble limiter la vitesse d'exécution de ma boucle while. La fréquence de mon écran étant de 75 Hz, cela donne un rafraîchissement toutes les 1000/75 = 13,3 ms.

    Ma nouvelle question serait donc : existe-t-il une façon de contourner cette limite ? Par exemple en utilisant un boitier réponse qui enverrait de façon continue un signal à python, et pas uniquement au moment où l'écran est rafraîchi ?

  4. #4
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Juin 2009
    Messages
    134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2009
    Messages : 134
    Par défaut
    Bon je continue à me répondre à moi-même, pour vous faire part de mes avancées.

    La fréquence de rafraîchissement est bien le facteur limitant. Pour m'en convaincre, il m'a suffit de sortir le pygame.display.flip() (qui permet précisément de rafraichir l'écran) de ma boucle while :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
        response_time = None
        draw_stimulus(grey,grey_side)
        pygame.display.flip()
        ticks0 = pygame.time.get_ticks()
        while response_time == None:
            for event in pygame.event.get():
                if event.key == K_SPACE:
                    response_time = pygame.time.get_ticks() - ticks0
    ce qui me permet d'avoir une mesure toutes les 4 ms en moyenne. Si personne n'a mieux à me suggérer comme solution je m'en contenterai, c'est déjà pas si mal.

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Bonjour,




    Je ne connais pygame que très superficiellement et les arcanes de Python très moyennement, mais il me semble qu’on peut dire ceci:

    Ce qui t’intéresse est la valeur de response_time.
    Or celle-ci résulte:
    1- de l’obtention d’un temps par pygame.time.get_ticks()
    2- de la soustraction de la constante ticks0 à ce temps obtenu




    D’après ce que je comprends des mécanismes de Python, je crois que ce qui se passe lors de l’exécution de pygame.time.get_ticks() est la chose suivante:

    l’interpréteur va chercher dans l’objet pygame le module time dans lequel il lui faut chercher la fonction get_ticks. Une fois qu’il a cette fonnction sous la main, il en fait un appel, ce qui renvoie le temps. La recherche de cette fonction en suivant le chemin -> pygame -> time -> get_ticks prend évidemment un certain temps.

    Pour diminuer ce temps il faudrait définir un alias getT = pygame.time.get_ticks qui fournirait à Python directement la localisation de la fonction dans le grand sac pygame et lui permettrait donc d’aller chercher la fonction sans sinuer dans la hiérarchie des objets.

    Une telle mesure se justifie non seulement parce qu’elle doit logiquement abaisser le temps d’exécution mais aussi parce que cette recherche est effectuée de façon réitérée.

    Ceci, c’est la façon dont je vois les choses, mais je n’ai pas une grande certitude que cela se passe vraiment ainsi. J’espère que quelqu’un de calé confirmera ou corrigera.






    Seconde chose, la soustraction de ticks0 prend un micro- temps, elle aussi.
    Personnellement, quand je fais des mesures de temps d’exécution, j’enregistre un ticks0 puis un ticks1 et je ne fais faire la soustraction qu’après: ticks1 - ticks0.







    Troisièmement, je ne suis pas sûr qu’il y ait un grand intérêt à utiliser la fonction pygame.time.get_ticks au lieu de time.clock de Python.

    Coïncidence, il y a eu une file toute récente sur une mesure de temps:
    http://www.developpez.net/forums/d92...s/#post5228797







    Enfin, je me demande si la structure de ton code est bien correcte.
    Je ne connais pas bien pygame, ni les events, j’ose quand même proposer ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    KSP = pygame.K_SPACE
    ptgt = pygame.time.get_ticks
    pep = pygame.event.poll
     
    while 1:
        draw_stimulus(grey,grey_side)
        pygame.event.clear
        pygame.display.flip()
        ticks0 = ptgt()
        while pep().key != KSP:
            pass
        ticks1 = ptgt()
        response_time = ticks1 - ticks0
        # utilisation de response_time
        # temporisation de la relance du test
        # instruction d'arret du while







    La fréquence de mon écran étant de 75 Hz, cela donne un rafraîchissement toutes les 1000/75 = 13,3 ms.
    waouhh ! bien vu

    Je découvre cette information après avoir écrit ce qui précède, et cela confirme mon impression. Dans mon code, le pygame.display.flip() ne se trouve pas réexécuté tant que response_time n’a pas pris sa valeur.
    Il n’y a en effet pas besoin de relancer l'image en permanence sur l’écran: une fois qu’elle y est, il suffit de l’y entretenir. Le véritable stimulus est l’APPARITION de l’image.

    Maintenant, je ne suis pas un spécialiste des écrans et je ne sais pas si je comprends bien tout.....



    EDIT:
    ce que j’ai dit pour pygame.time.get_ticks est valable pour pygame.display.poll ! C’est à dire créer un alias de cette fonction aussi, puisqu’elle est encore plus réexécutée que n’importe quelle autre !

  6. #6
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Ah, je vois qu’on a pensé à la même chose sur pygame.display.flip() dans une boucle.

    Reste à savoir si mon code est écrit correctement car il me semble plus condensé donc plus court.

  7. #7
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 068
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 068
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    pygame.init()
    etc ...
    draw_stimulus(grey,grey_side)
    pygame.display.flip()
    ticks0 = pygame.time.get_ticks()
    while not pygame.key.get_pressed()[pygame.K_SPACE]:pygame.event.wait()
    response_time = pygame.time.get_ticks() - ticks0

Discussions similaires

  1. Logiciel pour enregistrer les touches du clavier
    Par WELCOMSMAIL dans le forum Autres Logiciels
    Réponses: 20
    Dernier message: 27/04/2006, 13h18
  2. [Struts]comment faites-vous pour enregistrer..
    Par pouss dans le forum Struts 1
    Réponses: 7
    Dernier message: 30/09/2005, 12h55
  3. Réponses: 9
    Dernier message: 22/09/2005, 16h34
  4. [Oracle 10g]Problème pour enregistrer blob
    Par Invité dans le forum Hibernate
    Réponses: 6
    Dernier message: 27/04/2005, 11h45
  5. TEdit numérique pour tous les claviers
    Par totofweb dans le forum C++Builder
    Réponses: 2
    Dernier message: 10/06/2004, 11h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo