How to use binned-channel reads
Adjacent Neuropixels channels are spatially correlated at LFP frequencies, so full per-channel sampling may not be needed for downstream analysis. LFPackReader supports on-the-fly channel binning: neighbouring channels are summed during decompression, keeping memory use proportional to the binned channel count rather than the raw 384.
A 4-channel bin reduces a 1-hour recording from 1.3 GB to 330 MB, and because binning is applied chunkwise the full array is never materialised in memory.
Set binning at construction
from lfpack import LFPackReader
sr = LFPackReader("recording.lf.h5", bin_channels=4)
traces = sr[0:1000] # shape (1000, nc // 4)
print(sr.nc) # nc // 4 output channelsbin_channels=4 sums every group of 4 adjacent channels. sr.nc returns the binned channel count (raw_nc // bin_channels).
Geometry after binning
sr = LFPackReader("recording.lf.h5", bin_channels=4)
# y positions averaged over each group of 4
print(sr.geometry["y"])
# original per-electrode y positions
print(sr.geometry_full["y"])
# (nc_raw,) — maps each raw channel to its output bin index
print(sr.geometry_full["binned_channel_index"])sr.geometry reflects the binned positions (mean of each group). sr.geometry_full always returns the full per-electrode geometry regardless of binning, plus a binned_channel_index field that maps every raw channel to its corresponding output channel (raw_channel // bin_channels).
Override binning per read
sr = LFPackReader("recording.lf.h5") # default: no binning
traces_raw = sr.read_samples(0, 1000) # (1000, nc)
traces_binned = sr.read_samples(0, 1000, bin_channels=8) # (1000, nc // 8)The bin_channels argument to read / read_samples overrides the instance default for that call only.
Notes
- Binning is applied after decompression; it does not affect what is stored on disk.
bin_channelsmust dividencevenly.- The default
bin_channels=1returns unmodified decompressed data.