Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
include README.rst
include CITATION.rst
prune drafts
include examples/*.py
recursive-include doc *
Expand Down
27 changes: 22 additions & 5 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,30 @@
Neo
===

Neo is a package for representing electrophysiology data in Python, together
Neo is a Python package for working with electrophysiology data in Python, together
with support for reading a wide range of neurophysiology file formats, including
Spike2, NeuroExplorer, AlphaOmega, Axon, Blackrock, Plexon, Tdt, and support for
writing to a subset of these formats plus non-proprietary formats including HDF5.

The goal of Neo is to improve interoperability between Python tools for
analyzing, visualizing and generating electrophysiology data (such as
OpenElectrophy, NeuroTools, G-node, Helmholtz, PyNN) by providing a common,
analyzing, visualizing and generating electrophysiology data by providing a common,
shared object model. In order to be as lightweight a dependency as possible,
Neo is deliberately limited to represention of data, with no functions for data
analysis or visualization.

Neo is used by a number of other software tools, including OpenElectrophy_
and SpykeViewer_ (data analysis and visualization), Elephant_ (data analysis),
the G-node_ suite (databasing) and PyNN_ (simulations).

Neo implements a hierarchical data model well adapted to intracellular and
extracellular electrophysiology and EEG data with support for multi-electrodes
(for example tetrodes). Neo's data objects build on the quantities_ package,
which in turn builds on NumPy by adding support for physical dimensions. Thus
neo objects behave just like normal NumPy arrays, but with additional metadata,
Neo objects behave just like normal NumPy arrays, but with additional metadata,
checks for dimensional consistency and automatic unit conversion.

A project with similar aims but for neuroimaging file formats is `NiBabel`_.

Code status
-----------

Expand All @@ -44,5 +49,17 @@ More information

For installation instructions, see doc/source/install.rst

:copyright: Copyright 2010-2014 by the Neo team, see AUTHORS.
:copyright: Copyright 2010-2014 by the Neo team, see doc/source/authors.rst
:license: 3-Clause Revised BSD License, see LICENSE.txt for details.


.. _OpenElectrophy: https://github.com/OpenElectrophy/OpenElectrophy
.. _Elephant: http://neuralensemble.org/elephant
.. _G-node: http://www.g-node.org/
.. _Neuroshare: http://neuroshare.org/
.. _SpykeViewer: https://spyke-viewer.readthedocs.org/en/latest/
.. _NiBabel: http://nipy.sourceforge.net/nibabel/
.. _PyNN: http://neuralensemble.org/PyNN
.. _quantities: http://pypi.python.org/pypi/quantities
.. _`NeuralEnsemble mailing list`: http://groups.google.com/group/neuralensemble
.. _`issue tracker`: https://github.c
108 changes: 54 additions & 54 deletions doc/source/core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,44 @@
Neo core
********

.. currentmodule:: neo
.. currentmodule:: neo.core

Introduction
============
This figure shows the main data types in Neo:

Objects in Neo represent neural data and collections of data. Neo objects fall
into three categories: data objects, container objects and grouping objects.
.. image:: images/base_schematic.png
:height: 500 px
:alt: Illustration of the main Neo data types
:align: center

Neo objects fall into three categories: data objects, container objects and grouping objects.

Data objects
------------

These objects directly represent data as arrays of numerical values with
associated metadata (units, sampling frequency, etc.).

:py:class:`AnalogSignalArray`:
A regular sampling of a single- or multi-channel continuous analog signal.
* :py:class:`AnalogSignal`: A regular sampling of a single- or multi-channel continuous analog signal.
* :py:class:`IrregularlySampledSignal`: A non-regular sampling of a single- or multi-channel continuous analog signal.
* :py:class:`SpikeTrain`: A set of action potentials (spikes) emitted by the same unit in a period of time (with optional waveforms).
* :py:class:`Event`: An array of time points representing one or more events in the data.
* :py:class:`Epoch`: An array of time intervals representing one or more periods of time in the data.

:py:class:`SpikeTrain`:
A set of action potentials (spikes) emitted by the same unit in a period of time (with optional waveforms).

:py:class:`Event`:
An array of time points representing one or more events in the data.

:py:class:`Epoch`:
An array of time intervals representing one or more periods of time in the data.

Container objects
-----------------

There is a simple hierarchy of containers:

:py:class:`Segment`:
A container for heterogeneous discrete or continous data sharing a common clock (time basis) but not necessarily the same sampling rate, start time or end time. A :py:class:`Segment` can be considered as equivalent to a "trial", "episode", "run", "recording", etc., depending on the experimental context. May contain any of the data objects.
* :py:class:`Segment`: A container for heterogeneous discrete or continous data sharing a common
clock (time basis) but not necessarily the same sampling rate, start time or end time.
A :py:class:`Segment` can be considered as equivalent to a "trial", "episode", "run",
"recording", etc., depending on the experimental context.
May contain any of the data objects.
* :py:class:`Block`: The top-level container gathering all of the data, discrete and continuous,
for a given recording session.
Contains :class:`Segment`, :class:`Unit` and :class:`ChannelIndex` objects.

:py:class:`Block`:
The top-level container gathering all of the data, discrete and continuous, for a given recording session. Contains :class:`Segment`, :class:`Unit` and :class:`RecordingChannelGroup` objects.

Grouping objects
----------------
Expand All @@ -47,25 +49,29 @@ were recorded on which electrodes, which spike trains were obtained from which
membrane potential signals, etc. They contain references to data objects that
cut across the simple container hierarchy.

* :py:class:`ChannelIndex`: A set of indices into :py:class:`AnalogSignal` objects,
representing logical and/or physical recording channels. This has two uses:

:py:class:`RecordingChannelGroup`:
A set of indices into :py:class:`AnalogSignal` objects, representing logical and/or
physical recording channels. This has several uses:
* for linking :py:class:`AnalogSignal` objects recorded from the same (multi)electrode
across several :py:class:`Segment` objects.
* for spike sorting of extracellular signals, where spikes may be recorded on more than one
recording channel, and the :py:class:`RecordingChannelGroup` can be used to associate each
:py:class:`Unit` with the group of recording channels from which it was calculated.
1. for linking :py:class:`AnalogSignal` objects recorded from the same (multi)electrode
across several :py:class:`Segment`\s.
2. for spike sorting of extracellular signals, where spikes may be recorded on more than one
recording channel, and the :py:class:`ChannelIndex` can be used to associate each
:py:class:`Unit` with the group of recording channels from which it was obtained.

:py:class:`Unit`:
A Unit gathers all the :class:`SpikeTrain` objects within a common :class:`Block`, possibly
across several Segments, that have been emitted by the same cell.
A :class:`Unit` is linked to the :class:`RecordingChannelGroup` object from which it was detected.
* :py:class:`Unit`: A Unit links the :class:`SpikeTrain` objects within a :class:`Block`,
possibly across multiple Segments, that were emitted by the same cell.
A :class:`Unit` is linked to the :class:`ChannelIndex` object from which the spikes were detected.

.. image:: images/base_schematic.png
:height: 500 px
:alt: Neo : Neurotools/OpenElectrophy shared base architecture
:align: center

NumPy compatibility
===================

Neo data objects inherit from :py:class:`Quantity`, which in turn inherits from NumPy
:py:class:`ndarray`. This means that a Neo :py:class:`AnalogSignal` is also a :py:class:`Quantity`
and an array, giving you access to all of the methods available for those objects.

For example, you can pass a :py:class:`SpikeTrain` directly to the :py:func:`numpy.histogram`
function, or an :py:class:`AnalogSignal` directly to the :py:func:`numpy.std` function.


Relationships between objects
Expand All @@ -91,14 +97,14 @@ In general, an object can access its children with an attribute *childname+s* in
* :attr:`Block.segments`
* :attr:`Segments.analogsignals`
* :attr:`Segments.spiketrains`
* :attr:`Block.recordingchannelgroups`
* :attr:`Block.channel_indexes`

These relationships are bi-directional, i.e. a child object can access its parent:

* :attr:`Segment.block`
* :attr:`AnalogSignal.segment`
* :attr:`SpikeTrains.segment`
* :attr:`RecordingChannelGroup.block`
* :attr:`SpikeTrain.segment`
* :attr:`ChannelIndex.block`

Here is an example showing these relationships in use::

Expand All @@ -119,14 +125,14 @@ Here is an example showing these relationships in use::

In some cases, a one-to-many relationship is sufficient. Here is a simple example with tetrodes, in which each tetrode has its own group.::

from neo import Block, RecordingChannelGroup
from neo import Block, ChannelIndex
bl = Block()

# the four tetrodes
for i in range(4):
rcg = RecordingChannelGroup(name = 'Tetrode %d' % i,
chx = ChannelIndex(name = 'Tetrode %d' % i,
channel_indexes=[0, 1, 2, 3])
bl.recordingchannelgroups.append(rcg)
bl.channelindexes.append(chx)

# now we load the data and associate it with the created channels
# ...
Expand All @@ -136,19 +142,19 @@ Now consider a more complex example: a 1x4 silicon probe, with a neuron on chann
bl = Block(name='probe data')

# one group for each neuron
rcg0 = RecordingChannelGroup(name='Group 0',
chx0 = ChannelIndex(name='Group 0',
channel_indexes=[0, 1, 2])
bl.recordingchannelgroups.append(rcg0)
bl.channelindexes.append(chx0)

rcg1 = RecordingChannelGroup(name='Group 1',
chx1 = ChannelIndex(name='Group 1',
channel_indexes=[1, 2, 3])
bl.recordingchannelgroups.append(rcg1)
bl.channelindexes.append(chx1)

# now we add the spiketrain from Unit 0 to rcg0
# and add the spiketrain from Unit 1 to rcg1
# now we add the spiketrain from Unit 0 to chx0
# and add the spiketrain from Unit 1 to chx1
# ...

Note that because neurons are sorted from groups of channels in this situation, it is natural that the :py:class:`RecordingChannelGroup` contains a reference to the :py:class:`Unit` object.
Note that because neurons are sorted from groups of channels in this situation, it is natural that the :py:class:`ChannelIndex` contains a reference to the :py:class:`Unit` object.
That unit then contains references to its spiketrains. Also note that recording channels can be
identified by names/labels as well as, or instead of, integer indices.

Expand Down Expand Up @@ -180,13 +186,7 @@ For more details, see the :doc:`api_reference`.



Inheritance
===========

Some Neo objects (:py:class:`AnalogSignal`, :py:class:`SpikeTrain`) inherit from :py:class:`Quantity`,
which in turn inherits from NumPy :py:class:`ndarray`. This means that a Neo :py:class:`AnalogSignal` actually is also a :py:class:`Quantity` and an array, giving you access to all of the methods available for those objects.

For example, you can pass a :py:class:`SpikeTrain` directly to the :py:func:`numpy.histogram` function, or an :py:class:`AnalogSignal` directly to the :py:func:`numpy.std` function.


Initialization
Expand Down
2 changes: 1 addition & 1 deletion doc/source/developers_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ However, the pep8 and flake8 programs does not check for all PEP 8 issues.
In particular, they does not check that the import statements are in the
correct order.

Also, please do not use "from __ import *". This is slow, can lead to
Also, please do not use ``from __ import *``. This is slow, can lead to
conflicts, and makes it difficult for code analysis software.


Expand Down
Binary file modified doc/source/images/base_schematic.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion doc/source/images/base_schematic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion doc/source/images/generate_diagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ def generate_diagram_simple():
'Event': (.5+rw*bf*4, 4),
'Epoch': (.5+rw*bf*4, .2),

'RecordingChannelGroup': (.5+rw*bf*.8, 8.5),
'ChannelIndex': (.5+rw*bf*.8, 8.5),

'Unit': (.5+rw*bf*2., 9.5),

Expand Down
Binary file modified doc/source/images/multi_segment_diagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading