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

  1. #1
    Membre du Club
    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
    Points : 61
    Points
    61
    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 actif
    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
    Points : 290
    Points
    290
    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 du Club
    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
    Points : 61
    Points
    61
    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 du Club
    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
    Points : 61
    Points
    61
    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 extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    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 extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    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 expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 046
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 046
    Points : 1 376
    Points
    1 376
    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

  8. #8
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut
    mmmmmh.... mouais

    Il semble que la fonction pygame.key.get_pressed ne soit pas la mieux pour l’objectif recherché:

    Getting the list of pushed buttons with this function is not the proper way to handle text entry from the user. You have no way to know the order of keys pressed, and rapidly pushed keys can be completely unnoticed between two calls to pygame.key.get_pressed - get the state of all keyboard buttons. There is also no way to translate these pushed keys into a fully translated character value. See the pygame.KEYDOWN events on the event queue for this functionality.

    http://www.pygame.org/docs/ref/key.html

  9. #9
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 046
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 046
    Points : 1 376
    Points
    1 376
    Par défaut
    rapidly pushed keys can be completely unnoticed between two calls to pygame.key.get_pressed
    ben, on attend qu'une seule frappe de la touche espace, donc ça devrait bien le faire.

    pour être tatillon, faudrait rajouter un event.wait() car le 1er appel à get_pressed() renvoie une liste vide s'il n'y a pas eu d'interception d'évenement, mais je doute que la main soit plus rapide que la machine.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    pygame.init()
    etc ...
    draw_stimulus(grey,grey_side)
    pygame.display.flip()
    ticks0 = pygame.time.get_ticks()
    pygame.event.wait()
    while not pygame.key.get_pressed()[pygame.K_SPACE]:pygame.event.wait()
    response_time = pygame.time.get_ticks() - ticks0
    ensuite il y a mesures et Mesures; comment on fait si le clavier casse et qu'il faille en acheter un autre qui aura des temps de latence différents, etc .... je pense que la marge de la milliseconde et raisonnable, car qui sait à quoi est occupé le processeur au moment où l'on frappe la touche.

    plus conventionnel mais moins rapide je pense ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    pygame.init()
    etc ...
    draw_stimulus(grey,grey_side)
    pygame.display.flip()
    ticks0 = pygame.time.get_ticks()
    while True:
        e = pygame.event.wait()
        if e.type == pygame.KEYDOWN and e.key == pygame.K_SPACE:break
    response_time = pygame.time.get_ticks() - ticks0

  10. #10
    Membre du Club
    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
    Points : 61
    Points
    61
    Par défaut
    Merci à tous les deux.

    Voilà quelques commentaires :

    - la fonction time.clocks() permet d'obtenir une précision meilleure que la ms, mais en l'utilisant je ne descends toujours pas en-dessous des 4 ms, donc je ne m'y pencherai dessus qu'après avoir résolu ce problème

    - dans ton code Eyquem, tu mets encore pygame.display.flip() dans une boucle while, mais j'imagine que cela n'est pas nécessaire ? Est-ce que cela apporte quelque chose de rafraîchir l'image plusieurs fois si mon stimulus reste le même ?

    - le code que tu proposes me donne par ailleurs l'erreur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        while pep().key != KSP:
    AttributeError: event member not defined
    - si c'est la soustraction qui peut introduire un temps de latence, je ne vois pas ce que cela change de faire pygame.time.get_ticks() - ticks0 ou ticks1 - ticks0

    - la raison pour laquelle j'utilisais une boucle for pour parcourir les événements est que j'utilise la touche échap pour pouvoir sortir de mon programme à tout moment. Le code en entier donnerait donc plutôt cela :

    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
                elif event.key == K_ESCAPE: raise Exception()
    - d'après les essais que j'ai pu faire, créer une fonction ptgt pour ne pas avoir à appeler pygame.time.get_ticks() n'augmente pas la résolution temporelle.

    - faire une boucle qui ne fait rien tant qu'un événement clavier n'a pas eu lieu me paraît bien pour essayer de diminuer les temps, mais le problème c'est que si j'introduis un print(pygame.time.get_ticks() - ticks0) dans ma boucle pour mesurer le temps écoulé entre deux mesures je risque de fausser ce qui se passe dans la réalité, non ?


    Peut-être enfin que ce délai de 4 ms est lié à la puissance de mon ordinateur... Il faudrait que je teste sur un autre pour pouvoir comparer.

  11. #11
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 046
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 046
    Points : 1 376
    Points
    1 376
    Par défaut
    pour rester dans ta logique ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    pygame.init()
    etc ...
    response_time = None
    draw_stimulus(grey,grey_side)
    pygame.display.flip()
    ticks0 = pygame.time.get_ticks()
    while not response_time :
        pygame.event.wait()
        KEY = pygame.key.get_pressed()
        if KEY[pygame.K_SPACE]: response_time = pygame.time.get_ticks() - ticks0
        elif  KEY[pygame.K_ESCAPE]: raise Exception()
    mais je reste sur ma 1ere soluce ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    pygame.init()
    etc ...
    draw_stimulus(grey,grey_side)
    pygame.display.flip()
    ticks0 = pygame.time.get_ticks()
    KEY = pygame.key.get_pressed()
    while not KEY[pygame.K_SPACE]|KEY[pygame.K_ESCAPE]:
        pygame.event.wait()
        KEY = pygame.key.get_pressed()
    response_time = pygame.time.get_ticks() - ticks0
    if KEY[K_ESCAPE]:raise Exception()

  12. #12
    Membre du Club
    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
    Points : 61
    Points
    61
    Par défaut
    OK.

    Pour tester la vitesse de ces boucles, je voudrais insérer un print(pygame.time.get_ticks() - ticks0) dans la boucle while mais pour cela il faut que je supprime l'instruction pygame.event.wait.

    Malheureusement, lorsque je fais cela, mon programme tourne en boucle infinie et aucune touche ne peut l'arrêter. Je ne comprends pas d'où vient cette boucle infinie. L'instruction pygame.event.wait() ne m'a pas l'air nécessaire pour faire changer la valeur de KEY, si ?

  13. #13
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 046
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 046
    Points : 1 376
    Points
    1 376
    Par défaut
    pour que key.get_pressed() soit actualisé, il faut intercepter un evenement quelqu'il soit, via get(), poll() ou wait(); sinon key.get_pressed() renvoie toujours une liste 0.
    essaies ça ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    pygame.init()
    etc ...
    draw_stimulus(grey,grey_side)
    KEY = pygame.key.get_pressed()
    pygame.display.flip()
    ticks0 = pygame.time.get_ticks()
    while not KEY[pygame.K_SPACE]|KEY[pygame.K_ESCAPE]:
        pygame.event.poll()
        KEY = pygame.key.get_pressed()
        print pygame.time.get_ticks() - ticks0
    response_time = pygame.time.get_ticks() - ticks0
    if KEY[pygame.K_ESCAPE]:raise Exception()

  14. #14
    Membre du Club
    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
    Points : 61
    Points
    61
    Par défaut
    Génial ça marche parfaitement.

    Avec pygame.time.get_ticks() j'obtiens maintenant une résolution de 1,15 ms contre 1,25 avec time.clock(), mais get_ticks() ne renvoit que des 1 ou des 2 donc sera forcément moins précis sur la moyenne (time.clock() a quant à lui une précision de 10^-7 ms mais bon, après j'imagine que cela ne sert à rien d'être aussi précis puisque à cette échelle là, les tâches que le processeur effectue en parallèle de python influent beaucoup sur ces mesures).

    Deux dernières petites questions :

    - est-ce qu'on peut faire confiance à time.clock() (par rapport à ma remarque précédente, car peut-être que pygame.time.get_ticks est moins dépendant des tâches en parallèle que le processeur effectue) ?

    - est-ce que je gagne quelque chose à mettre un pygame.event.wait() dans ma boucle ou est-ce la même chose de la laisser tourner même quand il ne se passe rien ?

  15. #15
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut
    @ josmiley

    rapidly pushed keys can be completely unnoticed between two calls to pygame.key.get_pressed
    ben, on attend qu'une seule frappe de la touche espace, donc ça devrait bien le faire.
    ah oui, tiens, on peut comprendre ça ainsi: les « rapidly pushed keys » signifierait “plusieurs touches pressées rapidement les unes à la suite des autres“. C’est bien ce que tu veux dire ?
    Moi j’ai compris: une touche pressée et relachée très rapidement (un clavier à fort rebond donc ?) ne sera pas attrapée par pygame.key.get_pressed

    Mais si pygame.key.get_pressed n’arrive pas à attraper tous les pressages de touches d’une succession rapide, c’est bien qu’il n’arrive pas à attraper certains pressages individuellement, non ? Donc presser une touche très rapidement peut aussi mettre cette fonction en défaut, me dis-je.







    Je pense que cette fonction pygame.key.get_pressed n’est en fait véritablement pas adaptée au problème car elle n’assure pas une surveillance constante, comme pygame.event.wait par exemple. Elle n’agit que sur DECLENCHEMENT.

    Un autre défaut secondaire est qu’elle collationne un ensemble de valeurs booléennes sur toutes les touches. Donc à chaque fois c’est un grand nombre de données inutiles qui sont captées et enregistrées.

    Du moins, c’est ce que je comprends, en non spécialiste de pygame.







    le 1er appel à get_pressed() renvoie une liste vide s'il n'y a pas eu d'interception d'évenement
    Je ne crois pas.
    pygame.key.get_pressed() renvoie une séquence de valeurs booléennes pour TOUTES les touches, quelles que soient leur activité, False ou True







    car qui sait à quoi est occupé le processeur au moment où l'on frappe la touche.
    Étant donné que le programme est affecté à une expérimentation en psychologie, je pense que l’ordi n’est pas utilisé à autre chose dans le même temps.







    Finalement je reprends ton idée de pygame.event.wait() et je propose:

    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
    17
    18
    19
    20
    21
    from time import clock
     
    KSP = pygame.K_SPACE
    pygevwait = pygame.event.wait
     
    while 1:
     
        pygame.event.set_allowed(pygame.KEYDOWN)
        pygame.event.clear()
     
        draw_stimulus(grey,grey_side)
        pygame.display.flip()
        ticks0 = clock()
     
        if pygevwait()==KSP:
            ticks1 = clock()
            response_time = ticks1 - ticks0
     
        # utilisation de response_time
        # temporisation de la relance du test
        # instruction d'arret du while





    josmiley, que penses tu de ce que j’ai écrit concernant l’usage d’alias ? C’est OK ou incorrect ?







    @ fuyo2004



    - la fonction time.clocks() permet d'obtenir une précision meilleure que la ms, mais en l'utilisant je ne descends toujours pas en-dessous des 4 ms, donc je ne m'y pencherai qu'après avoir résolu ce problème
    Une précision de l’ordre de la ms ne signifie pas que les mesures doivent être de l’ordre de la ms pour que cette précision ait un intérêt. Au contraire.
    Elle signifie que la précision relative sur une mesure sera toujours meilleure que si on a une précision de 1 seconde.
    Ainsi pour une mesure de 1 seconde, la précision relative sera de 0.0001/1 avec une précision de 1 ms (donc fine), tandis qu’elle sera de 1/1 (donc grossière) avec une précision de 1 seconde.

    Une précision de 1 ms pour une mesure de 4 ms n’est pas bonne, voilà pourquoi il vaut mieux que des mesures soient très au dessus de la précision. Mais une précision de 1 seconde est carrément sans intérêt pour une mesure de 4 ms.

    Donc, sauf erreur de ma part, il vaut toujours mieux utiliser un outil précis qu’un moins précis.









    Dans mon code , pygame.display.flip() est en effet dans une boucle mais il ne faut pas se laisser abuser par un nom.

    La boucle while dont il est question est celle pour la répétition du test pas pour le réaffichage permanent de l’image. Une fois pygame.display.flip() exécutée pour un test, l’affichage n’est pas relancé tant que l’appui de la touche ESPACE n’est pas effectué (du moins c’est ce que je vise dans mon code).

    C’est bien pourquoi j’ai mis en commentaires pour bien mettre en évidence la nature de la boucle, et que j’ai écrit
    le pygame.display.flip() ne se trouve pas réexécuté tant que response_time n’a pas pris sa valeur.







    while pep().key != KSP:
    AttributeError: event member not defined
    Ça ne m’étonne pas, je ne connais pas particulièrement pygame. Mes réponse sont des propositions d’idées.

    Peut être le nouveau code que j’ai mis ci-dessus fera-t-il mieux ?










    Il me semblait que dans le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    te = clock()
    a = 10
    tf = clock()
    diff = tf - te
    sur l’instruction tf = clock(), l’interpréteur n’a pas à se poser de question:
    il évalue ce qui est à droite, c’est à dire qu’il crée un objet qui contient l’information renvoyée par clock(),
    puis il colle illico l’étiquette tf sur cet objet et je pensais que c’était très rapide.

    Tandis que je pensais que dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    te = clock()
    a= 10
    diff = clock() - te
    l’interpréteur devant procéder à une analyse de ce qui se trouve à droite avant de faire les opérations, analyse qui est nécessairement (me dis-je) plus longue que dans le cas précédent puisqu’il y a cette fois ci deux éléments au lieu de 1 (et même 3 puisqu’il doit identifier l’opérateur, mais je ne sais pas si c’est avant ou après avoir évalué clock() ),
    eh bien donc je pensais que le premier code était plus rapide.


    Or ta question m’a poussé à faire ce que je n’avais encore jamais fait sur ce sujet: tester ces impressions.
    Et là, surprise: le second type de code est un tantinet plus rapide que le premier, c’est à dire l’inverse de ce que je croyais.

    Donc tu as raison, il est contre-productif de faire
    tf = clock()
    diff = tf-te

    plutôt que
    diff = clock() - te

    Mais ce n’est pas liée à la soustraction, que j’ai un peu hâtivement avancée comme justificatif bidon à mon affirmation naze.
    La soustraction intervient de toutes façons seulement APRÈS que le second objet clock() ait été constitué (celui auquel on soustrait te). Donc ce clock() ne peut pas intégrer le micro-temps qui est ensuite nécessaire pour mener à bien la sosutraction.

    Alors je me suis rabattu sur l’existence de 3 termes dans clock() - te au lieu d’un seul pour expliquer le petit temps supérieur que je pensais que prenait cette écriture clock() - te.
    Mais en fait ce n’est pas suffisant (ou carrément foireux comme explication). Il semble que la création d’une étiquette tf à coller sur un objet renvoyé par clock() prenne beaucoup de temps et que ça en prenne plus que la putative économie de temps réalisée par ailleurs avec une expression tf = clock() simple.











    - d'après les essais que j'ai pu faire, créer une fonction ptgt pour ne pas avoir à appeler pygame.time.get_ticks() n'augmente pas la résolution temporelle.
    Cela fait peut être gagner un temps trop faible par rapport au temps global, dans ton cas.

    J’aimerais bien avoir un avis sur ce point des alias de la part de quelqu’un qui s’y connaît bien.









    Faire une boucle qui ne fait rien: c’est mieux avec la fonction pygame.event.wait
    C’est pourquoi j’ai taché de la garder dans le code supplémentaire suivant qui tient compte d’arrêter avec ESCAPE.

    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
    17
    18
    19
    20
    21
    22
    23
    24
    from time import clock
     
    KSP = pygame.K_SPACE
    pygevwait = pygame.event.wait
     
    while 1:
     
        pygame.event.set_allowed(pygame.KEYDOWN)
        pygame.event.clear()
     
        draw_stimulus(grey,grey_side)
        pygame.display.flip()
        ticks0 = clock()
     
        if pygevwait() == KSP:
            ticks1 = clock()
            response_time = ticks1 - ticks0
            # utilisation de response_time, par exemple:
            print 'response_time =',response_time
     
        print "Pour arreter: ESC ,  sinon n'importe quelle autre touche"
        if pygevwait() == pygame.K_ESCAPE:
            break
        # temporisation de la relance du test
    Renvoyer le test de ESCAPE après la réaction du programme à une frappe de touche évite de perdre du temps avec une instruction alourdie du genre
    if pygevwait() in (KSP, pygame.K_ESCAPE):









    si j'introduis un print(pygame.time.get_ticks() - ticks0) dans ma boucle pour mesurer le temps écoulé entre deux mesures je risque de fausser ce qui se passe dans la réalité, non ?
    Assurément, car print est très long à s’exécuter.
    Mais attention à quelle boucle dont il est question.
    La seule boucle dans laquelle il ne doit rien se passer, c’est celle durant laquelle il y a attente d’une frappe de touche. En dehors de ça, même un print ne pose pas de problème.
    Cette “boucle“ , cette attente plutôt, est contenue dans le pygevwait() de
    if pygevwait() == KSP:

  16. #16
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 046
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 046
    Points : 1 376
    Points
    1 376
    Par défaut
    Citation Envoyé par fuyo2004 Voir le message
    - est-ce que je gagne quelque chose à mettre un pygame.event.wait() dans ma boucle ou est-ce la même chose de la laisser tourner même quand il ne se passe rien ?
    contrairement à poll() et get(); wait() met le programme en 'veille' et attend que le systeme le réveille(en gros) ce qui libère le processeur pour autre chose.

  17. #17
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 046
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 046
    Points : 1 376
    Points
    1 376
    Par défaut
    version sans pygame.key.get_pressed() ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    pygame.init()
    etc ...
    draw_stimulus(grey,grey_side)
    response_time = None
    pygame.display.flip()
    ticks0 = pygame.time.get_ticks()
    while not response_time:
        for e in pygame.event.get(pygame.KEYDOWN):
            if e.key == pygame.K_SPACE:response_time=pygame.time.get_ticks()-ticks0;break
            elif e.key == pygame.K_ESCAPE:raise Exception()
    @ eyquem
    les appels à key.get_pressed() sont limités grace à event.wait(); si key.get_pressed() rate une frappe, c'est que event.wait() l'a aussi manquée; ce qui n'arrive normalement pas.
    les touches rapidement poussées peuvent être totalement inaperçues entre deux appels à pygame.key.get_pressed()
    en toute logique ...

    maintenant, j'aimerai savoir si le fait que chez moi et d'autres, key.get_pressed() ne peut fonctionner sans interception d'évènement, et lié à la plateform ou autre ...
    je suis sous Debian.

  18. #18
    Membre du Club
    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
    Points : 61
    Points
    61
    Par défaut
    Citation Envoyé par josmiley Voir le message
    contrairement à poll() et get(); wait() met le programme en 'veille' et attend que le systeme le réveille(en gros) ce qui libère le processeur pour autre chose.
    oui mais je n'ai pas besoin qu'il soit libéré pour autre chose a priori. N'y aurait-il pas au contraire un effet d'inertie pour mettre le programme en veille et le réveiller qui allongerait les temps de mesures ?

    Sinon je pense rester sur cette version-là :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    pygame.init()
    etc ...
    draw_stimulus(grey,grey_side)
    pygame.display.flip()
    ticks0 = pygame.time.get_ticks()
    KEY = pygame.key.get_pressed()
    while not KEY[pygame.K_SPACE]|KEY[pygame.K_ESCAPE]:
        pygame.event.wait()
        KEY = pygame.key.get_pressed()
    response_time = pygame.time.get_ticks() - ticks0
    if KEY[K_ESCAPE]:raise Exception()

    je ne pense pas que GET_PRESSED influera trop, comme il est dit dans la notice cette fonction est inadaptée pour la saisie de texte, mais mes présentations de stimuli ont au moins 1 seconde d'intervalle entre chaque donc ça devrait être bon.

  19. #19
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 046
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 046
    Points : 1 376
    Points
    1 376
    Par défaut
    attention à l'ordre des lignes !!!
    regardes bien ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    pygame.init()
    etc ...
    draw_stimulus(grey,grey_side)
    KEY = pygame.key.get_pressed()
    pygame.display.flip()
    ticks0 = pygame.time.get_ticks()
    while not KEY[pygame.K_SPACE]|KEY[pygame.K_ESCAPE]:
        pygame.event.poll()
        KEY = pygame.key.get_pressed()
        print pygame.time.get_ticks() - ticks0
    response_time = pygame.time.get_ticks() - ticks0
    if KEY[pygame.K_ESCAPE]:raise Exception()

  20. #20
    Membre du Club
    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
    Points : 61
    Points
    61
    Par défaut
    Citation Envoyé par josmiley Voir le message
    attention à l'ordre des lignes !!!
    Je ne vois pas trop ce que ça change...
    J'ai repris le code que tu m'avais donné dans un post plus haut.

    Du coup je suis embrouillé, tu as à nouveau enlevé pygame.event.wait() dans ton script, il vaut mieux s'en passer donc ?

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