Skip to content

radiens_qc.units

Read the units a clustered sort found in a recording.

Distinct from :mod:radiens_qc.events, which reads threshold crossings. The two come from different scrapes of the same recording and neither substitutes for the other -- see :mod:radiens_qc.spikes. A crossing is a site detecting something; a unit is a cell the sorter clustered across a neighborhood, and the question this level answers is what cells are here rather than what each site saw.

Nothing here is archived on a :class:~radiens_qc.report.QualityReport, for the same reason an excerpt is not: a report is a measurement the KPI pass produced, while this is a view into the recording, fetched when a figure is drawn. The sort is the caller's, named by spikes_id; see :mod:radiens_qc.spikes.

Waveforms are the largest thing the package moves, so they are fetched separately -- :func:fetch_unit_waveforms reads a bounded sample of spikes, which :meth:SortedUnits.with_waveforms attaches to the units it read them for. :func:fetch_units never fetches them, and nothing caches them. The figures reporting amplitude find it there, and say so when it is absent.

Classes

SortedUnits dataclass

Every unit a clustered sort found in one recording.

Attributes:

Name Type Description
base_name str

Recording identifier.

sampling_rate float

Sampling rate in Hz.

time_range_sec tuple[float, float]

(start, end) on the dataset's own time base, which does not generally start at zero.

geometry DataFrame

Per-channel probe geometry, indexed by ntv_idx. Held so a figure can draw the sites a unit sits among, not because a unit belongs to one.

units DataFrame

One row per unit, indexed by integer label, carrying the primary site, spike count and rate, SNR, and probe coordinates. Those coordinates are the primary site's, copied: the sorter reports no position of its own, so they carry nothing site_ntv_idx does not.

spikes dict[int, NDArray[float64]]

label -> spike times in seconds on that same time base.

spikes_id str

Fileset the units were read from, so a caller wanting waveforms reads them from the same sort.

waveforms dict[int, UnitFootprint]

label -> UnitFootprint, empty until :meth:with_waveforms attaches what :func:fetch_unit_waveforms read. Empty is a normal state, not a failure: the figures that show amplitude say so rather than drawing a field of zeros.

Attributes

labels property
labels

Unit labels, in the row order :attr:units holds them.

Methods:

amplitudes_uv
amplitudes_uv()

label -> µV peak of each unit's mean waveform at its detecting site.

Measured from the waveforms because the sorter reports no amplitude of its own. The same quantity the channel level maps as event amplitude -- the mean absolute peak of an event, at the site that saw it best -- so the two share a color scale and a unit map can be read against the site map beneath it.

Peak of the mean rather than peak-to-peak: peak-to-peak is roughly twice as large, and drawing it against the channel level's scale would put every unit at the top of a ramp that means something else.

Empty when no waveforms are attached, and a unit whose footprint omits its own detecting site is skipped rather than reported at a neighbor's amplitude.

depth_order
depth_order()

Row order for a unit raster: by where the cell sits, not by label.

A unit's probe coordinates are its primary site's, copied -- the sorter reports no position of its own -- so units sharing a site tie exactly. Descending spike count breaks the tie, which puts the site's dominant cell first and matches how :func:_unit_table picks the listing every other per-unit field is read from.

times
times(label)

Spike times for one unit, empty when it has none in the read span.

with_waveforms
with_waveforms(waveforms)

A copy carrying waveforms, as read by :func:fetch_unit_waveforms.

Separate from the fetch so the read stays a read: waveforms are the largest payload the package moves, and whether to pay for them is the caller's decision, not something reading the units settles.

UnitFootprint dataclass

One unit's spikes as the probe saw them, across a neighborhood at once.

Attributes:

Name Type Description
detecting_ntv_idx int

The site these spikes were detected on -- the one that saw the unit most, among the sites that detected it at all.

site_ntv_idx list[int]

The site each column of :attr:waveforms was recorded on, in row order, starting with detecting_ntv_idx. Neighbors are ordered by distance from the detecting site rather than by position on the probe.

waveforms NDArray[float64]

(spikes, sites, wfm_pts), one window per site per spike.

spike_count int

Spikes the unit fired on the detecting site over the read span, before any sampling -- so a sampled footprint still reports what it is a sample of.

Functions:

fetch_unit_waveforms

fetch_unit_waveforms(
    vc, dataset, units, *, sample=WAVEFORM_SAMPLE
)

Each unit's spikes, each one carrying every site that saw it.

Read by channel rather than by neuron. A neuron-keyed read attributes a whole channel's rows to every neuron on it, so a site carrying two cells reports the same waveforms for both. Reading by channel and selecting the rows whose label is the unit's keeps a unit's spikes its own.

A spike is kept only on the site that saw its largest peak, and it carries that site's detection neighborhood alongside. Taking one detecting site's spikes therefore gives a footprint whose traces are all the same spikes seen in different places -- which is what makes the spatial spread readable. Pooling across detecting sites would not: those are disjoint sets of spikes, so each site's mean would be over different events, and a unit whose peak wandered would read as one that was wide.

The detecting site is the one that saw the unit most. A unit is listed under several only when its extremum moved between them, which happens to the marginal, low-count units rather than the well-isolated ones.

Read from the fileset the units came from. Sampling bounds the payload: a unit firing at 20 Hz for half an hour has 36,000 spikes, and a mean is converged long before that.

Returns:

Type Description
dict[int, UnitFootprint]

label -> UnitFootprint, for every unit with waveforms in the read span.

fetch_units

fetch_units(vc, data, spikes_id, *, channels=None)

Read every unit a clustered sort found in the recording.

Parameters:

Name Type Description Default
vc VidereClient

Client connected to the server holding the recording.

required
data DatasetMetadata | Path

An already-linked recording, or a path to link.

required
spikes_id str

Clustered fileset to read.

required
channels Sequence[int] | None

Amplifier ntv_idx values to read. None (the default) reads the datasource's current selection.

None

Returns:

Type Description
SortedUnits

The units, with the site geometry needed to draw the probe they sit on.

Raises:

Type Description
ValueError

If no amplifier channels are selected, or the fileset is detect-only or lacks a selected channel.