Neo 0.5.0 release notes

22nd March 2017

For Neo 0.5, we have taken the opportunity to simplify the Neo object model.

Although this will require an initial time investment for anyone who has written code with an earlier version of Neo, the benefits will be greater simplicity, both in your own code and within the Neo code base, which should allow us to move more quickly in fixing bugs, improving performance and adding new features.

More detail on these changes follows:

Merging of “single-value” and “array” versions of data classes

In previous versions of Neo, we had AnalogSignal for one-dimensional (single channel) signals, and AnalogSignalArray for two-dimensional (multi-channel) signals. In Neo 0.5.0, these have been merged under the name AnalogSignal. AnalogSignal has the same behaviour as the old AnalogSignalArray.

It is still possible to create an AnalogSignal from a one-dimensional array, but this will be converted to an array with shape (n, 1), e.g.:

>>> signal = neo.AnalogSignal([0.0, 0.1, 0.2, 0.5, 0.6, 0.5, 0.4, 0.3, 0.0],
...                           sampling_rate=10*kHz,
...                           units=nA)
>>> signal.shape
(9, 1)

Multi-channel arrays are created as before, but using AnalogSignal instead of AnalogSignalArray:

>>> signal = neo.AnalogSignal([[0.0, 0.1, 0.2, 0.5, 0.6, 0.5, 0.4, 0.3, 0.0],
...                            [0.0, 0.2, 0.4, 0.7, 0.9, 0.8, 0.7, 0.6, 0.3]],
...                           sampling_rate=10*kHz,
...                           units=nA)
>>> signal.shape
(9, 2)

Similarly, the Epoch and EpochArray classes have been merged into an array-valued class Epoch, ditto for Event and EventArray, and the Spike class, whose main function was to contain the waveform data for an individual spike, has been suppressed; waveform data are now available as the waveforms attribute of the SpikeTrain class.

Recording channels

As a consequence of the removal of “single-value” data classes, information on recording channels and the relationship between analog signals and spike trains is also stored differently.

In Neo 0.5, we have introduced a new class, ChannelIndex, which replaces both RecordingChannel and RecordingChannelGroup.

In older versions of Neo, a RecordingChannel object held metadata about a logical recording channel (a name and/or integer index) together with references to one or more AnalogSignals recorded on that channel at different points in time (different Segments); redundantly, the AnalogSignal also had a channel_index attribute, which could be used in addition to or instead of creating a RecordingChannel.

Metadata about AnalogSignalArrays could be contained in a RecordingChannelGroup in a similar way, i.e. RecordingChannelGroup functioned as an array-valued version of RecordingChannel, but RecordingChannelGroup could also be used to group together individual RecordingChannel objects.

With Neo 0.5, information about the channel names and ids of an AnalogSignal is contained in a ChannelIndex, e.g.:

>>> signal = neo.AnalogSignal([[0.0, 0.1, 0.2, 0.5, 0.6, 0.5, 0.4, 0.3, 0.0],
...                            [0.0, 0.2, 0.4, 0.7, 0.9, 0.8, 0.7, 0.6, 0.3]],
...                            [0.0, 0.1, 0.3, 0.6, 0.8, 0.7, 0.6, 0.5, 0.3]],
...                           sampling_rate=10*kHz,
...                           units=nA)
>>> channels = neo.ChannelIndex(index=[0, 1, 2],
...                             channel_names=["chan1", "chan2", "chan3"])
>>> signal.channel_index = channels

In this use, it replaces RecordingChannel.

ChannelIndex may also be used to group together a subset of the channels of a multi-channel signal, for example:

>>> channel_group = neo.ChannelIndex(index=[0, 2])
>>> channel_group.analogsignals.append(signal)
>>> unit = neo.Unit()  # will contain the spike train recorded from channels 0 and 2.
>>> unit.channel_index = channel_group

Checklist for updating code from 0.3/0.4 to 0.5

To update your code from Neo 0.3/0.4 to 0.5, run through the following checklist:

  1. Change all usages of AnalogSignalArray to AnalogSignal.
  2. Change all usages of EpochArray to Epoch.
  3. Change all usages of EventArray to Event.
  4. Where you have a list of (single channel) AnalogSignals all of the same length, consider converting them to a single, multi-channel AnalogSignal.
  5. Replace RecordingChannel and RecordingChannelGroup with ChannelIndex.

Note

in points 1-3, the data structure is still an array, it just has a shorter name.

Other changes

  • added NixIO (about the NIX format)
  • added IgorIO
  • added NestIO (for data files produced by the NEST simulator)
  • NeoHdf5IO is now read-only. It will read data files produced by earlier versions of Neo, but another HDF5-based IO, e.g. NixIO, should be used for writing data.
  • many fixes/improvements to existing IO modules. All IO modules should now work with Python 3.