gentnerlab / pyoperant

python package for operant conditioning
BSD 3-Clause "New" or "Revised" License
13 stars 15 forks source link

Refactor interface code #109

Open siriuslee opened 8 years ago

siriuslee commented 8 years ago

I have been working on writing a new interface for our lab's chronic recordings using pylibnidaqmx. This has raised several thoughts in my mind about some useful changes we can make to the interface code (and higher level abstractions). Some of these are just general thoughts and some have arisen because we need to write analog outputs, read analog inputs, and write boolean arrays on the boolean outputs. I would really appreciate any and all feedback on any of these points.

  1. It would be great to have each interface have some standard properties that the abstract layers can send. For these, I would suggest: "subdevice", "channel" and "invert". If an interface doesn't need these, they can be ignored by accepting **kwargs as an input.
  2. Change _config_write and _config_read to _config_write_bool and _config_read_bool to allow more cleanly for their analog counterparts
  3. Interfaces with boolean outputs should be rewritten to allow for boolean arrays to be sent (required for addressing #108)
  4. Add some useful properties and methods to the BaseInterface class to minimize the amount of work when implementing a new interface. One nice one would be a polling method since a python version can be done pretty easily with a while loop and an implemented _readbool method. I can do this by cleaning up my code from the arduino interface. Further, the base class could have properties such as "can_read_bool" to easily describe its capabilities.

Other things that I think would be cleaner but might be a bit over-engineered:

  1. Should the AudioOutput class really be in hwio? I have to add AnalogOutput and AnalogInput classes which should share a lot of implementation with AudioOutput. If possible, it might be cleaner to move to a speaker component with an AnalogOutput instance as an output. The interfaces could then also implement functions like "_queue_output" and "_clear_output" to provide a more general implementation than "_queue_wav" and "_stop_wav".
  2. It would be great to start thinking about splitting some components off into their own separate thread. It's often possible to make an experiment using only sequential operations, but that can be pretty hacky. Further, if we want trigger a trial start using one of two separate reasons (e.g. microphone threshold crossing or button press), it really can't be done serially. To keep delays down when implementing #108 I've already had to start doing this.