Reading and analyzing data with Neo#

Getting started#

Neo is a library for working with neurophysiology data in the Python programming language. One of the big advantages of Neo is that it works with many different file formats: it doesn’t matter which format your data is stored in, Neo provides a standard way to read the data, and then represents it in a standardised way, as a set of Python objects.

The first step in reading data is to import the appropriate Neo input-output (or IO) module for your data. For this example, we’re going to work with membrane potential traces stored in a text file, so we use the AsciiSignalIO module:

In [1]: from neo.io import AsciiSignalIO

In [2]: data = AsciiSignalIO("example_data.txt", delimiter=" ").read()

Note

For a full list of IO modules provided by Neo, see List of implemented IO modules.

In [3]: data
Out[3]: 
[Block with [<neo.core.segment.Segment object at 0x7feadff836d0>] segments
 file_origin: 'example_data.txt'
 # segments (N=[<neo.core.segment.Segment object at 0x7feadff836d0>])
 0: Segment with [<AnalogSignal(array([[-58.469, -52.855, -58.79 , -58.815],
       [-59.061, -50.518, -52.003, -57.24 ],
       [-59.01 , -50.51 , -51.988, -57.199],
       ...,
       [-56.535, -56.653, -56.374, -53.659],
       [-56.501, -56.62 , -56.42 , -53.64 ],
       [-56.468, -56.586, -56.464, -53.621]], dtype=float32) * mV, [0.0 s, 10.001 s], sampling rate: 1.0 kHz)>] analogsignals
    # analogsignals (N=[<AnalogSignal(array([[-58.469, -52.855, -58.79 , -58.815],
       [-59.061, -50.518, -52.003, -57.24 ],
       [-59.01 , -50.51 , -51.988, -57.199],
       ...,
       [-56.535, -56.653, -56.374, -53.659],
       [-56.501, -56.62 , -56.42 , -53.64 ],
       [-56.468, -56.586, -56.464, -53.621]], dtype=float32) * mV, [0.0 s, 10.001 s], sampling rate: 1.0 kHz)>])
    0: AnalogSignal with 4 channels of length 10001; units mV; datatype float32
       name: 'multichannel'
       sampling rate: 1.0 kHz
       time: 0.0 s to 10.001 s]

Different data files can contain different amounts of data, from single traces to multiple recording sessions. To provide consistent behaviour, for all IO modules, the read() method returns a list of data blocks. A Block typically represents a recording session. Each block contains a list of segments, where each Segment contains data recorded at the same time.

In this example file, we see a single type of data, the “analog signal”, which represents continuous time series sampled at a fixed interval. The other types of data that can be contained in a Segment are discussed below under Data types.

Note

read() reads the entire file into memory at once. If you only want to access part of the data, you can do so using Neo’s “lazy” data loading - see the section on Performance and memory consumption below.

Neo data objects are based on NumPy arrays, and behave very similarly. For example, they can be plotted just like arrays:

In [4]: import matplotlib.pyplot as plt

In [5]: signal = data[0].segments[0].analogsignals[0]

In [6]: plt.plot(signal.times, signal)
Out[6]: 
[<matplotlib.lines.Line2D at 0x7feadda4e610>,
 <matplotlib.lines.Line2D at 0x7feadda5e350>,
 <matplotlib.lines.Line2D at 0x7feadda5e850>,
 <matplotlib.lines.Line2D at 0x7feadda5ed50>]

In [7]: plt.xlabel(f"Time ({signal.times.units.dimensionality.string})")
Out[7]: Text(0.5, 0, 'Time (s)')

In [8]: plt.ylabel(f"Membrane potential ({signal.units.dimensionality.string})")
Out[8]: Text(0, 0.5, 'Membrane potential (mV)')

In [9]: plt.savefig("example_plot.png")
_images/example_plot.png

You now know enough to start using Neo. For more examples, see Examples. If you want to know more, read on.

NumPy#

Neo is based on NumPy. All Neo data classes behave like NumPy arrays, but have extra functionality.

The first addition is support for units. In contrast to a plain NumPy array, an AnalogSignal knows the units of the data it contains, e.g.:

In [10]: signal.units
Out[10]: array(1.) * mV

This helps avoid errors like adding signals with different units, lets you auto-generate figure axis labels, and makes it easy to change units, like here from millivolts to volts e.g.:

In [11]: signal.magnitude[:5]
Out[11]: 
array([[-58.469, -52.855, -58.79 , -58.815],
       [-59.061, -50.518, -52.003, -57.24 ],
       [-59.01 , -50.51 , -51.988, -57.199],
       [-58.96 , -50.503, -51.973, -57.158],
       [-58.911, -50.495, -51.958, -57.117]], dtype=float32)

In [12]: signal.rescale("V").magnitude[:5]
Out[12]: 
array([[-0.058469  , -0.052855  , -0.05879   , -0.058815  ],
       [-0.059061  , -0.050518  , -0.052003  , -0.05724001],
       [-0.05901   , -0.05051   , -0.051988  , -0.05719901],
       [-0.05896   , -0.050503  , -0.051973  , -0.057158  ],
       [-0.058911  , -0.050495  , -0.051958  , -0.057117  ]],
      dtype=float32)

The second addition is support for structured metadata. Some of these metadata are required. For example, an AnalogSignal must always have a sampling_rate attribute, and Neo will produce an Exception if you try to add two signals with different sampling rates:

In [13]: signal.sampling_rate
Out[13]: array(1.) * kHz

Some of these metadata are recommended but optional, like a name for each signal. Such metadata appear as attributes of the data objects:

In [14]: signal.name
Out[14]: 'multichannel'

And finally, some metadata are fully optional. These are stored in the annotations and array_annotations attributes:

In [15]: signal.array_annotations
Out[15]: {'channel_index': array([0, 1, 2, 3])}

For more information about this, see Annotations.

Most NumPy array methods also work on Neo data objects, e.g.:

In [16]: signal.mean()
Out[16]: array(-56.33598, dtype=float32) * mV

Data objects can be sliced like arrays (array annotations are automatically sliced appropriately):

In [17]: signal[100:110, 1:3]
Out[17]: 
AnalogSignal with 2 channels of length 10; units mV; datatype float32
name: 'multichannel'
sampling rate: 1.0 kHz
time: 0.1 s to 0.11 s

In [18]: signal[100:110, 1:3].array_annotations
Out[18]: {'channel_index': array([1, 2])}

To convert a Neo data object to a plain NumPy array, use the magnitude attribute:

In [19]: signal[100:110, 1:3].magnitude
Out[19]: 
array([[-60.654, -60.   ],
       [-60.724, -60.   ],
       [-60.792, -60.   ],
       [-60.859, -60.   ],
       [-60.924, -60.   ],
       [-60.989, -60.   ],
       [-61.052, -60.   ],
       [-61.114, -60.   ],
       [-61.175, -60.   ],
       [-61.234, -60.   ]], dtype=float32)

Data types#

The following classes directly represent data as arrays of numerical values with associated metadata (units, sampling frequency, etc.).

  • AnalogSignal: A regular sampling of a single- or multi-channel continuous analog signal.

  • IrregularlySampledSignal: A non-regular sampling of a single- or multi-channel continuous analog signal.

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

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

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

  • ImageSequence: A three dimensional array representing a sequence of images.

AnalogSignal#

We have already met the AnalogSignal, which represents continuous time series sampled at a fixed interval.

In addition to reading data from a file, as above, it is also possible to create new signal objects directly, e.g.:

In [20]: import numpy as np

In [21]: from quantities import mV, kHz

In [22]: from neo import AnalogSignal

In [23]: signal = AnalogSignal(np.random.normal(-65.0, 5.0, size=(100, 5)),
   ....:                       units=mV, sampling_rate=1 * kHz)
   ....: 

In [24]: signal
Out[24]: 
AnalogSignal with 5 channels of length 100; units mV; datatype float64
sampling rate: 1.0 kHz
time: 0.0 s to 0.1 s

IrregularlySampledSignal#

IrregularlySampledSignal represents continuous time series sampled at non-regular time points. This means that instead of specifying the sampling rate or sampling interval, you must specify the array of times at which the signal was sampled.

In [25]: from quantities import ms, nA

In [26]: from neo import IrregularlySampledSignal

In [27]: isignal = IrregularlySampledSignal(
   ....:              times=[0.0, 1.11, 4.27, 16.38, 19.33] * ms,
   ....:              signal=[0.5, 0.8, 0.5, 0.7, 0.2] * nA,
   ....:              description="input current")
   ....: 

In [28]: isignal
Out[28]: 
IrregularlySampledSignal with 1 channels of length 5; units nA; datatype float64
description: 'input current'
sample times: [ 0.    1.11  4.27 16.38 19.33] ms

Note

in case of multi-channel data, samples are assumed to have been taken at the same time points in all channels. If you need to specify different time points for different channels, use one signal object per channel.

SpikeTrain#

A SpikeTrain represents the times of occurrence of action potentials (spikes).

In [29]: from neo import SpikeTrain

In [30]: spike_train = SpikeTrain([3, 4, 5], units='sec', t_stop=10.0)

In [31]: spike_train
Out[31]: 
SpikeTrain containing 3 spikes; units s; datatype float64 
time: 0.0 s to 10.0 s

It may also contain the waveforms of the action potentials, stored as AnalogSignals within the spike train object - see the reference documentation for more on this.

Event#

It is common in electrophysiology experiments to record the times of specific events, such as the times at which stimuli are presented. An Event contains an array of times at which events occurred, together with an optional array of labels for the events, e.g.:

In [32]: from neo import Event

In [33]: events = Event(np.array([5, 15, 25]), units="second",
   ....:                labels=["apple", "rock", "elephant"],
   ....:                name="stimulus onset")
   ....: 

In [34]: events
Out[34]: 
Event containing 3 events with labels; time units s; datatype int64 
name: 'stimulus onset'

Epoch#

A variation of events is where something occurs over a certain period of time, in which case we need to know both the start time and the duration. An Epoch contains an array of start or onset times together with an array of durations (or a single value if all epochs have the same duration), and an optional array of labels.

In [35]: from neo import Epoch

In [36]: epochs = Epoch(times=np.array([5, 15, 25]),
   ....:                durations=2.0,
   ....:                units="second",
   ....:                labels=["apple", "rock", "elephant"],
   ....:                name="stimulus presentations")
   ....: 

In [37]: epochs
Out[37]: 
Epoch containing 3 epochs with labels; time units s; datatype int64 
name: 'stimulus presentations'

ImageSequence#

In addition to electrophysiology, neurophysiology signals may be obtained through functional microscopy. The ImageSequence class represents a sequence of images, as a 3D array organized as [frame][row][column]. It behaves similarly to AnalogSignal, but in 3D rather than 2D.

In [38]: from quantities import Hz, micrometer

In [39]: from neo import ImageSequence

In [40]: img_sequence_array = [[[column for column in range(20)]for row in range(20)]
   ....:                       for frame in range(10)]
   ....: 

In [41]: image_sequence = ImageSequence(img_sequence_array, units='dimensionless',
   ....:                                sampling_rate=1 * Hz,
   ....:                                spatial_scale=1 * micrometer)
   ....: 

In [42]: image_sequence
Out[42]: 
ImageSequence 10 frames with width 20 px and height 20 px; units dimensionless; datatype int64 
sampling rate: 1.0 Hz
spatial_scale: 1.0 um

Annotations#

Neo objects have certain required metadata, such as the sampling_rate for AnalogSignals. There are also certain recommended metadata, such as a name and description. For any metadata not covered by the required or recommended fields, additional annotations can be added, e.g.:

In [43]: from quantities import um as µm

In [44]: signal.annotate(pipette_tip_diameter=1.5 * µm)

In [45]: signal.annotations
Out[45]: {'pipette_tip_diameter': array(1.5) * um}

For those IO modules that support writing data to file, annotations will also be written, provided they can be serialized to JSON format.

Array annotations#

Since certain Neo objects contain array data, it is sometimes necessary to annotate individual array elements, or individual columns.

For 1D arrays, the array annotations should have the same length as the array, e.g.

In [46]: events.shape
Out[46]: (3,)

In [47]: events.array_annotate(secondary_labels=["red", "green", "blue"])

For 2D arrays, the array annotations should match the shape of the channel dimension, e.g.

In [48]: signal.shape
Out[48]: (100, 5)

In [49]: signal.array_annotate(quality=["good", "good", "noisy", "good", "noisy"])

Dataset structure#

The overall structure of a Neo dataset is shown in this figure:

Illustration of the main Neo data types

Beyond the core data classes, Neo has various classes for grouping and structuring different data objects. We have already met two of them, the Block and Segment.

Tree structure#

Block and Segment provide a basic two-level hierarchical structure: Blocks contain Segments, which contain data objects.

Segments are used to group data that have a common time basis, i.e. that were recorded at the same time. A Segment can be considered as equivalent to a “trial”, “episode”, “run”, “recording”, etc., depending on the experimental context.

Segments have the following attributes, used to access lists of data objects:

  • analogsignals

  • epochs

  • events

  • imagesequences

  • irregularlysampledsignals

  • spiketrains

Block is the top-level container gathering all of the data, discrete and continuous, for a given recording session. It contains Segment and Group (see next section) objects in the attributes segments and groups.

Grouping and linking objects#

Sometimes your data have a structure that goes beyond a simple two-level hierarchy. For example, suppose that you wish to group together signals that were recorded from the same tetrode in multi-tetrode recording setup.

For this, Neo provides a Group class:

In [50]: from neo import Group

In [51]: signal1 = AnalogSignal(np.random.normal(-65.0, 5.0, size=(100, 5)), units=mV, sampling_rate=1 * kHz)

In [52]: signal2 = AnalogSignal(np.random.normal(-65.0, 5.0, size=(1000, 5)), units=nA, sampling_rate=10 * kHz)

In [53]: group = Group(objects=(signal1, signal2))

In [54]: group
Out[54]: 
Group with [<AnalogSignal(array([[-64.66170296, -61.14037816, -69.33659855, -64.22820973,
        -64.95736688],
       [-71.99078066, -64.31960999, -67.01256252, -64.5856492 ,
        -59.87906462],
       [-73.60813204, -68.33397994, -70.43419932, -64.47483041,
        -59.65210434],
       [-58.93063423, -65.31073563, -69.15736453, -59.45444548,
        -55.66774708],
       [-68.17469147, -57.08360988, -71.42801557, -61.06251082,
        -59.8328112 ],
       [-68.19306052, -57.47677208, -64.63434258, -65.9303949 ,
        -55.02502406],
       [-61.70890347, -62.51390524, -73.59655529, -66.25836535,
        -58.78414102],
       [-69.22097898, -62.637702  , -76.71135135, -57.40285989,
        -74.09641512],
       [-62.87333876, -62.87390249, -64.46690311, -69.05174633,
        -62.76876609],
       [-70.44659289, -62.54497852, -57.71394454, -72.64303244,
        -69.25382567],
       [-67.51588423, -67.20857477, -67.7549537 , -65.1151516 ,
        -68.43911171],
       [-64.46353623, -61.90728687, -67.61008877, -64.28710475,
        -58.45947579],
       [-62.78203342, -63.0038793 , -69.77356708, -66.78595051,
        -61.68792258],
       [-65.32474043, -68.3627173 , -62.98956218, -66.28832878,
        -66.08917637],
       [-66.11727041, -62.96897764, -66.6273795 , -63.99428694,
        -60.19649112],
       [-61.14874734, -61.01118006, -55.30654157, -70.25337525,
        -72.38573465],
       [-71.17207978, -68.33821354, -66.80814009, -61.77288273,
        -66.59236287],
       [-66.21835749, -63.97582583, -62.58585594, -66.87208907,
        -63.12504303],
       [-68.0462542 , -62.22191842, -69.83147227, -59.95384454,
        -60.03021218],
       [-66.37714207, -62.3916283 , -69.74402682, -61.80957099,
        -67.18224408],
       [-60.91371081, -59.95634326, -61.41838696, -67.00947582,
        -71.68968529],
       [-71.30475249, -63.53882244, -58.71825329, -73.00485867,
        -67.15262265],
       [-54.1903088 , -60.820349  , -65.01694708, -62.26390946,
        -69.17219594],
       [-61.22875794, -66.12642347, -68.54202565, -71.49129693,
        -70.15789221],
       [-59.853252  , -72.31591729, -60.57008543, -52.75291857,
        -62.52022302],
       [-61.45709157, -61.23954664, -63.03748449, -62.15018942,
        -66.21386537],
       [-62.41853077, -65.40547146, -59.84325301, -70.05189574,
        -80.54127201],
       [-62.13849313, -57.88506492, -60.34821279, -73.64050434,
        -72.36802663],
       [-69.97159017, -55.31315781, -76.93408818, -64.87258398,
        -69.28841518],
       [-57.51343102, -65.21376034, -64.65101398, -66.346736  ,
        -65.62136373],
       [-62.44271612, -63.73454766, -56.78778334, -57.91641188,
        -69.28170579],
       [-65.34169932, -68.87410208, -69.80315735, -64.09961907,
        -67.39400987],
       [-60.1573748 , -68.85981345, -68.02917042, -66.01618555,
        -65.94620154],
       [-67.07276605, -71.27460244, -65.73055346, -68.7134081 ,
        -69.47137499],
       [-67.97728812, -61.78559066, -62.85620256, -61.55781044,
        -71.68630421],
       [-59.9884215 , -69.15254304, -57.72884838, -61.0686057 ,
        -72.79545377],
       [-60.8752039 , -64.08387988, -58.84755218, -67.92799905,
        -58.0657095 ],
       [-67.1855648 , -68.71731628, -60.48422989, -66.9495976 ,
        -64.542556  ],
       [-65.74573298, -57.6977495 , -67.32503195, -60.23777811,
        -62.36280272],
       [-65.99693698, -66.14578775, -68.21728735, -68.63638045,
        -52.53105211],
       [-61.74833287, -58.87015812, -58.94449789, -66.66932541,
        -64.13371627],
       [-65.50370887, -64.82898142, -68.08455563, -65.09742043,
        -69.21434534],
       [-67.70973457, -58.95357264, -70.70478055, -62.3284687 ,
        -60.5472699 ],
       [-65.32130983, -66.02998062, -71.14680552, -63.80078688,
        -60.11442446],
       [-64.41994379, -65.55275513, -58.18700749, -57.87343523,
        -59.04097822],
       [-63.79048702, -67.10341538, -66.08302702, -60.46511195,
        -66.42019235],
       [-63.72799272, -67.31441262, -56.5367071 , -65.9148877 ,
        -64.73146364],
       [-66.1500155 , -65.95530038, -68.8291285 , -57.76277863,
        -66.5399908 ],
       [-69.86185697, -74.3204716 , -67.97201277, -70.62244654,
        -65.41811209],
       [-60.41925606, -65.57920817, -51.86927124, -58.72409031,
        -63.86141351],
       [-67.02991826, -63.73545406, -64.11602445, -71.58774879,
        -63.94523344],
       [-60.14290408, -71.01481059, -63.02223057, -66.25753485,
        -64.79108276],
       [-66.18622808, -65.30317875, -66.99648916, -75.98364321,
        -59.76031418],
       [-67.71817062, -63.85723308, -67.94976878, -62.63456926,
        -64.24801993],
       [-63.57849315, -71.72355489, -69.16205139, -65.14434083,
        -72.15061415],
       [-55.79588077, -69.42483029, -61.26715561, -70.66663792,
        -63.30358375],
       [-55.78975032, -69.04094422, -67.2431771 , -65.10371576,
        -68.45919855],
       [-66.42846743, -64.6475901 , -64.82489647, -66.15611851,
        -66.75835627],
       [-62.70530754, -64.26731413, -67.36571524, -65.03670931,
        -59.40862795],
       [-68.87936883, -73.49732373, -64.37042634, -66.15221014,
        -62.28052126],
       [-64.98504448, -67.14245461, -69.37585366, -66.80972547,
        -56.91154158],
       [-70.86483499, -63.50656486, -59.37839201, -57.37367515,
        -65.53432402],
       [-57.48951831, -64.61985854, -68.41949799, -64.48407516,
        -53.37884042],
       [-73.2953503 , -62.82327948, -62.21526899, -61.86745659,
        -66.21048766],
       [-65.99686656, -66.4328331 , -68.33208935, -56.07469943,
        -52.83104554],
       [-61.56056424, -70.8643528 , -64.00129775, -68.90427126,
        -51.68044015],
       [-58.99999864, -66.8636425 , -65.5334146 , -62.61492857,
        -66.58052338],
       [-70.68450373, -68.01959023, -64.08725481, -66.8895134 ,
        -65.46564521],
       [-65.65941309, -63.82283875, -68.92922311, -64.43195575,
        -70.97528351],
       [-62.88084066, -67.19875965, -61.29097614, -66.50247098,
        -60.04684694],
       [-62.40963937, -67.48848105, -65.21615395, -62.29940752,
        -72.22785948],
       [-67.79843791, -55.71518302, -61.2023287 , -58.63474833,
        -71.66450839],
       [-75.53083834, -65.04965623, -60.62142812, -73.69060251,
        -66.77216342],
       [-60.97794499, -59.35254456, -64.77193098, -65.83110327,
        -67.68791403],
       [-65.6060445 , -68.42223588, -68.14447773, -71.36507352,
        -64.30452735],
       [-68.054435  , -61.55058913, -64.5812675 , -68.76809951,
        -71.77530503],
       [-65.54886995, -55.74238423, -58.31496942, -72.17831147,
        -60.1804915 ],
       [-61.54127391, -70.92843666, -61.25658889, -58.31795134,
        -61.25337928],
       [-61.08994184, -60.64967513, -57.1038325 , -60.62470283,
        -61.38697703],
       [-56.23929322, -67.21229629, -53.59072463, -56.55843509,
        -66.67707412],
       [-59.77964592, -68.04385175, -56.11789139, -63.57885225,
        -64.77148994],
       [-60.83724016, -64.62363094, -60.45984706, -65.2818457 ,
        -59.50168703],
       [-67.07091581, -64.67683172, -69.84230378, -66.04884317,
        -62.51366677],
       [-74.51391955, -63.87014855, -62.56497917, -56.74574799,
        -67.75269356],
       [-63.81197028, -67.86138788, -72.80046182, -71.65979507,
        -70.13882814],
       [-65.33685858, -61.14073119, -67.10088197, -64.06091251,
        -61.05700715],
       [-70.65313079, -67.80045171, -56.2095683 , -60.90344586,
        -67.67551801],
       [-59.18913699, -59.30148731, -67.03068084, -69.94002452,
        -64.08879935],
       [-67.80808155, -59.10620701, -65.18667111, -61.88574364,
        -69.17787281],
       [-72.575116  , -67.52584509, -65.50633565, -67.30399677,
        -66.95933102],
       [-63.62281483, -66.87359946, -64.88528614, -71.82760889,
        -62.48646248],
       [-68.83370519, -67.27342152, -57.80899403, -65.35018109,
        -62.36862666],
       [-62.41673884, -66.81652294, -77.02384307, -65.54246477,
        -63.98615041],
       [-59.95541637, -58.98689599, -63.57121501, -68.05509556,
        -62.79555113],
       [-71.37967852, -61.63135762, -63.63446845, -61.62605706,
        -60.9477507 ],
       [-63.11507567, -53.02778073, -63.85233628, -67.1549075 ,
        -59.45727421],
       [-63.94725612, -63.72260979, -59.98793834, -67.85268133,
        -66.71910485],
       [-60.41573915, -62.10166866, -64.14014858, -72.59153097,
        -70.1630149 ],
       [-63.85801519, -66.76868   , -68.71248265, -65.948096  ,
        -62.18790453],
       [-67.44269693, -69.47547303, -65.12588569, -56.52099749,
        -66.64288309]]) * mV, [0.0 s, 0.1 s], sampling rate: 1.0 kHz)>, <AnalogSignal(array([[-60.38631356, -62.39569905, -66.12251196, -70.53199042,
        -67.4672915 ],
       [-67.8645007 , -61.40164876, -72.19656715, -69.96797098,
        -72.18002722],
       [-59.3957681 , -62.80595567, -71.61255547, -55.78393313,
        -63.9006015 ],
       ...,
       [-63.70374196, -69.00529897, -73.66722574, -64.7216123 ,
        -66.17678013],
       [-67.91016458, -61.76493782, -68.57215419, -69.39514803,
        -67.59784091],
       [-53.73759427, -62.79619149, -70.86397349, -59.85139641,
        -58.94821317]]) * nA, [0.0 s, 0.1 s], sampling rate: 10.0 kHz)>] analogsignals

Since AnalogSignals can contain data from multiple channels, sometimes we wish to include only a subset of channels in a group. For this, Neo provides the ChannelView class, e.g.:

In [55]: from neo import ChannelView

In [56]: channel_of_interest = ChannelView(obj=signal1, index=[2])

In [57]: signal_with_spikes = Group(objects=(channel_of_interest, spike_train))

In [58]: signal_with_spikes
Out[58]: Group with [<SpikeTrain(array([3., 4., 5.]) * s, [0.0 s, 10.0 s])>] spiketrains, [<neo.core.view.ChannelView object at 0x7feadd7e7550>] channelviews

Performance and memory consumption#

In some cases you may not wish to load everything in memory, because it could be too big, or you know you only need to access a subset of the data in a file.

For this scenario, some IO modules provide an optional argument to their read() methods: lazy=True/False.

With lazy=True all data objects (AnalogSignal/SpikeTrain/Event/Epoch/ImageSequence) are replaced by proxy objects (AnalogSignalProxy/SpikeTrainProxy/EventProxy/EpochProxy/ImageSequenceProxy).

By default (if not specified), lazy=False, i.e. all data are loaded.

These proxy objects contain metadata (name, sampling_rate, …) so they can be inspected, but they do not contain any array-like data.

When you want to load the actual data from a proxy object, use the load() method to return a real data object of the appropriate type.

Furthermore load() has a time_slice argument, which allows you to load only a slice of data from the file. In this way the consumption of memory can be finely controlled.

Examples#

For more examples of using Neo, see Examples.

Citing Neo#

If you use Neo in your work, please mention the use of Neo in your Methods section, using our RRID: RRID:SCR_000634.

If you wish to cite Neo in publications, please use:

Garcia S., Guarino D., Jaillet F., Jennings T.R., Pröpper R., Rautenberg P.L., Rodgers C., Sobolev A.,Wachtler T., Yger P. and Davison A.P. (2014) Neo: an object model for handling electrophysiology data in multiple formats. Frontiers in Neuroinformatics 8:10: doi:10.3389/fninf.2014.00010

A BibTeX entry for LaTeX users is:

@article{neo14,
    author = {Garcia S. and Guarino D. and Jaillet F. and Jennings T.R. and Pröpper R. and
              Rautenberg P.L. and Rodgers C. and Sobolev A. and Wachtler T. and Yger P.
              and Davison A.P.},
    doi = {10.3389/fninf.2014.00010},
    full_text = {https://www.frontiersin.org/articles/10.3389/fninf.2014.00010/full},
    journal = {Frontiers in Neuroinformatics},
    month = {February},
    title = {Neo: an object model for handling electrophysiology data in multiple formats},
    volume = {8:10},
    year = {2014}
}