{"id":216,"date":"2020-12-13T13:42:13","date_gmt":"2020-12-13T17:42:13","guid":{"rendered":"http:\/\/blog.labhackers.com\/?p=216"},"modified":"2020-12-21T12:26:47","modified_gmt":"2020-12-21T16:26:47","slug":"test-visual-stimulus-onset-timing-using-keyboard-events","status":"publish","type":"post","link":"https:\/\/blog.labhackers.com\/?p=216","title":{"rendered":"Test Visual Stimulus Onset Timing using Keyboard Events !?"},"content":{"rendered":"\n<p><sup>Originally posted on March 6, 2019.<\/sup><\/p>\n\n\n\n<p>In this post we look at how to use the&nbsp;<a href=\"http:\/\/www.labhackers.com\/millikey.html\">MilliKey&nbsp;<\/a>DeLux light sensor upgrade to test visual stimulus onset timing using&nbsp;<a href=\"https:\/\/psychopy.org\/\">PsychoPy<\/a>&nbsp;Coder by checking for a keyboard event.<\/p>\n\n\n\n<div class=\"wp-block-media-text alignwide is-stacked-on-mobile\" style=\"grid-template-columns:41% auto\"><figure class=\"wp-block-media-text__media\"><img loading=\"lazy\" decoding=\"async\" width=\"350\" height=\"320\" src=\"https:\/\/blog.labhackers.com\/wp-content\/uploads\/2020\/12\/millikey_delux_sml-2.png\" alt=\"\" class=\"wp-image-385 size-full\" srcset=\"https:\/\/blog.labhackers.com\/wp-content\/uploads\/2020\/12\/millikey_delux_sml-2.png 350w, https:\/\/blog.labhackers.com\/wp-content\/uploads\/2020\/12\/millikey_delux_sml-2-300x274.png 300w\" sizes=\"auto, (max-width: 350px) 100vw, 350px\" \/><\/figure><div class=\"wp-block-media-text__content\">\n<p class=\"has-large-font-size\">The MilliKey DeLux is an affordable and easy to use light sensor attachment for MilliKey response boxes. The MilliKey DeLux can generate light level driven&nbsp;<strong>1000 Hz USB serial or keyboard events<\/strong>&nbsp;that are read by the same experiment software controlling visual stimulus presentation.<\/p>\n<\/div><\/div>\n\n\n\n<p>In a previous post about&nbsp;<a href=\"http:\/\/blog.labhackers.com\/?p=134\" target=\"_blank\" rel=\"noreferrer noopener\">Testing PsychoPy event.waitKeys() Event Timing<\/a>, we demonstrated how to use the MilliKey to test the keyboard event time stamping accuracy of the experiment software. This was achieved by sending USB serial messages from the experiment software instructing the MilliKey to generate keyboard events and then comparing the key press time to the time the serial message was sent. We found that, at least on Windows and Linux, PsychoPy can accurately time stamp MilliKey 1000 Hz keyboard events with one millisecond average delay and sub-millisecond variability.<\/p>\n\n\n\n<p>One of the unique features of the MilliKey DeLux is that it can be configured to generate a letter \u2018l\u2019 key press event when the light sensor brightness crosses a trigger threshold level. This allows you to assess visual stimulus onset timing of an experiment by using the standard keyboard event handling functionality of the software being used.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">PsychoPy Coder Test Script<\/h2>\n\n\n\n<p>Lets start by creating a simple PsychoPy Coder demo that repeatedly:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>clears the screen to black<\/li><li>draws a white screen<\/li><li>waits for a keyboard press event<\/li><li>prints time difference between reported keyboard event and stimulus onset (white screen) times.<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">#!\/usr\/bin\/env python\n# -*- coding: utf-8 -*-\nfrom __future__ import absolute_import, division, print_function\nfrom psychopy import visual, event, core\n\n# Number of dark -> light display change tests to run\ntest_count = 10\n\n# Create a full screen window and two full screen stim.\nwin = visual.Window(fullscr=True, screen=0)\nwhite_stim = visual.ShapeStim(win, lineColor='white', fillColor='white',\n                              vertices=((-1,-1),(1,-1),(1,1),(-1,1)))\ndark_stim = visual.ShapeStim(win, lineColor='black', fillColor='black',\n                             vertices=((-1,-1),(1,-1),(1,1),(-1,1)))\n\n# draw \/ setup both stim\nwhite_stim.draw()\ndark_stim.draw()\nwin.flip()\n\n# Manually press any key to start test\nevent.waitKeys(timeStamped=True)\n\nprint(\"trial\\tRT\\tkey_time\\tflip_time\\tkey\")\n# run test_count loops\ncount=0\nwhile count &lt; test_count:\n    # Draw black screen and display it for about 0.5 seconds.\n    dark_stim.draw()\n    win.flip()\n    core.wait(0.5)\n # Throw away any possible junk keys\n # prior to changing display \n    event.getKeys()\n \n    # Draw white (target) stim and flip to it,\n    # getting time flip occurred (stim onset)\n    # time from psychopy.\n    white_stim.draw()\n    ftime = win.flip()\n\n # Key keyboard event and print time difference between\n # flip() time and keypress time.\n    k, ktime = event.waitKeys(timeStamped=True)[0]\n    kdelay = ktime - ftime    \n    print(\"%d\\t%.6f\\t%.6f\\t%.6f\\t%s\"%(count, kdelay, ftime, ktime, k))\n\n    core.wait(0.25)\n    count+=1<\/code><\/pre>\n\n\n\n<p>We have basically created the most simple of manual reaction time tests. Run the above script from PsychoPy Coder and press a key as quickly as you can each time the screen turns white.<\/p>\n\n\n\n<p>For example, running the example and manually pressing the space key, I get output like:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">trial\tRT\tkey_time\tflip_time\tkey\n0\t0.368140\t1.687949\t2.056089\tspace\n1\t0.171302\t2.570518\t2.741820\tspace\n2\t0.197275\t3.256913\t3.454187\tspace\n3\t0.198487\t3.967356\t4.165843\tspace\n4\t0.196070\t4.679771\t4.875841\tspace\n5\t0.215323\t5.390571\t5.605894\tspace\n6\t0.197549\t6.118132\t6.315682\tspace\n7\t0.193179\t6.828715\t7.021894\tspace\n8\t0.166193\t7.535785\t7.701978\tspace\n9\t0.193039\t8.214774\t8.407813\tspace<\/pre>\n\n\n\n<p>So far this has all been kind of boring right?<\/p>\n\n\n\n<p>What if we could use&nbsp;<em>this exact script<\/em>&nbsp;to test the visual onset timing of the white screen? Lets do it using the MilliKey DeLux.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">MilliKey DeLux Setup<\/h2>\n\n\n\n<p>For this test to work we first need to make sure the MilliKey DeLux is configured to:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>use a sensible threshold level for the monitor being Generate Keyboard Events.<\/li><li>auto generate light sensor triggered keyboard events.<\/li><\/ol>\n\n\n\n<p>Lets do this using the LabHackers\u2019 Device Manager application.<\/p>\n\n\n\n<div class=\"wp-block-media-text alignwide is-stacked-on-mobile\" style=\"grid-template-columns:37% auto\"><figure class=\"wp-block-media-text__media\"><img loading=\"lazy\" decoding=\"async\" width=\"190\" height=\"266\" src=\"https:\/\/blog.labhackers.com\/wp-content\/uploads\/2020\/12\/lhdm_delux_tab.png\" alt=\"\" class=\"wp-image-386 size-full\"\/><\/figure><div class=\"wp-block-media-text__content\">\n<p>MilliKey DeLux light sensor settings are found on the DeLux tab of the LabHackers\u2019 Device Manager application.<\/p>\n\n\n\n<p>For this example use the following settings:<br><strong>Trigger Type<\/strong>: \u2018Keyboard Event\u2019<br><strong>Trigger Delay<\/strong>: 5 msec<br><strong>Enable Background Processing<\/strong>: Checked \/ True<\/p>\n<\/div><\/div>\n\n\n\n<p>The<strong>&nbsp;Trigger Threshold<\/strong>&nbsp;setting can be set using the auto threshold feature of the Light Sensor Dialog. The following video is a screen capture from a Windows 10 computer running the Labhackers\u2019 Device Manager application. It illustrates using the auto threshold feature to set the light sensor threshold to an appropriate level for the monitor being tested. The MilliKey DeLux hardware, which can not be seen in the video, was placed over the white rectangle of the test dialog on the LCD monitor.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-rich is-provider-embed-handler wp-block-embed-embed-handler wp-embed-aspect-4-3 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"MilliKey DeLux Keyboard Trigger Configuration\" width=\"750\" height=\"563\" src=\"https:\/\/www.youtube.com\/embed\/UmUa79bcdnE?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>After you have configured the MilliKey DeLux to generate \u2018offline\u2019 keyboard events, and have exited the LabHackers\u2019 Device Manager, the MilliKey will generate a \u2018l\u2019 key press event 5 milliseconds (Trigger Delay) after screen brightness crosses the threshold level set. Each key press lasts 123 msec, at which time a key release event is sent by the MilliKey.<\/p>\n\n\n\n<p><strong>Note:<\/strong>&nbsp;Once the MilliKey DeLux is&nbsp;<em>armed<\/em>&nbsp;and ready to create keyboard events, if the light level hitting the is not controlled you may get a bunch of letter \u2018l\u2019s being typed on your computer. If you want to abort this test and get the MilliKey to stop generating keyboard events, unplug the MilliKey USB cable from the computer and reconnect it. This turns off the&nbsp;<strong>Enable Background Processing<\/strong>&nbsp;setting, which is disabled by default when you first connect the MilliKey to a computer.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Results<\/h2>\n\n\n\n<p>For this test we used a Windows 7 computer connected to a CRT monitor running at 60Hz. We used a CRT monitor because there is effectively no delay between when a video card starts a screen retrace and when the top left corner of the CRT monitor starts displaying update. In contrast LCD \/ TFT monitors all have a response time, which can range between 1 and 10+ msec depending on the monitor model.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">trial   RT      key_time        flip_time       key\n0       0.004892        4.412357        4.417248        l\n1       0.005464        5.188762        5.194226        l\n2       0.005237        5.976979        5.982216        l\n3       0.005049        6.765145        6.770194        l\n4       0.004792        7.553340        7.558132        l\n5       0.005583        8.341535        8.347118        l\n6       0.005390        9.129753        9.135143        l\n7       0.005198        9.917925        9.923123        l\n8       0.005766        10.694352       10.700118       l\n9       0.005555        11.482574       11.488128       l<\/pre>\n\n\n\n<p>Since a CRT monitor was used, the time difference between win.flip() and when the CRT actually starts being updated should be 0.0 msec. Remember that we set the MilliKey DeLux to generate the key press event 5 msec after the stimulus onset was detected by the device hardware, so if win.flip() is accurate, the delay calculated by the test should be 0.0 after we subtract the 5 msec event delay specified in the device settings.<\/p>\n\n\n\n<p>As the following table shows, they are:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>0<\/td><td>0.0049<\/td><td>-0.0001<\/td><\/tr><tr><td>1<\/td><td>0.0055<\/td><td>0.0005<\/td><\/tr><tr><td>2<\/td><td>0.0052<\/td><td>0.0002<\/td><\/tr><tr><td>3<\/td><td>0.0050<\/td><td>0.0000<\/td><\/tr><tr><td>4<\/td><td>0.0048<\/td><td>-0.0002<\/td><\/tr><tr><td>5<\/td><td>0.0056<\/td><td>0.0006<\/td><\/tr><tr><td>6<\/td><td>0.0054<\/td><td>0.0004<\/td><\/tr><tr><td>7<\/td><td>0.0052<\/td><td>0.0002<\/td><\/tr><tr><td>8<\/td><td>0.0058<\/td><td>0.0008<\/td><\/tr><tr><td>9<\/td><td>0.0056<\/td><td>0.0006<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>It is important to note that using keyboard events as light sensor triggers is only suggested on systems that provide accurate keyboard event timing. Therefore we can not suggest this method for PsychoPy testing on macOS at this time. macOS users should use the Serial event mode, which we will demonstrate in a future post.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Next<\/h2>\n\n\n\n<p>The MilliKey DeLux keyboard event mode is very useful for testing stimulus onset timing in experiment software that you know provides accurate keyboard event timing and when you can not, or do not, want to add custom code to your experiment.<\/p>\n\n\n\n<p>If the keyboard event time stamping accuracy of the software being used is poor, or you would rather not get light sensor triggers as keyboard events, then you can use USB Serial events instead. In the next MilliKey DeLux post, we will look at using the Serial trigger type to test stimulus onset timing in a PsychoPy Coder experiment.<\/p>\n\n\n\n<p>Happy Hacking!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Originally posted on March 6, 2019. In this post we look at how to use the&nbsp;MilliKey&nbsp;DeLux light sensor upgrade to test visual stimulus onset timing using&nbsp;PsychoPy&nbsp;Coder by checking for a keyboard event. The MilliKey DeLux is an affordable and easy to use light sensor attachment for MilliKey response boxes. The MilliKey DeLux can generate light&hellip; <a class=\"more-link\" href=\"https:\/\/blog.labhackers.com\/?p=216\">Continue reading <span class=\"screen-reader-text\">Test Visual Stimulus Onset Timing using Keyboard Events !?<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","footnotes":""},"categories":[19,17,20],"tags":[22,21,15,8,18,10,14],"class_list":["post-216","post","type-post","status-publish","format-standard","hentry","category-display-timing","category-keyboard-event-timing","category-millikey-delux-light-sensor","tag-delux","tag-display","tag-keyboard","tag-millikey","tag-psychopy","tag-python","tag-timing","entry"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/blog.labhackers.com\/index.php?rest_route=\/wp\/v2\/posts\/216","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.labhackers.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.labhackers.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.labhackers.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.labhackers.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=216"}],"version-history":[{"count":6,"href":"https:\/\/blog.labhackers.com\/index.php?rest_route=\/wp\/v2\/posts\/216\/revisions"}],"predecessor-version":[{"id":448,"href":"https:\/\/blog.labhackers.com\/index.php?rest_route=\/wp\/v2\/posts\/216\/revisions\/448"}],"wp:attachment":[{"href":"https:\/\/blog.labhackers.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=216"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.labhackers.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=216"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.labhackers.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=216"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}