a-hurst / klibs

A simple Python framework for writing cognitive psychology experiments
7 stars 1 forks source link

Add KLResponseListener module #29

Closed a-hurst closed 1 year ago

a-hurst commented 1 year ago

PR Description

Closes #27. This PR adds a new module, KLResponseListener, to supersede the existing ResponseCollector method of collecting responses from participants. It is designed to be much simpler, more flexible, and more Pythonic than the KLResponseCollectors module and its classes. KLResponseCollectors will still be left in for backwards compatibility with existing code, but shouldn't be used for any new projects.

The problem with KLResponseCollectors is that it's far too complicated for its own good. For example, using the current ResponseCollector class to collect a simple key detection response involves code like this, which is very hard to follow unless you know what self.rc is and how to specify all the possible options:

self.rc.uses(KeyPressResponse)
self.rc.terminate_after = [10, TK_S]
self.rc.display_callback = self.response_callback
self.rc.keypress_listener.key_map = {' ': 'detection'}
self.rc.keypress_listener.interrupts = True

Note that some of these options are self.rc attributes and some are self.rc.keypress_listener attributes, making things very obtuse and to remember or document.

Then, to actually collect the response, you would need to call the collect method and then call a method of a submodule of self.rc to actually get the response value and reaction time:

self.rc.collect()
response, rt = self.rc.keypress_listener.response()

By contrast, creating an equivalent keypress listener with the new KeypressListener class is much simpler and more readable:

self.key_listener = KeypressListener(
    {' ': 'detection'}, timeout=10, loop_callback=self.response_callback
)

Likewise, collecting responses and retrieving the response values is now done in a single line:

response, rt = self.key_listener.collect()

Currently, only 3 ResponseListeners have been implemented:

Additional ResponseListeners may be added in the future, but these three are by far the most commonly used. Equivalents of AudioResponse and DrawResponse have not been ported over from KLResponseCollector due to their niche use cases, but could be easily implemented as project-specific BaseResponseListener subclasses or added into klibs itself at a future date.

Further, the new KLResponseListeners module has extensive documentation and basic unit testing, both of which are a large improvement over KLResponseCollectors.

Merge Checklist