multimeter#
- class brainpy.state.multimeter(in_size=1, record_from=(), interval=Quantity(1., 'ms'), offset=Quantity(0., 'ms'), start=Quantity(0., 'ms'), stop=None, origin=Quantity(0., 'ms'), time_in_steps=False, frozen=False, name=None)#
NEST-compatible analog recorder for neuron/device state variables.
multimeterrecords analog state samples from connected targets into an in-memoryeventsdictionary compatible with NESTmultimetersemantics. The NEST device-level timing model is reproduced while exposing a Python update API:Sampling times are constrained to a step-grid lattice defined by
intervalandoffset.Recording is gated by a window \((\mathrm{origin}+\mathrm{start},\;\mathrm{origin}+\mathrm{stop}]\) (start exclusive, stop inclusive) evaluated in simulation steps.
Samples are enqueued at the current step and emitted on the next
update()call (or immediately byflush()), reproducing the one-step request/reply lag used by NEST multimeters.
1. Step-Grid Sampling Model
Let \(dt\) be simulation resolution in ms, and let step index \(n = \mathrm{round}(t/dt)\). During
update(), sampled values are stamped at\[s = n + 1.\]Define integer grid parameters
\[m = \frac{\mathrm{interval}}{dt}, \qquad o = \frac{\mathrm{offset}}{dt}.\]A sample is enqueued iff \(s\) lies on the lattice:
\[s \equiv 0 \ (\mathrm{mod}\ m) \quad \text{if}\ o = 0, \qquad s \equiv o \ (\mathrm{mod}\ m),\ s \ge o \quad \text{if}\ o > 0.\]Both
intervalandoffsetmust be exact integer multiples ofdt(verified to within1e-12tolerance in floating conversion).2. Active Window and Delivery Lag
With \(s_\min = (\mathrm{origin}+\mathrm{start})/dt\) and \(s_\max = (\mathrm{origin}+\mathrm{stop})/dt\) (or \(+\infty\) when
stopisNone), a pending sample is written toeventsonly when\[s > s_\min \quad \land \quad s \le s_\max.\]Because pending samples are emitted before new sampling in each
update(), values observed at step \(n\) become visible ineventsat step \(n+1\) unlessflush()is called.3. Payload Normalization and Shape Constraints
For each requested recordable
kinrecord_from,data[k]is converted tonp.float64and flattened to shape(N,). All recordables must share the sameN; scalar payloads (size 1) are broadcast to(N,)when another recordable definesN > 1.sendersis converted tonp.int64with the same broadcast rule, defaulting to ones when omitted. Stored event arrays are one-dimensional with length equal to the total number of emitted samples across all steps.4. Computational Implications
Per
update()call with payload sizeNandR = len(record_from), enqueue work is \(O(RN)\). Pending emission is linear in the number of buffered items and the appended event count. Memory usage grows linearly with total emitted events fortimes,senders, and each requested recordable channel.- Parameters:
in_size (
Size, optional) – Output size/shape argument consumed bybrainstate.nn.Dynamics. This recorder is stateful and returns event dictionaries;in_sizeis retained for API consistency only. Default is1.record_from (
Sequence[str], optional) – Ordered names of recordable state variables expected as keys indataduringupdate(). If empty, incoming payloads are silently ignored and no values are stored. Default is().interval (
saiunit.Quantityorfloat, optional) – Scalar sampling interval in time units convertible to ms (typicallyu.ms). Must satisfyinterval >= dtand be an exact integer multiple ofdt(checked to within1e-12tolerance). Default is1.0 * u.ms.offset (
saiunit.Quantityorfloat, optional) – Scalar phase offset of the sampling lattice relative to the simulation origin, convertible to ms. Must be0.0or a positive integer multiple ofdt; non-zero offsets shift the first sample to step \(o\) and every \(m\)-th step thereafter. Default is0.0 * u.ms.start (
saiunit.Quantityorfloat, optional) – Scalar exclusive lower bound of the recording window relative toorigin, convertible to ms. A pending sample at stamp step \(s\) is discarded when \(s \le s_\min\). Default is0.0 * u.ms.stop (
saiunit.Quantity,float, orNone, optional) – Scalar inclusive upper bound of the recording window relative toorigin, convertible to ms. Must satisfystop >= startwhen notNone.Nonemeans no upper bound (\(s_\max = +\infty\)). Default isNone.origin (
saiunit.Quantityorfloat, optional) – Scalar global time-origin shift added to bothstartandstopwhen constructing the active window, convertible to ms. Shifting the origin displaces the entire recording window without changing its duration. Default is0.0 * u.ms.time_in_steps (
bool, optional) – Controls the unit ofevents['times']. IfFalse, timestamps are stored as float milliseconds (stamp_step * dt). IfTrue, timestamps are stored as integer-valued step numbers cast tofloat64, and an additionalevents['offsets']key is emitted as a zero-filled array of matching shape. Default isFalse.frozen (
bool, optional) – NEST-compatibility flag.Trueis unconditionally rejected because multimeters cannot be frozen. Default isFalse.name (
strorNone, optional) – Optional node name forwarded tobrainstate.nn.Dynamics. Default isNone.
Parameter Mapping
Table 40 Mapping of constructor parameters to model symbols# Parameter
Default
Math symbol
Semantics
interval1.0 * u.ms\(m \cdot dt\)
Sampling period on the simulation step grid.
offset0.0 * u.ms\(o \cdot dt\)
Phase shift of the sampling lattice.
start0.0 * u.ms\(t_{\mathrm{start,rel}}\)
Relative exclusive lower bound of the activity window.
stopNone\(t_{\mathrm{stop,rel}}\)
Relative inclusive upper bound of the activity window.
origin0.0 * u.ms\(t_0\)
Global time-origin shift for the recording window.
record_from()\(\{x_r\}_{r=1}^{R}\)
Ordered recordable channels expected in each payload.
- Raises:
ValueError – If
frozen=True; if any timing parameter (interval,offset,start,stop,origin,dt) is not scalar-convertible, not finite when required, not aligned todt, or violates ordering constraints (e.g.interval < dtorstop < start); ifdatapassed toupdate()is not a mapping; if a required recordable key is absent fromdata; if a recordable payload is empty after conversion; or if recordable/sender lengths are inconsistent after flattening/broadcasting.TypeError – If unit conversion or array casting of any time parameter or payload value to a numeric type fails.
KeyError – If
get()is called with a key other than'events'or'n_events'.
Notes
After the first
connect()call or the first data-carryingupdate(), propertiesinterval,offset, andrecord_frombecome immutable and further assignments raiseValueError.This recorder does not read neuron states autonomously; the caller is responsible for extracting state values and passing them via
datain eachupdate()call after state integration.init_state()clears all accumulated events and the pending buffer; it can be used to reset the recorder between simulation segments without reconstructing the object.
References
Examples
Record membrane potential from a single
iaf_psc_deltaneuron for 50 steps at 0.1 ms resolution, with the recording window clipped to the first 5 ms:>>> import brainpy >>> import brainstate >>> import saiunit as u >>> import numpy as np >>> with brainstate.environ.context(dt=0.1 * u.ms): ... neuron = brainpy.state.iaf_psc_delta(1, I_e=500.0 * u.pA) ... neuron.init_state() ... mm = brainpy.state.multimeter( ... record_from=['V_m'], ... interval=0.1 * u.ms, ... start=0.0 * u.ms, ... stop=5.0 * u.ms, ... ) ... for k in range(50): ... with brainstate.environ.context(t=k * 0.1 * u.ms): ... neuron.update() ... vm = float(neuron.V.value[0] / u.mV) dftype = brainstate.environ.dftype() ... _ = mm.update( ... {'V_m': np.array([vm], dtype=dftype)}, ... senders=np.array([1]), ... ) ... events = mm.flush() ... _ = events['V_m'].shape
- flush()[source]#
Emit all buffered pending samples and return the current event store.
Reads
dtfrombrainstate.environ.get_dt(), validates timing calibration, converts pending step stamps to output times, and appends all active samples to the internal event arrays. After the call the pending buffer is empty.- Returns:
events – Event dictionary identical to
events, reflecting all samples emitted up to and including this call. See the class-levelReturnssection for the full description of keys and dtypes.- Return type:
dict[str,np.ndarray]- Raises:
ValueError – If
dtobtained from the simulation environment is non-positive, not scalar-convertible, or incompatible with the configured timing parameters (interval,offset,start,stop,origin).TypeError – If
dtcannot be converted to a scalarfloatms value.
- update(data=None, senders=None)[source]#
Process one simulation step and optionally enqueue a new sample.
- Parameters:
data (
Mapping[str,ArrayLike]orNone, optional) – Mapping from each name inrecord_fromto its current analog value payload. Each payload is converted tonp.float64and flattened to shape(N,). Scalars (size 1) are broadcast to(N,)when another recordable definesN > 1. IfNone, no new sample is enqueued and only pending samples are emitted. Default isNone.senders (
ArrayLikeorNone, optional) – Sender IDs associated with the payload. Converted tonp.int64and flattened to shape(N,)using the same scalar-broadcast rule as recordables. IfNone, all sender IDs default to1. Default isNone.
- Returns:
events – Event dictionary identical to
eventsafter emitting all pending samples and optionally enqueuing the new payload. See the class-levelReturnssection for the full description of keys and dtypes.- Return type:
dict[str,np.ndarray]- Raises:
ValueError – If current simulation time
tis not aligned to the simulation grid; if timing parameters are incompatible withdt; ifdatais not aMapping; if a required recordable key is absent fromdata; if a recordable payload is empty after conversion; or if recordable/sender lengths are inconsistent after the scalar-broadcast rule.TypeError – If conversion of
t,dt, or any payload value to a numeric array fails.KeyError – If
brainstate.environdoes not provide the't'ordtcontext keys required for step computation.