CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-neo

A comprehensive Python library for representing electrophysiology data with support for reading and writing a wide range of neurophysiology file formats.

Pending
Overview
Eval results
Files

core-data-structures.mddocs/

Core Data Structures

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.

Capabilities

Container Classes

Top-level organizational structures that group related electrophysiology data.

class Block:
    """
    Main container for entire experiments or recording sessions.
    
    A Block represents the top level grouping of data and is not necessarily 
    temporally homogeneous, in contrast to Segment.
    """
    def __init__(self, name=None, description=None, file_origin=None,
                 file_datetime=None, rec_datetime=None, index=None,
                 **annotations): ...
    
    # Container relationships
    segments: list[Segment]  # Temporal divisions of the experiment
    groups: list[Group]      # Logical groupings across segments
    
    # Methods
    def filter(self, **kwargs): ...  # Filter contained objects by properties
    def merge(self, other): ...      # Merge with another Block

class Segment:
    """
    Container for temporally related data objects.
    
    A Segment represents a time period within an experiment, typically
    corresponding to a trial, stimulus presentation, or recording epoch.
    """
    def __init__(self, name=None, description=None, **annotations): ...
    
    # Data object containers
    analogsignals: list[AnalogSignal]               # Continuous signals
    irregularlysampledsignals: list[IrregularlySampledSignal]  # Non-uniform sampling
    spiketrains: list[SpikeTrain]                   # Spike timing data
    events: list[Event]                             # Point events
    epochs: list[Epoch]                             # Time intervals
    imagesequences: list[ImageSequence]             # Image data sequences
    
    # Methods  
    def filter(self, **kwargs): ...     # Filter contained objects
    t_start: pq.Quantity               # Segment start time
    t_stop: pq.Quantity                # Segment stop time

class Group:
    """
    Logical grouping container for related data objects.
    
    Groups organize related objects across segments, typically representing
    electrode arrays, tetrodes, or other logical recording arrangements.
    """
    def __init__(self, name=None, description=None, **annotations): ...
    
    # Data object containers (same as Segment)
    analogsignals: list[AnalogSignal]
    spiketrains: list[SpikeTrain]
    events: list[Event]
    epochs: list[Epoch]

Signal Classes

Continuous data representations for analog recordings.

class AnalogSignal:
    """
    Regularly sampled continuous analog signals with physical units.
    
    Represents multi-channel continuous data like LFP, EEG, voltage clamp
    recordings, or any uniformly sampled analog measurements.
    
    Note: The 'copy' parameter is deprecated and will be removed in Neo 0.15.0.
    Only copy=None is accepted; any other value raises ValueError.
    """
    def __init__(self, signal, units=None, dtype=None, copy=None,
                 t_start=0*pq.s, sampling_rate=None, sampling_period=None,
                 name=None, file_origin=None, description=None,
                 array_annotations=None, **annotations): ...
    
    # Properties
    shape: tuple                    # (n_samples, n_channels)
    sampling_rate: pq.Quantity      # Hz, kHz, etc.
    sampling_period: pq.Quantity    # s, ms, etc.
    t_start: pq.Quantity           # Start time
    t_stop: pq.Quantity            # End time
    duration: pq.Quantity          # Total duration
    times: pq.Quantity             # Time array for each sample
    
    # Methods
    def time_slice(self, t_start, t_stop): ...          # Extract time window
    def time_index(self, t): ...                        # Get array index for time
    def time_shift(self, t_shift): ...                  # Shift signal to new start time
    def downsample(self, downsampling_factor, **kwargs): ...  # Downsample signal data
    def resample(self, sample_count, **kwargs): ...     # Resample to fixed sample count
    def rectify(self, **kwargs): ...                    # Rectify by taking absolute value
    def concatenate(self, *signals, overwrite=False, padding=False): ...  # Concatenate signals
    def splice(self, signal, copy=False): ...           # Replace part of signal
    def channel_index_to_channel_id(self, index): ...   # Channel mapping
    def merge(self, other): ...                         # Combine signals

class IrregularlySampledSignal:
    """
    Irregularly sampled continuous analog signals.
    
    For data with non-uniform sampling intervals, where each sample
    has an associated timestamp.
    """
    def __init__(self, times, signal, units=None, time_units=None,
                 dtype=None, copy=None, name=None, file_origin=None, description=None,
                 array_annotations=None, **annotations): ...
    
    # Properties  
    times: pq.Quantity             # Sample timestamps
    shape: tuple                   # (n_samples, n_channels)
    t_start: pq.Quantity          # First timestamp
    t_stop: pq.Quantity           # Last timestamp
    
    # Methods
    def time_slice(self, t_start, t_stop): ...
    def merge(self, other): ...

class ChannelView:
    """
    View into specific channels of multi-channel signals.
    
    Provides a way to work with subsets of channels from AnalogSignal
    or IrregularlySampledSignal objects without copying data.
    """
    def __init__(self, obj, index): ...
    
    # Properties inherit from parent signal
    # Methods delegate to parent signal

Event and Timing Classes

Discrete event data and time interval representations.

class Event:
    """
    Time-stamped discrete events with labels and annotations.
    
    Represents point events like stimulus onsets, behavioral markers,
    or detected events with associated metadata.
    """
    def __init__(self, times, labels=None, units=None, name=None,
                 description=None, **annotations): ...
    
    # Properties
    times: pq.Quantity            # Event timestamps
    labels: np.ndarray            # String labels for each event
    size: int                     # Number of events
    
    # Methods
    def time_slice(self, t_start, t_stop): ...
    def merge(self, other): ...

class Epoch:
    """
    Time intervals with duration and labels.
    
    Represents periods of time like stimulus presentations, behavioral
    states, or analysis windows with start times and durations.
    """
    def __init__(self, times, durations, labels=None, units=None,
                 name=None, description=None, **annotations): ...
    
    # Properties
    times: pq.Quantity            # Start times
    durations: pq.Quantity        # Duration of each epoch
    labels: np.ndarray            # String labels
    size: int                     # Number of epochs
    
    # Methods
    def time_slice(self, t_start, t_stop): ...
    def merge(self, other): ...

Spike Data Classes

Specialized containers for action potential timing data.

class SpikeTrain:
    """
    Sequence of action potential timestamps with metadata.
    
    Represents spike timing data from single units or multi-unit
    activity with support for waveforms and spike classifications.
    """
    def __init__(self, times, t_stop, units=None, dtype=None, copy=None,
                 sampling_rate=1.0*pq.Hz, t_start=0.0*pq.s, waveforms=None,
                 left_sweep=None, name=None, file_origin=None, description=None,
                 array_annotations=None, **annotations): ...
    
    # Properties
    times: pq.Quantity            # Spike timestamps  
    t_start: pq.Quantum           # Recording start time
    t_stop: pq.Quantity           # Recording stop time
    duration: pq.Quantity         # Total recording duration
    size: int                     # Number of spikes
    waveforms: pq.Quantity        # Spike waveform data (optional)
    sampling_rate: pq.Quantity    # Waveform sampling rate
    left_sweep: pq.Quantity       # Pre-spike waveform duration
    
    # Methods
    def time_slice(self, t_start, t_stop): ...     # Extract time window
    def merge(self, other): ...                     # Combine spike trains
    def isi(self): ...                             # Inter-spike intervals
    def cv(self): ...                              # Coefficient of variation

Image and ROI Classes

Support for image sequences and regions of interest.

class ImageSequence:
    """
    Sequences of 2D images with timing information.
    
    For optical imaging data, calcium imaging, or other image-based
    measurements with temporal sequences.
    """
    def __init__(self, image_data, units=None, dtype=None, copy=True,
                 t_start=0*pq.s, sampling_rate=None, sampling_period=None,
                 spatial_scale=None, name=None, description=None,
                 **annotations): ...
    
    # Properties
    shape: tuple                  # (n_frames, height, width, [channels])
    sampling_rate: pq.Quantity    # Frame rate
    spatial_scale: pq.Quantity    # Spatial resolution
    times: pq.Quantity           # Frame timestamps
    
    # Methods  
    def time_slice(self, t_start, t_stop): ...

class RectangularRegionOfInterest:
    """Rectangular region of interest definition."""
    def __init__(self, x, y, width, height, **annotations): ...
    
class CircularRegionOfInterest:  
    """Circular region of interest definition."""
    def __init__(self, x, y, radius, **annotations): ...
    
class PolygonRegionOfInterest:
    """Polygon-shaped region of interest definition."""
    def __init__(self, x, y, **annotations): ...

Filter Classes

Query and filtering system for data objects.

class FilterCondition:
    """Abstract base class for filter conditions."""
    
class Equals:
    """Equality filter condition for data properties."""
    def __init__(self, value): ...
    
class IsNot:
    """Inequality filter condition."""  
    def __init__(self, value): ...
    
class LessThan:
    """Less-than filter condition."""
    def __init__(self, value): ...
    
class GreaterThan:
    """Greater-than filter condition."""
    def __init__(self, value): ...
    
class IsIn:
    """Membership test filter condition."""
    def __init__(self, values): ...
    
class InRange:
    """Range-based filter condition."""
    def __init__(self, min_val, max_val): ...

Usage Examples

Creating and Organizing Data

import neo
import numpy as np
import quantities as pq

# Create hierarchical structure
block = neo.Block(name="Experiment 1", experimenter="Dr. Smith")
segment = neo.Segment(name="Trial 1", trial_id=1)
block.segments.append(segment)

# Add continuous signals
signal_data = np.random.randn(1000, 4) * pq.mV
analog_signal = neo.AnalogSignal(
    signal_data,
    sampling_rate=1*pq.kHz,
    t_start=0*pq.s,
    name="LFP",
    channel_names=['Ch1', 'Ch2', 'Ch3', 'Ch4']
)
segment.analogsignals.append(analog_signal)

# Add spike data
spike_times = np.array([0.1, 0.3, 0.7, 1.2]) * pq.s
spike_train = neo.SpikeTrain(
    spike_times,
    t_start=0*pq.s,
    t_stop=2*pq.s,
    name="Unit 1"
)
segment.spiketrains.append(spike_train)

# Add events
event_times = np.array([0.5, 1.0, 1.5]) * pq.s
events = neo.Event(
    event_times,
    labels=['stimulus_on', 'response', 'stimulus_off']
)
segment.events.append(events)

Working with Signal Data

# Time slicing
signal_slice = analog_signal.time_slice(0.1*pq.s, 0.5*pq.s)

# Channel selection
channel_view = neo.ChannelView(analog_signal, [0, 2])  # Channels 1 and 3

# Access properties
print(f"Shape: {analog_signal.shape}")
print(f"Sampling rate: {analog_signal.sampling_rate}")
print(f"Duration: {analog_signal.duration}")
print(f"Times shape: {analog_signal.times.shape}")

Filtering and Queries

from neo.core.filters import Equals, GreaterThan

# Filter spike trains by name
unit1_trains = segment.filter(name=Equals("Unit 1"), objects="SpikeTrain")

# Filter events by time
late_events = segment.filter(times=GreaterThan(1.0*pq.s), objects="Event")

# Complex filtering
fast_spikes = segment.filter(
    name=Equals("Unit 1"),
    size=GreaterThan(10),
    objects="SpikeTrain"
)

Types

# Base quantity types from quantities package  
Signal = np.ndarray * pq.Quantity      # Multidimensional array with units
Time = pq.Quantity                     # Time values (s, ms, μs, etc.)
Rate = pq.Quantity                     # Frequencies (Hz, kHz, MHz, etc.)
Voltage = pq.Quantity                  # Electrical potential (V, mV, μV, etc.)

# Container types
BlockList = list[Block]                # List of Block objects
SegmentList = list[Segment]            # List of Segment objects
GroupList = list[Group]                # List of Group objects

# Data object types  
AnalogSignalList = list[AnalogSignal]  # List of AnalogSignal objects
SpikeTrainList = list[SpikeTrain]      # List of SpikeTrain objects
EventList = list[Event]                # List of Event objects
EpochList = list[Epoch]                # List of Epoch objects

# Metadata types
Annotations = dict[str, Any]           # Arbitrary key-value metadata
ChannelNames = list[str]               # Channel identification strings
Labels = np.ndarray                    # String labels for events/epochs

Install with Tessl CLI

npx tessl i tessl/pypi-neo

docs

core-data-structures.md

data-utilities.md

file-io-support.md

index.md

rawio-access.md

tile.json