# IQCapture

## class IQCapture( samples: ndarray, sample_period_ns: float, channels: tuple[str, ...], center_freq_hz: tuple[float, ...], t0_ns: int | None = None, dropped_samples: int = 0, )[source]

Bases: [`object`](https://docs.python.org/3/builtins/functions.html#object "(in Python v3.15)")

One time-aligned block of IQ samples across one or more channels of a signal path.

Every row shares one timebase, so a multi-channel capture is aligned by construction.

Variables:
:   - **samples** (*numpy.ndarray*) – Complex IQ samples shaped `(n_channels, n_samples)`. Always
      two-dimensional, even for a single channel.
    - **sample_period_ns** ([*float*](https://docs.python.org/3/builtins/functions.html#float "(in Python v3.15)")) – Time between samples, in nanoseconds, shared by every row.
    - **channels** ([*tuple*](https://docs.python.org/3/builtins/stdtypes.html#tuple "(in Python v3.15)")*[*[*str*](https://docs.python.org/3/builtins/stdtypes.html#str "(in Python v3.15)")*,* *...**]*) – Channel each row of `samples` came from.
    - **center_freq_hz** ([*tuple*](https://docs.python.org/3/builtins/stdtypes.html#tuple "(in Python v3.15)")*[*[*float*](https://docs.python.org/3/builtins/functions.html#float "(in Python v3.15)")*,* *...**]*) – Frequency each channel was tuned to, in Hz.
    - **t0_ns** ([*int*](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)") *|* *None*) – Hardware timestamp of the first sample, in nanoseconds since the Unix
      epoch. `None` when the device has no clock of its own, in which case
      [`InstroSDR`](https://dev.nominal.io/instro/ref/instruments/generated/instro.unstable.sdr.InstroSDR.md#instro.unstable.sdr.InstroSDR "instro.unstable.sdr.sdr.InstroSDR") anchors the block to the host clock.
    - **dropped_samples** ([*int*](https://docs.python.org/3/builtins/functions.html#int "(in Python v3.15)")) – Samples lost before this block because the stream could not keep up.

Raises:
:   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If `samples` is not two-dimensional, or its row count does not match
    `channels` and `center_freq_hz`.

Example

```
capture = IQCapture(
    samples=np.zeros((1, 4096), dtype=np.complex128),
    sample_period_ns=1e9 / 2.4e6,
    channels=("0",),
    center_freq_hz=(100e6,),
)
row = capture.samples_for("0")
```

### samples: ndarray

### sample_period_ns: float

### channels: tuple[str, ...]

### center_freq_hz: tuple[float, ...]

### t0_ns: int | None = None

### dropped_samples: int = 0

### property overflow: bool

Whether any samples were dropped before this block.

Returns:
:   *bool* – `True` when `dropped_samples` is greater than zero.

### samples_for(channel: str) → ndarray[source]

Return the row of samples belonging to one channel.

Parameters:
:   **channel** ([*str*](https://docs.python.org/3/builtins/stdtypes.html#str "(in Python v3.15)"))

    Channel to read.

Returns:
:   *numpy.ndarray* – The channel’s complex IQ samples, one-dimensional.

Raises:
:   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If the capture holds no such channel.

### center_freq_for(channel: str) → float[source]

Return the frequency a channel was tuned to when these samples were taken.

Parameters:
:   **channel** ([*str*](https://docs.python.org/3/builtins/stdtypes.html#str "(in Python v3.15)"))

    Channel to read.

Returns:
:   *float* – Center frequency in Hz.

Raises:
:   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If the capture holds no such channel.

### select( channels: Sequence[str], ) → IQCapture[source]

Narrow this capture to a subset of its channels, keeping the shared timebase.

Parameters:
:   **channels** (*Sequence**[*[*str*](https://docs.python.org/3/builtins/stdtypes.html#str "(in Python v3.15)")*]*)

    Channels to keep, in the order the rows should appear.

Returns:
:   *IQCapture* – A capture holding only `channels`, or this capture unchanged if they
    already match.

Raises:
:   [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError "(in Python v3.15)") – If any of `channels` is not in the capture.
