Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Registries, Plugins, and Wiki Integration #109

merged 18 commits into from
Jul 27, 2021


Copy link

@sneakers-the-rat sneakers-the-rat commented Jul 22, 2021

Very late now, but I believe i have done this: #39

I will return tomorrow to write the docs and the PR, but yes it is time.

dump anything that inherits from the appropriate metaclass into PLUGINDIR and...

import autopilot

# list all hardware
# or an alias

# get hardware (including from plugins)
autopilot.get('hardware', 'PWM')

# get anything

and as a little bonus...

>>> from autopilot.utils import wiki
>>> wiki.ask('[[HiFiBerry Amp2]]', "Uses GPIO Pin")
[{'Uses GPIO Pin': [3, 5, 7, 12, 35, 38, 40],
  'name': 'HiFiBerry Amp2',
  'url': ''}]

which will serve as the means of submitting plugins and doing some stuff that is truly messed up how cool it is... more soon ;)

Copy link
Contributor Author

this is like a 1000% improvement in usability in my opinion.

Copy link
Contributor Author

also i am removing the requirement for 3.7 and am just going to note the dependency on spinnaker in the docs and throw exceptions (i don't even know if that is a limitation still, but being 3 versions behind now for literally no reason seems bad). added 3.7-9 to the CI

Copy link
Contributor Author

ok since there's a decent amount of documentation to be written i'm just going to merge this now and write docs after everything has been merged from this and parallax

@sneakers-the-rat sneakers-the-rat merged commit 13c4c56 into dev Jul 27, 2021
@sneakers-the-rat sneakers-the-rat deleted the simpler_registries branch July 27, 2021 00:46
@sneakers-the-rat sneakers-the-rat added this to the v0.4.0 milestone Jul 30, 2021
sneakers-the-rat added a commit that referenced this pull request Aug 4, 2021
OK i am too fried to write the PR description, and there's still a bit to do here, but i want to start hoisting this massive thing onto the table. one day we will do this in a way that isn't rewriting the whole thing between versions, but it is not this day.

v0.4.0 - Become Multifarious (July 30, 2021)

This release is primarily to introduce the new plugin system, the autopilot wiki, and their integration as a way of
starting the transformation of Autopilot into a tool with decentralized development and governance (as well as
make using the tool a whole lot easier and more powerful).

*With humble thanks to Lucas Ott, Tillie Morris,* `Chris Rodgers <>`_,
`Arne Meyer <>`_ , `Mikkel Roald-Arbøl <>`_ ,
`David Robbe <>`_ ,
*and an anonymous discussion board poster for being part of this release.*

New Features

* `Registries & Plugins <>`_ - Autopilot now supports users writing their code
  outside of the library as plugins! To support this, a registry system was implemented throughout the program. Plugin objects
  can be developed as objects that inherit from the Autopilot object tree -- eg. implementing a GPIO object by subclassing
  :class:`.hardware.gpio.GPIO` , or a new task by subclassing :class:`~.tasks.task.Task` . This system is flexible enough
  to allow any lineage of objects to be included as a plugin -- stimuli, tasks, and so on -- and we will be working to
  expand registries to every object in Autopilot, including the ability for plugins to replace core modules to make
  Autopilot's flexibility verge on ludicrous. The basic syntax of the registry system is simple and doesn't require any
  additional logic beyond inheritance to be implemented on plugin objects -- ``autopilot.get('object_type', 'object_name')``
  is the basic method, with a few aliases for specific object types like ``autopilot.get_hardware()``. Also thanks to
  `Arne Meyer <>`_ for submitting an early draft of the registry system and
  `Mikkel Roald-Arbøl <>`_ for raising the issue.
* At long last, the Autopilot Wiki is alive!!!! - - The wiki is the place for communal
  preservation of technical knowledge about using Autopilot, like hardware designs, build guides, parameter sets,
  and beyond! This isn't any ordinary wiki, though, we got ourselves a *semantic wiki* which augments traditional wikis
  with a rich system of human and computer-readable linked attributes: a particular type of page will have some set of attributes,
  like a page about a 3D printed part will have an associated .stl file, but rather than having these be in plaintext
  they are specified in a format that is queryable, extensible, and infinitely mutable. The vision for the wiki is much
  grander (but not speculative! very concrete!) than just a place to take notes, but is intended to blend the use of
  Autopilot as an experimental tool with body of knowledge that supports it. Autopilot can query the wiki with the ``wiki`` module
  like ``wiki.ask('[[Category:3D_CAD]]', 'Has STL')`` to get links to all .stl files for all 3D parts on the wiki. The integration
  between the two makes using and submitting information trivial, but *also* makes *designing whole new types of community interfaces*
  completely trivial. As a first pass, the Wiki will be the place to index plugins, the system for submitting them, querying them,
  and downloading them only took a few hours and few dozen lines of code to implement. The wiki is infinitely malleable -- that's the point --
  and I am very excited to see how people use it.
* Tests & Continuous Integration with Travis! We are on the board with having nonzero tests! The travis page is here:
  and the coveralls page is here: .  At the moment we have a whopping 27% coverage,
  but as we build out our testing suite we hope that it will become much easier for people to contribute to Autopilot and be
  confident that it works!
* New Hardware Objects
    * :class:`.cameras.PiCamera` - A fast interface to the PiCamera, wrapping the picamera library, and using tips from its developer to juice every bit of speed i could!
    * The I2C_9DOF object was massively improved to take better advantage of its onboard DSP and expose more of its i2c commands.
* New Transforms
    * :class:`.timeseries.Kalman` - adapted a Kalman filter from the wonderful filterpy package! it's in the new timeseries transform module
    * :class:`.geometry.IMU_Orientation` - IMU_Orientation performs a sensor fusion algorithm with the Kalman Filter class to combine gyroscope and accelerometer measurements into a better estimate of earth-centric roll and pitch.
      This is used by the IMU class, but is made independent so it can be used without an Autopilot hardware object/post-facto/etc.
    * :class:`.timeseries.Filter_IIR` - Filter_IIR implements scipy's IIR filter as a transform object.
    * :class:`.timeseries.Integrate` - Integrate adds successive numbers together (scaled by dt if requested). not much by itself, but when used with a kalman filter very useful :)
    * :class:`.geometry.Rotate` - use scipy to rotate a vector by some angle in x, y, and/or z
    * :class:`.geometry.Spheroid` - fit and transform 3d coordinates according to some spheroid - used in the IMU's accelerometer calibration method: given some target spheroid, and some deformed spheroid (eg. a miscalibrated accelerometer might have the x, y, or z axis scaled or offset) either explicitly set or estimated from a series of point measurements, transform future input given that transformation to correct for the deformed source spheroid.
* New Prefs
    * ``'AUTOPLUGIN'`` - Attempt to import the contents of the plugin directory,
    * ``'PLUGIN_DB'`` - filename to use for the .json plugin_db that keeps track of installed plugins',
    * ``'PING_INTERVAL'`` - How many seconds should pilots wait in between pinging the Terminal?',
    * ``'TERMINAL_SETTINGS_FN'`` - filename to store QSettings file for Terminal',
    * ``'TERMINAL_WINSIZE_BEHAVIOR'`` - Strategy for resizing terminal window on opening',
    * ``'TERMINAL_CUSTOM_SIZE'`` - Custom size for window, specified as [px from left, px from top, width, height]',

Major Improvements

* Stereo Sound (Thank you `Chris Rodgers! <>`_) - #102
* Multihop messages & direct messaging - #99 - it is now possible to
  send multihop messages through multiple Station objects, as well as easier to send messages directly
  between net nodes. See the examples in the network tests section of the docs.
* Multiple Children  (Thank you `Chris Rodgers! <>`_) - #103 -
  the ``CHILDID`` field now accepts a list, allowing a Pilot to initialize child tasks on multiple children. (this syntax and
  the hierarchical nature of pilots and children will be deprecated as we refactor the networking modules into a general mesh system,
  but this is lovely to have for now :)
* Programmatic Setup - #33 - noninteractive setup of prefs and
  scripts by using ``autopilot.setup -f prefs.json -p PREFNAME=VALUE -s scriptname1 -s scriptname2``
* Widget to stream video, en route to more widgets for direct GUI control of hardware objects connected to pilots
* Support python 3.8 and 3.9 essentially by not insisting that the spinnaker SDK be installable by all users (which at the time
  was only available for 3.7)

Minor Improvements

* Terminal can be opened maximized, or have its size and position set explicitly, preserve between launches (Thank you `Chris Rodgers! <>`_) - #70
* Pilots will periodically ping the Terminal again, Terminal can manually ping Pilots that may have gone silent - #91
* Pilots share their prefs with the Terminal in their initial handshake - #91
* Reintroduce router ports for net-nodes to allow them to bind a port to receive messages - 35be5d6
* Listen methods are now optional for net_nodes
* Allowed the creation of dataless tasks - 628e1fb
* Allowed the creation of plotless tasks - 08d99d5
* The ``I2C_9DOF`` clas uses memoryviews rather than buffers for a small performance boost - 890f2c5
* Phasing out using ``Queue`` s in favor of ``collections.deque`` for applications that only need thread and not process safety because they
  are way faster and what we wanted in the first place anyway.
* New Scripts - ``i2c``, ``picamera``, ``env_terminal``
* utils.NumpyEncoder and decoder to allow numpy arrays to be json serialized
* calibrations are now loaded by hardware objects themselves instead of the extraordinarily convoluted system in ``prefs`` -- though
  some zombie code still remains there.
* Net nodes know their ip now, but this is a lateral improvement pending a reworking of the networking modules.
* ``performance`` script now sets ``swappiness = 10`` to discourage the use of swapfiles - see
* Setting a string in the ``deprecation`` field of a pref in ``_DEFAULTS`` prints it as a warning to start actually deprecating responsibly.
* Logging in more places like Subject creation, manipulation, protocol assignation.


* Loggers would only work for the last object that was instantiated, which was really embarassing. fixed - #91
* Graduation criteria were calculated incorrectly when subjects were demoted in stages of a protocol - #91
* fix durations in solenoid class (Thank you `Chris Rodgers! <>`_) - #63
* LED_RGB ignores zero - #98
* Fix batch assignment window crashing when there are subjects that are unassigned to a task - e42fc58
* Catch malformed protocols in batch assignment widget - 2cc8508
* Remove broken ``Terminal.reset_ui`` method and made control panel better at adding/removing pilots - #91
* Subject class handles unexpected state a lot better (eg. no task assigned, no step assigned, tasks with no data.) but is still
  an absolute travesty that needs to be refactored badly.
* The jackclient would crash with long-running continuous sounds as the thread feeding it samples eventually hiccuped.
  Made more robust by having jackclient store samples locally int he sound server rather than being continuously streamed from the queue.
* PySide2 references still incorrectly used ``QtGui`` rather than ``QtWidgets``
* pigpio scripts would not be stopped and removed when a task was stopped, the :func:`.gpio.clear_scripts` function now handles that.
* ``xcb`` was removed from ``PySide2`` distributions, so it's now listed in the requirements for the Terminal and made available in the ``env_terminal`` script.
* ``LED_RGB`` didn't appropriately raise a ``ValueError`` when called with a single ``pin`` - #117
* A fistful of lingering Python 2 artifacts

Code Structure

* continuing to split out modules in :mod:`autopilot.core` - networking this time
* utils is now a separate module instead of being in multiple places
* the npyscreen forms in ``setup_autopilot`` were moved to a separate module
* ``setup_autopilot`` was broken into functions instead of a very long and impenetrable script. still a bit of cleaning to do there.
* ``autopilot.setup.setup_autopilot`` was always extremely awkward, so it's now been aliased as ``autopilot.setup``
* the docs have now been split into subfolders rather than period separated names to make urls nicer -- eg /dev/hardware/cameras.htm
  rather than /dev/hardware.cameras.html . this should break some links when switching between versions on readthedocs
  but other than that be nondestructive.


* new :ref:`quickstart` documentation with lots of quick examples!


* Removed the ``check_compatible`` method in the Transforms class. We will want to make a call at some point if we want to implement a full realtime pipelining framework or if we want to use something like luigi or joblib or etc.
  for now this is an admission that type and shape checking was never really implemented but it does raise some exceptions sometimes.

## todo before merge

- [x] changelog
- [x] write plugins docs
- [x] write wiki docs
- [x] finish uploading initial round of information to wiki
- [x] refresh user guide docs
- [x] remove lab-specific code.

* platform driver skeleton

* formatting

* formatting

* note on processing

* testing docs

* checkpoint actually think i'm misreading the basic program

* mask method implemented with columnwise bit banging

* a lil more documentation and type annotation

* how 2 document props?

* how 2 document props?

* draft height prop

* bugfixing plat

* lol compare the variable not the literal number 2

* absolute value

* clean init

* fliplr binary col command

* doin it manual style

* copy instead of replace

* testing faster move speed

* release method, default times

* join method

* draft absolute position movement mode

* level method

* lower than max for now

* lower than max for now

* lower than max for now

* maybe loading variable wrong?

* ohhh its the mask lol

* remeasured offsets

* remeasured offsets

* handle setting height with int when mask is all zeros
implement __getitem__ and __setitem__ for setting height.

* update docs, include examples

* oop forgot about how sensitive sphinx was to headers

* need linebreaks, also giving example header a little space

* omg sphinx

* omg sphinx

* logging in subject creation

* more logging flags....
fixing unraised exceptions in subject
handling exceptions in graduation init
logger in subject

* handle unassigned subjects in batch reassign, various other bugfixes and cleanups int he godforsaken gui module

* raise exception with informative error if prepare_run called without current

* correct check for presence of trial table
mute annoying lack of base sound class, be noisy if it fails instead.

* provisionally allow dataless tasks...

* allow tasks without plots

* Update

crude hack to get the QtWdigets for calibrate ports working by commenting out QFont stuff

* catch malformed protocol files in batch reassign

* removing extraneous spaces; adding a few comments

* comments

* qt deprecations: replacing desktop with primaryScreen and screenGeometry with size

* comments

* removing commented code about logo

* remove the subtractions, because this is all captured by availableGeometry anyway

* implementing new pref TERMINAL_WINSIZE_BEHAVIOR

* bugfix

* index error when assigning height with int

* velocity mode

* can't have negative params

* negative values of velocity, and make 0 velocity init stick

* pigpio by asking for permission instead of checking agent in i2c

* start pigpiod

* buffer -> memoryview
script to enable i2c

* - don't erase private variables on init
- use numpy instead of struct

* squeeze extra dims

* IIR Filter transform

* add to docs

* actually add to docs...

* jesus christ get the name right

* correct attributes

* testing references

* bibtex not biblatex

* pitch and roll

* implementing kalman filter and orientation transform... doing some testing.

* uysing degrees again, setting default gyro scale

* Let terminal GUI remember its previous size (depending on a new pref) (#68)

* removing extraneous spaces; adding a few comments

* comments

* qt deprecations: replacing desktop with primaryScreen and screenGeometry with size

* comments

* removing commented code about logo

* remove the subtractions, because this is all captured by availableGeometry anyway

* implementing new pref TERMINAL_WINSIZE_BEHAVIOR

* Revert "Let terminal GUI remember its previous size (depending on a new pref) (#68)"

This reverts commit eda5404.

* minor thangs

- cleaned up docstring a little bit
- switched location of terminal settings to 'TERMINAL_SETETINGS_FN'
- added 'custom' size mode
- made 'TERMINAL_WINSIZE_BEHAVIOR', a 'choice' box, and 'remember' is the default
- fixed resizing of Control Panel widgets so they fill the available space

* play nicely on cli, exit with 1 if scripts weren't successful

* set gyro HPF

* draft orientation kalman filter wrapper
- change to [roll, pitch]

* bugfixin'

* bugfixin'

* bugfixin'

* bugfixin'

* bugfixin'

* bugfixin'

* not just deleting every entry

* not just deleting every entry

* add flag to invert gyro measaurements

* adding scripts to docs

* refactor imu processor and 9dof
- build in kalman filtration into rotation attr
- make imu orientation class more flexible (implements the general trig but also the kalman filter)
- keep last readings
- set i2c baudrate to 100kHz in i2c script

* extra dimension

* start implementing rotation, adding spec for accel range

* rotate class

* correct comparison

* correct comparison

* correct comparison

* flipping gyroscope polarity

* eye instead of ones...

* lower HPF, increase accel range

* read separately?

* integrate and add

* don't require format in and out until they like work lol

* reinstate route port, make lsitens optional

* reinstate route port, make lsitens optional

* log history changes in subject

* spheroid transformer and tests

- numpy encoder for serializing to json
- start of calibration logic in hardware classes

* travis???

* an example

* calibration routine for accelerometer

* gathering info for picamera class
add picamera script

* PiCamera draft!!!

* docs ref fixes

* ig picamera doesn't use latest on rtd

* starting to write parallax task

* making video widget to stream frames to while positioning/configuring/training dlc
also fixing old QtGui calls
- !!! and sending prefs from pilot with handshake method

* catch errors on creating batch reassign window

- remade pop_dialogue function to use pyside2 objects, support window modality
- started to gather shorthand references to GUI objects in _MAPS object...

good lord the GUI needs to be rearchitected.

* patches for subject...
- record step in assign_protocol, rather than in the terminal, as was done for some reason before
- fix get_step_history which would get hung on a unicode error
- filter data given to graduation objects such that data from previous runs on a particular step are removed -- eg. if the subject was pushed back to do a step again, don't give data from the previous time the subject did the step to assess graduation criteria or else it would always graduate immediately.

* starting to work with pi

* fix add new pilot in gui
fix pinging

* video streaming draft

* video streaming draft

* video streaming draft

* video streaming draft

* video streaming draft

* video streaming draft

* fixing autograd actually

* really actually fixing autograduation by actually slicing the table to exclude trials from after the reassignment window
- don't overwrite grad params if subject has overlapping params
- cleaned up old python 2 relics & some unnecessary whitespace & imports

* fixing pi state calls and start button updating
- fixing add new pilot panel when new pilots signal their existence
- actually storing and transmitting state correctly
- creating pilots in pilot_db

* reimplementing continous sounds as something that jackd holds locally as a cycle rather than as a thread that feeds jack server.

* reimplementing continous sounds as something that jackd holds locally as a cycle rather than as a thread that feeds jack server.

* start button can ping pis

* pilots ping

* add closeEvent to video streamer
- try to fix logging from multiple sources
- don't send continuous data to plots if they don't exist
- remove socket.sending check from single message streams
- make default min_size in stream video == 1
- handle full queues in camera class

* trying deque instead of queue

* trying deque instead of queue

* trying deque instead of queue

* nocopy on send

* implement grayscale

* implementing fast grayscale capture

* implementing fast grayscale capture

* dq

* fixing online graduation
giving graduation objects loggers

* Fixing logging from multiple objects in the same logger
- instead of giving the file handler to the individual logger that we create, eg. "", we need to give it to the parent module-level logger object, so that logging messages from children are passed up and all use it. as is, only the first logger for a given module actually logs.
- if the log directory doesn't exist, try to create it.

* writing video
camera rotation
moving big comment block in gui to scaprs lol

* bugfixin

* bugfixin

* fix pilot db update
picamera release
pyqtgraph image axis order

* - clear scripts when stopping task
- put task end method in 'finally' block
- add 'swappiness = 10' to performance script

* linebreak that didn't make it?

* dont raise warnings lmao

* fix pinging

* fix bug where LED pins could not be set to zero (evaluates False)

* Hotfix - direct messaging between nodes & multihop messages (#99)

Addresses #93 - allows messages to be sent directly between net nodes with less fuss, as well as allows messages to be addressed with a list, see the appropriate tests and the discussion in the linked issue

In addition, fixed a number of things en passant

- added a few tests, including the testing framework to allow GUI tests to be run on the CI, and added tests to the docs experimentally
- send full continuous sound through queue rather than in frames, which was causing the continous sound to become truncated
- pop a dialogue if terminal is launched without any pilots prompting to add a pilot, addressing #27
- better identification of objects in log creation, looking first for an `id` field that will eventually be the uniform way of identifying objects
- split networking into its own module
- more type hinting
- continued work on removing ad-hoc logic, failing loudly instead of trying to do things implicitly
- added favicon to docs <3
- refactored docs into subfolders rather than long period-delimited filenames.
- bumped zmq and tornado dep versions

Squashed commits: 

* travis basics

* travis test 2

* travis test 3 - no enc setup scripts in

* travis test 4 - get the command right

* named test file right

* reversing test of event invoker

* jesuz

* drop all chunks at once

* debug flag

* handling emptiness and making logger from process

* fixing multihop messages... just the send part, now need to fix the 'handle listen' in  both the Station and the Net_Node
also some type hinting and docstring fixes and cleanup as we go

* refactoring networking to own module
refactoring docs to use folders instead of extremely long paths

* image links

* api links

* favicon

* somehow still missing networking docs

* favicon

* actually adding scripts

* draft of direct messaging between net_nodes

* networking docs

* clean up station object
- absolutely had no idea what class attributes were when i made this i guess
- fixing docstring
- type hinting
- spawning thread in the process by putting it in run rather than in init

* correct type hints

* maybe get scripts to render?

* node-to-node test

* multihop test
- station objects and node objects count how many messages they receive
- let station objects be instantiated programmatically
- fixing programmatic station release
- loggers check id first before name

* fixing prefs test defaults

* coverage of mp?

* coverage of mp?

* coverage of mp?

* coverage of mp?

* coverage of mp?

* coverage of mp?

* testing delay in sound trigger

* testing delay in sound trigger

* set agent
clear method for prefs

* the godforsaken managers module

* the godforsaken managers module

* the godforsaken managers module

* - terminal test
- get app from QApplication.instance() instead of implicitly
- close ioloop on release of net nodes
- 'float' type in setup
- don't save prefs if in tests
- bumping requirements to support some features we rely on

* asyncio debug mode

* do it except not in different build configs

* do it except not in different build configs

* close event?

* istg

* again istg

* again istg

* graspin at straws

* graspin at straws

* good heavens finally.

reverting exploratory attempts at fixes

* adding tests to the docs

* prompt to add pilots on blank screen init

* postmerge node fixes

* rough draft of parallax task

(and give ip property to nodes)

* change explicit type check to catchall text box that should just fail if malformed in, since will be coerced with ast.literal_eval anyway.

* specific pytest-qt

* imgconverter docs fix?

* imgconverter docs fix?

* fixing lots of things in the docs and hopefully pdf building

* seems to be a problem with blink...

* really?

* testing whether its the blink

* making links absolute

* see if absolute fixes

* Implement Registries, Plugins, and Wiki Integration (#109)

Very late now, but I believe i have done this: #39

I will return tomorrow to write the docs and the PR, but yes it is time.

dump anything that inherits from the appropriate metaclass into `PLUGINDIR` and...

import autopilot

# list all hardware
# or an alias

# get hardware (including from plugins)
autopilot.get('hardware', 'PWM')

# get anything

and as a little bonus...

>>> from autopilot.utils import wiki
>>> wiki.ask('[[HiFiBerry Amp2]]', "Uses GPIO Pin")
[{'Uses GPIO Pin': [3, 5, 7, 12, 35, 38, 40],
  'name': 'HiFiBerry Amp2',
  'url': ''}]

which will serve as the means of submitting plugins and doing some stuff that is truly messed up how cool it is... more soon ;)

* deduplicate utils

formerly had core/utils and a utils module, just have the module now.

* draft simpler registry :)

* moving common utility functions out of __init__

* task and hardware aliases

* proper sorting

* got excited and made a wiki API access module in this branch by accident whoops

* want to get one good build off!

* want to get one good build off!

* tests for registry module

* whoops reverting stuff that was broken at the time of adding it lmao jonny watch the results of the tests jesus christ

* basic test of a plugin

* implementing get throughout rest of library

removing imports and references to hardware and task objects, and finally killed the godforsaken Task List once and for all.
also adding other assorted improvements and bugfixes from the registries branch

* just for shits lets see if other versions work

* fix path traversal through modules whose base class is not in __init__

* proof of concept plugins manager ;)

* add xcb depends to scripts and docs to close #108

* fix: set_duration and Solenoid.duration are both in ms, no conversion from sec necessary (#63)

* Connect to multiple CHILDID (#103)

* station.l_child can now send START to multiple CHILDID

* update prefs to indicate that CHILDID can now be a list

* typo

* Stereo sound (#102)

From @cxrodgers 👍 

This is a PR for issue #94

This implements multi-channel (e.g., stereo) sound. 

Some major changes:
* The sound classes in autopilot.stim.sound accept a `channel` argument. (Right now, only Noise does this.) If this is `None` (the default), a mono (1-dimensional) sound is produced, exactly as before. If this is 0, a Noise burst only in the first channel is produced. If 1, a Noise burst only in the second channel is produced.
* Multi-channel sounds are properly padded to the correct chunk length in Jack_Sound.chunk (implemented here:
* The preference OUTCHANNELS is now interpreted differently. If empty string, then plays in mono mode (same sound to all speakers). If a list, connect channels to physical speakers in that order. If an int, treat as a list of length one. (implemented here:
* I removed padding code in the process() function because 1) this should already be done by Jack_Sound.chunk; 2) process probably doesn't have time to do this kind of thing; 3) the padding code was causing errors on multi-channel sounds, would need to be reimplemented as in Jack_Sound.chunk, but see reason number 1.
* OUTCHANNELS default in changes to empty string (mono mode, no changes to Task code needed). The old default of [1] suggested 1-based indexing and in any case produced essentially mono results.
* NCHANNELS deprecated in

Error are raised if:
* The length of OUTCHANNELS is longer than the number of available ports
* OUTCHANNELS indicates mono mode, but multi-channel audio is provided
* OUTCHANNELS is length N, but M-channel audio is provided, where N != M. However, 1-dimensional (mono) audio can be provided, and this will play to all N speakers.

jonny had suggested using None as the OUTCHANNELS flag for "connect no speakers", but [] works for this more naturally. Also, None cannot easily be put into the json.

Known issues:
* Presently only Noise can produce multi-channel output. Others can only produce mono output, as before. Should be an easy improvement.
* Only works for Jack, not pyo! 

Not tested!
* pyo is not tested!
* AUDIOSERVER = 'docs' is not tested!
* continuous mode is not tested!

Tested on:
* jackd from APT and (less thoroughly) jackd built from source

I know this is a big change, please lmk if changes are requested/needed!

* first pass at stereo

* doc; remove extra whitespace; reorganize order of imports

* doc Noise

* doc and reorganize the way Noise is generated

* fix typo

* intify channel if possible

* remove duplicate outports code

* typo

* handle stereo or mono output

* new way of init outports

* remove empty lines and comments

* doc

* move soudn writing code to its own method

* cherry pick a commit to init stereo_output, which required a merge on init_logger

* fix chunking and padding for multi-channel sound

* removing debug statements

* reimplement mono sound

* fix typo; error messages; use empty string instead of None as mono flag

* remove comment

* change default of OUTCHANNELS to empty string (mono)

* deprecate NCHANNELS

* adding

* catch ModuleNotFoundError

* server_type is not accessible via self

* trace out FS; finish test_init_noise

* put various durations into test function

* flesh out mono and stereo tests

* comments

* change calling functions to pytest parameterizations

* deprecation for prefs

* replace SOUND_LIST with autopilot.get, make placeholder Stim metaclass to make it work when audio server is undefined

* fix registry with plugin present

* warn if jackd server sampling rate doesn't match prefs

Co-authored-by: sneakers-the-rat <>

* add .bib for docs

* moving numpy encoder and decoder to new utils location

* move parallax to plugin repo:

* [skip travis] cleaning up some more code and docs from parallax

* [skip travis] cleaning up dead files

* Programmatic setup!

* cleaned up the setup_autopilot routine a lot. split everything into separate functions so at least the behavior is *somewhat* encapsulated. they're still very messy and this needs some real reconsideration because it's pretty fragile, but hey at least now it can be called as something other than a module from __main__
* Programmatic setup with custom prefs (specified individually as -p PREFNAME=VALUE -p PREF2=VAL2 and -f prefs.json) and scripts.
* allowed passing multiple scripts and prefs
* still need to write tests

* actually propagate custom directory passed with -d/--dir

basically need to make sure the rest of the directory structure underneath it follows the basic one. implemented by just making the prefs dictionary explicitly and adding it into the prefs that are passed to the setup form (rather than trying to make some auto-re-computing thing)

* whoa i cant believe i actually just relied on a global variable.

* [skip travis] v0.4.0 changelog

* [skip travis] credits in changelog and some formatting

* [skip travis] grats

* maybe try actually knowing css

* [skip travis] getting started refreshing docs

* raise valueerror when instantiating LED_RGB with malformed `pins` or when `pin` is given

* [skip travis] - quickstart checkpoint

* [skip travis] - quickstart checkpoint

* [skip travis] - quickstart checkpoint

* quickstart

- state property for GPIO
- some more params for Transformer to let it be used with the new mode of networking

* [skip travis] fix chris' name

* [skip travis] clearing up a lot of erroneous documentation about hardware class creation

* [skip travis] trying to include raw blink

* making textual blink

* [skip travis] checking nbsp

* [skip travis] checking nbsp

* [skip travis] last bits for the night

* [skip travis] last bits for the night

* [skip travis] committing before battery runs out!

* [skip travis] committing before battery runs out!

* [skip travis] plugins docs!

* removing wehrlab specific stuff
- changing Nafc class references to use registries

* add tests

* bump version to v0.4.0!!!!

and update what's new ;)

Co-authored-by: Mike Wehr <>
Co-authored-by: Chris Rodgers <>
Co-authored-by: sneakers-the-rat <>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
None yet

Successfully merging this pull request may close these issues.

None yet

1 participant