---
jupytext:
  formats: md:myst
  text_representation:
    extension: .md
    format_name: myst
    format_version: 0.13
    jupytext_version: 1.11.5
kernelspec:
  display_name: Python 3
  language: python
  name: python3
---

# Capture

The `capture` module provides the core `Capture` class for loading, manipulating, and analyzing capture data from Saleae Logic devices.

## Overview

The `Capture` class represents an individual capture from a Logic MSO device. It provides methods to:

- Load capture data from binary files using `np.memmap` to avoid reading the whole capture into memory
- Access channel data and metadata
- Query information about the capture (channels, time range, etc.)

## Classes

### `Capture`

```python
@dataclass
class Capture:
    # the data in the capture, mappings from channel name to data
    analog_data: Dict[str, BaseAnalogData]
    digital_data: Dict[str, BaseDigitalData]

    # the config used to capture the data
    config: CaptureConfig
```

**Properties:**

- `analog_start_time`: The start time of the capture in MSO-relative seconds
- `analog_sample_rate`: The sample rate that analog traces were taken at in Hz
- `analog_channel_names`: Returns a list of analog channel names in the capture
- `analog_time_series`: Returns the time array for analog data
- `analog_stop_time`: Returns the end time of the capture in seconds
- `num_analog_samples`: Returns the number of analog samples in the capture

**Class Methods:**

- `from_dir`: Create a Capture from a directory containing .bin files
  ```python
  @classmethod
  def from_dir(cls, dir_path: Path) -> "Capture"
  ```
  Call this method on previously saved capture directories to re-create the exact `Capture` object
  that existed when the capture was first returned, including the `CaptureConfig` object used
  to generate the capture in the first place.

- `from_config`: Create a Capture from a CaptureConfig and a save path
  ```python
  @classmethod
  def from_config(cls, config: CaptureConfig, dir_path: Path) -> "Capture"
  ```
  Call this when your previously saved capture doesn't have any .json files detailing the capture
  config in it. This may be the case if your capture came from a Logic2 export.

**Methods:**

- `delete`: Delete the capture files from disk

  Deletes all capture data files from disk. The capture must have been previously stored to disk (i.e., created via `from_dir` or `from_config`).
  Raises `RuntimeError` if the capture was not stored to disk.

  This method will:
  1. Clear the analog and digital data arrays from memory
  2. Run garbage collection to free memory, and
  3. Delete all .bin files from the capture directory on disk

## Working with Capture Data

The `analog_data` and `digital_data` attributes are dictionaries mapping channel names to `AnalogData` and `DigitalData` objects respectively. Channels must have unique names which will be generated for you if not supplied.

### Analog Data

You can access continuous analog data using standard NumPy indexing.

```python
# Get voltage data for channel 1 (channel_index 0)
ch1_volts = cap.analog_data["CH0_volts"].voltages

# Get a specific sample
sample_index = 1000
voltage_at_sample = cap.analog_data["CH0_volts"].voltages[sample_index]
```

### Digital Data

Digital data is stored as an initial state and a list of transition times, which are relative
to the trigger position (or the start of the capture). There are a couple of helper methods that
we use internally to validate data integrity that we've exposed for your use:

```python
def state_at_idx(self, idx: int) -> bool:
    """
    Returns the state of the digital channel just before the given transition_time index
    """
```

This one in particular may come in handy:

```python
def state_at_time(self, time: float) -> bool:
    """
    Returns the state of the digital channel at the given time
    """
```

## Re-Loading Previously Saved Captures

The `Capture` class provides a method for creating a `Capture` instance exactly as it
was when first captured. Call the following to re-load both the configuration and data files:

```{code-cell} python
from pathlib import Path
from saleae.mso_api import Capture

capture = Capture.from_dir(Path("../my-capture"))
print(f"Re-loaded capture with channels: {capture.analog_channel_names}")
```
