0
# Core Data Structures
1
2
Fundamental data containers and objects for representing all types of electrophysiology data. Neo's hierarchical design organizes data into containers (Block, Segment, Group) that hold data objects (signals, spikes, events) with rich metadata and dimensional consistency.
3
4
## Capabilities
5
6
### Container Classes
7
8
Top-level organizational structures that group related electrophysiology data.
9
10
```python { .api }
11
class Block:
12
"""
13
Main container for entire experiments or recording sessions.
14
15
A Block represents the top level grouping of data and is not necessarily
16
temporally homogeneous, in contrast to Segment.
17
"""
18
def __init__(self, name=None, description=None, file_origin=None,
19
file_datetime=None, rec_datetime=None, index=None,
20
**annotations): ...
21
22
# Container relationships
23
segments: list[Segment] # Temporal divisions of the experiment
24
groups: list[Group] # Logical groupings across segments
25
26
# Methods
27
def filter(self, **kwargs): ... # Filter contained objects by properties
28
def merge(self, other): ... # Merge with another Block
29
30
class Segment:
31
"""
32
Container for temporally related data objects.
33
34
A Segment represents a time period within an experiment, typically
35
corresponding to a trial, stimulus presentation, or recording epoch.
36
"""
37
def __init__(self, name=None, description=None, **annotations): ...
38
39
# Data object containers
40
analogsignals: list[AnalogSignal] # Continuous signals
41
irregularlysampledsignals: list[IrregularlySampledSignal] # Non-uniform sampling
42
spiketrains: list[SpikeTrain] # Spike timing data
43
events: list[Event] # Point events
44
epochs: list[Epoch] # Time intervals
45
imagesequences: list[ImageSequence] # Image data sequences
46
47
# Methods
48
def filter(self, **kwargs): ... # Filter contained objects
49
t_start: pq.Quantity # Segment start time
50
t_stop: pq.Quantity # Segment stop time
51
52
class Group:
53
"""
54
Logical grouping container for related data objects.
55
56
Groups organize related objects across segments, typically representing
57
electrode arrays, tetrodes, or other logical recording arrangements.
58
"""
59
def __init__(self, name=None, description=None, **annotations): ...
60
61
# Data object containers (same as Segment)
62
analogsignals: list[AnalogSignal]
63
spiketrains: list[SpikeTrain]
64
events: list[Event]
65
epochs: list[Epoch]
66
```
67
68
### Signal Classes
69
70
Continuous data representations for analog recordings.
71
72
```python { .api }
73
class AnalogSignal:
74
"""
75
Regularly sampled continuous analog signals with physical units.
76
77
Represents multi-channel continuous data like LFP, EEG, voltage clamp
78
recordings, or any uniformly sampled analog measurements.
79
80
Note: The 'copy' parameter is deprecated and will be removed in Neo 0.15.0.
81
Only copy=None is accepted; any other value raises ValueError.
82
"""
83
def __init__(self, signal, units=None, dtype=None, copy=None,
84
t_start=0*pq.s, sampling_rate=None, sampling_period=None,
85
name=None, file_origin=None, description=None,
86
array_annotations=None, **annotations): ...
87
88
# Properties
89
shape: tuple # (n_samples, n_channels)
90
sampling_rate: pq.Quantity # Hz, kHz, etc.
91
sampling_period: pq.Quantity # s, ms, etc.
92
t_start: pq.Quantity # Start time
93
t_stop: pq.Quantity # End time
94
duration: pq.Quantity # Total duration
95
times: pq.Quantity # Time array for each sample
96
97
# Methods
98
def time_slice(self, t_start, t_stop): ... # Extract time window
99
def time_index(self, t): ... # Get array index for time
100
def time_shift(self, t_shift): ... # Shift signal to new start time
101
def downsample(self, downsampling_factor, **kwargs): ... # Downsample signal data
102
def resample(self, sample_count, **kwargs): ... # Resample to fixed sample count
103
def rectify(self, **kwargs): ... # Rectify by taking absolute value
104
def concatenate(self, *signals, overwrite=False, padding=False): ... # Concatenate signals
105
def splice(self, signal, copy=False): ... # Replace part of signal
106
def channel_index_to_channel_id(self, index): ... # Channel mapping
107
def merge(self, other): ... # Combine signals
108
109
class IrregularlySampledSignal:
110
"""
111
Irregularly sampled continuous analog signals.
112
113
For data with non-uniform sampling intervals, where each sample
114
has an associated timestamp.
115
"""
116
def __init__(self, times, signal, units=None, time_units=None,
117
dtype=None, copy=None, name=None, file_origin=None, description=None,
118
array_annotations=None, **annotations): ...
119
120
# Properties
121
times: pq.Quantity # Sample timestamps
122
shape: tuple # (n_samples, n_channels)
123
t_start: pq.Quantity # First timestamp
124
t_stop: pq.Quantity # Last timestamp
125
126
# Methods
127
def time_slice(self, t_start, t_stop): ...
128
def merge(self, other): ...
129
130
class ChannelView:
131
"""
132
View into specific channels of multi-channel signals.
133
134
Provides a way to work with subsets of channels from AnalogSignal
135
or IrregularlySampledSignal objects without copying data.
136
"""
137
def __init__(self, obj, index): ...
138
139
# Properties inherit from parent signal
140
# Methods delegate to parent signal
141
```
142
143
### Event and Timing Classes
144
145
Discrete event data and time interval representations.
146
147
```python { .api }
148
class Event:
149
"""
150
Time-stamped discrete events with labels and annotations.
151
152
Represents point events like stimulus onsets, behavioral markers,
153
or detected events with associated metadata.
154
"""
155
def __init__(self, times, labels=None, units=None, name=None,
156
description=None, **annotations): ...
157
158
# Properties
159
times: pq.Quantity # Event timestamps
160
labels: np.ndarray # String labels for each event
161
size: int # Number of events
162
163
# Methods
164
def time_slice(self, t_start, t_stop): ...
165
def merge(self, other): ...
166
167
class Epoch:
168
"""
169
Time intervals with duration and labels.
170
171
Represents periods of time like stimulus presentations, behavioral
172
states, or analysis windows with start times and durations.
173
"""
174
def __init__(self, times, durations, labels=None, units=None,
175
name=None, description=None, **annotations): ...
176
177
# Properties
178
times: pq.Quantity # Start times
179
durations: pq.Quantity # Duration of each epoch
180
labels: np.ndarray # String labels
181
size: int # Number of epochs
182
183
# Methods
184
def time_slice(self, t_start, t_stop): ...
185
def merge(self, other): ...
186
```
187
188
### Spike Data Classes
189
190
Specialized containers for action potential timing data.
191
192
```python { .api }
193
class SpikeTrain:
194
"""
195
Sequence of action potential timestamps with metadata.
196
197
Represents spike timing data from single units or multi-unit
198
activity with support for waveforms and spike classifications.
199
"""
200
def __init__(self, times, t_stop, units=None, dtype=None, copy=None,
201
sampling_rate=1.0*pq.Hz, t_start=0.0*pq.s, waveforms=None,
202
left_sweep=None, name=None, file_origin=None, description=None,
203
array_annotations=None, **annotations): ...
204
205
# Properties
206
times: pq.Quantity # Spike timestamps
207
t_start: pq.Quantum # Recording start time
208
t_stop: pq.Quantity # Recording stop time
209
duration: pq.Quantity # Total recording duration
210
size: int # Number of spikes
211
waveforms: pq.Quantity # Spike waveform data (optional)
212
sampling_rate: pq.Quantity # Waveform sampling rate
213
left_sweep: pq.Quantity # Pre-spike waveform duration
214
215
# Methods
216
def time_slice(self, t_start, t_stop): ... # Extract time window
217
def merge(self, other): ... # Combine spike trains
218
def isi(self): ... # Inter-spike intervals
219
def cv(self): ... # Coefficient of variation
220
```
221
222
### Image and ROI Classes
223
224
Support for image sequences and regions of interest.
225
226
```python { .api }
227
class ImageSequence:
228
"""
229
Sequences of 2D images with timing information.
230
231
For optical imaging data, calcium imaging, or other image-based
232
measurements with temporal sequences.
233
"""
234
def __init__(self, image_data, units=None, dtype=None, copy=True,
235
t_start=0*pq.s, sampling_rate=None, sampling_period=None,
236
spatial_scale=None, name=None, description=None,
237
**annotations): ...
238
239
# Properties
240
shape: tuple # (n_frames, height, width, [channels])
241
sampling_rate: pq.Quantity # Frame rate
242
spatial_scale: pq.Quantity # Spatial resolution
243
times: pq.Quantity # Frame timestamps
244
245
# Methods
246
def time_slice(self, t_start, t_stop): ...
247
248
class RectangularRegionOfInterest:
249
"""Rectangular region of interest definition."""
250
def __init__(self, x, y, width, height, **annotations): ...
251
252
class CircularRegionOfInterest:
253
"""Circular region of interest definition."""
254
def __init__(self, x, y, radius, **annotations): ...
255
256
class PolygonRegionOfInterest:
257
"""Polygon-shaped region of interest definition."""
258
def __init__(self, x, y, **annotations): ...
259
```
260
261
### Filter Classes
262
263
Query and filtering system for data objects.
264
265
```python { .api }
266
class FilterCondition:
267
"""Abstract base class for filter conditions."""
268
269
class Equals:
270
"""Equality filter condition for data properties."""
271
def __init__(self, value): ...
272
273
class IsNot:
274
"""Inequality filter condition."""
275
def __init__(self, value): ...
276
277
class LessThan:
278
"""Less-than filter condition."""
279
def __init__(self, value): ...
280
281
class GreaterThan:
282
"""Greater-than filter condition."""
283
def __init__(self, value): ...
284
285
class IsIn:
286
"""Membership test filter condition."""
287
def __init__(self, values): ...
288
289
class InRange:
290
"""Range-based filter condition."""
291
def __init__(self, min_val, max_val): ...
292
```
293
294
## Usage Examples
295
296
### Creating and Organizing Data
297
298
```python
299
import neo
300
import numpy as np
301
import quantities as pq
302
303
# Create hierarchical structure
304
block = neo.Block(name="Experiment 1", experimenter="Dr. Smith")
305
segment = neo.Segment(name="Trial 1", trial_id=1)
306
block.segments.append(segment)
307
308
# Add continuous signals
309
signal_data = np.random.randn(1000, 4) * pq.mV
310
analog_signal = neo.AnalogSignal(
311
signal_data,
312
sampling_rate=1*pq.kHz,
313
t_start=0*pq.s,
314
name="LFP",
315
channel_names=['Ch1', 'Ch2', 'Ch3', 'Ch4']
316
)
317
segment.analogsignals.append(analog_signal)
318
319
# Add spike data
320
spike_times = np.array([0.1, 0.3, 0.7, 1.2]) * pq.s
321
spike_train = neo.SpikeTrain(
322
spike_times,
323
t_start=0*pq.s,
324
t_stop=2*pq.s,
325
name="Unit 1"
326
)
327
segment.spiketrains.append(spike_train)
328
329
# Add events
330
event_times = np.array([0.5, 1.0, 1.5]) * pq.s
331
events = neo.Event(
332
event_times,
333
labels=['stimulus_on', 'response', 'stimulus_off']
334
)
335
segment.events.append(events)
336
```
337
338
### Working with Signal Data
339
340
```python
341
# Time slicing
342
signal_slice = analog_signal.time_slice(0.1*pq.s, 0.5*pq.s)
343
344
# Channel selection
345
channel_view = neo.ChannelView(analog_signal, [0, 2]) # Channels 1 and 3
346
347
# Access properties
348
print(f"Shape: {analog_signal.shape}")
349
print(f"Sampling rate: {analog_signal.sampling_rate}")
350
print(f"Duration: {analog_signal.duration}")
351
print(f"Times shape: {analog_signal.times.shape}")
352
```
353
354
### Filtering and Queries
355
356
```python
357
from neo.core.filters import Equals, GreaterThan
358
359
# Filter spike trains by name
360
unit1_trains = segment.filter(name=Equals("Unit 1"), objects="SpikeTrain")
361
362
# Filter events by time
363
late_events = segment.filter(times=GreaterThan(1.0*pq.s), objects="Event")
364
365
# Complex filtering
366
fast_spikes = segment.filter(
367
name=Equals("Unit 1"),
368
size=GreaterThan(10),
369
objects="SpikeTrain"
370
)
371
```
372
373
## Types
374
375
```python { .api }
376
# Base quantity types from quantities package
377
Signal = np.ndarray * pq.Quantity # Multidimensional array with units
378
Time = pq.Quantity # Time values (s, ms, μs, etc.)
379
Rate = pq.Quantity # Frequencies (Hz, kHz, MHz, etc.)
380
Voltage = pq.Quantity # Electrical potential (V, mV, μV, etc.)
381
382
# Container types
383
BlockList = list[Block] # List of Block objects
384
SegmentList = list[Segment] # List of Segment objects
385
GroupList = list[Group] # List of Group objects
386
387
# Data object types
388
AnalogSignalList = list[AnalogSignal] # List of AnalogSignal objects
389
SpikeTrainList = list[SpikeTrain] # List of SpikeTrain objects
390
EventList = list[Event] # List of Event objects
391
EpochList = list[Epoch] # List of Epoch objects
392
393
# Metadata types
394
Annotations = dict[str, Any] # Arbitrary key-value metadata
395
ChannelNames = list[str] # Channel identification strings
396
Labels = np.ndarray # String labels for events/epochs
397
```