Skip to content

Models

Oscilloscope model capabilities and registry

Model capability definitions for different Siglent oscilloscope series.

ModelCapability dataclass

ModelCapability(model_name: str, series: str, num_channels: int, max_sample_rate: float, memory_depth: int, bandwidth_mhz: int, has_math_channels: bool, has_fft: bool, has_protocol_decode: bool, supported_decode_types: List[str], scpi_variant: str, dialect: str = 'legacy', vendor: str = 'siglent', horiz_divisions: int = 14, vert_divisions: int = 8)

Defines capabilities and features for a specific oscilloscope model.

This dataclass contains all model-specific information including hardware specifications and supported features.

validate_channel

validate_channel(scope, channel: int) -> None

Raise unless channel exists on scope's model.

The bound comes from the connected model's num_channels. When that is unavailable or not an int -- an unconnected scope, or a unittest.mock.Mock stand-in whose attribute access yields Mocks that cannot be compared numerically -- fall back to MAX_SUPPORTED_CHANNELS so the guard degrades to a range check instead of raising TypeError.

Parameters:

Name Type Description Default
scope

Oscilloscope (or stand-in) whose model_capability bounds the range

required
channel int

1-based channel number to validate

required

Raises:

Type Description
InvalidParameterError

If the channel is outside 1..num_channels

Source code in scpi_control/models.py
def validate_channel(scope, channel: int) -> None:
    """Raise unless `channel` exists on `scope`'s model.

    The bound comes from the connected model's ``num_channels``. When that is
    unavailable or not an int -- an unconnected scope, or a ``unittest.mock.Mock``
    stand-in whose attribute access yields Mocks that cannot be compared
    numerically -- fall back to MAX_SUPPORTED_CHANNELS so the guard degrades to a
    range check instead of raising TypeError.

    Args:
        scope: Oscilloscope (or stand-in) whose model_capability bounds the range
        channel: 1-based channel number to validate

    Raises:
        InvalidParameterError: If the channel is outside 1..num_channels
    """
    num_channels = getattr(getattr(scope, "model_capability", None), "num_channels", None)
    if not isinstance(num_channels, int):
        num_channels = MAX_SUPPORTED_CHANNELS
    if not 1 <= channel <= num_channels:
        raise exceptions.InvalidParameterError(f"Invalid channel number: {channel}. Must be 1-{num_channels}.")

detect_model_from_idn

detect_model_from_idn(idn_string: str) -> ModelCapability

Detect oscilloscope model and return its capability profile.

Routes on the manufacturer field: Tektronix and LeCroy IDNs are matched against their vendor-scoped registry entries (falling back to a generic vendor capability), while every other manufacturer takes the historical Siglent detection path unchanged.

Parameters:

Name Type Description Default
idn_string str

The response from *IDN? command Format: "Manufacturer,Model,Serial,Firmware" Example: "Siglent Technologies,SDS824X HD,SERIAL123,1.0.0.0"

required

Returns:

Type Description
ModelCapability

ModelCapability object for the detected model

Raises:

Type Description
ValueError

If model cannot be detected from IDN string

Source code in scpi_control/models.py
def detect_model_from_idn(idn_string: str) -> ModelCapability:
    """Detect oscilloscope model and return its capability profile.

    Routes on the manufacturer field: Tektronix and LeCroy IDNs are matched
    against their vendor-scoped registry entries (falling back to a generic
    vendor capability), while every other manufacturer takes the historical
    Siglent detection path unchanged.

    Args:
        idn_string: The response from *IDN? command
                   Format: "Manufacturer,Model,Serial,Firmware"
                   Example: "Siglent Technologies,SDS824X HD,SERIAL123,1.0.0.0"

    Returns:
        ModelCapability object for the detected model

    Raises:
        ValueError: If model cannot be detected from IDN string
    """
    # Parse the manufacturer and model name from IDN string
    parts = idn_string.split(",")
    if len(parts) < 2:
        raise ValueError(f"Invalid *IDN? response format: {idn_string}")

    manufacturer = parts[0].strip().upper()
    model_from_idn = parts[1].strip()
    logger.info(f"Detecting model from IDN: {manufacturer} / {model_from_idn}")

    if "TEKTRONIX" in manufacturer:
        return _match_registry(model_from_idn, "tektronix") or _generic_vendor_capability(model_from_idn, "tektronix")
    if "LECROY" in manufacturer:  # covers both "LECROY" and "TELEDYNE LECROY"
        return _match_registry(model_from_idn, "lecroy") or _generic_vendor_capability(model_from_idn, "lecroy")

    # Everything else takes the historical Siglent path, byte-for-byte
    matched = _match_registry(model_from_idn)
    if matched is not None:
        return matched
    return _detect_siglent(model_from_idn)

list_supported_models

list_supported_models() -> List[str]

Get list of all explicitly supported model names.

Returns:

Type Description
List[str]

List of model names that have full capability definitions

Source code in scpi_control/models.py
def list_supported_models() -> List[str]:
    """Get list of all explicitly supported model names.

    Returns:
        List of model names that have full capability definitions
    """
    return sorted(MODEL_REGISTRY.keys())

get_model_by_series

get_model_by_series(series: str) -> List[ModelCapability]

Get all models in a specific series.

Parameters:

Name Type Description Default
series str

Series identifier (e.g., "SDS1000XE", "SDS2000XPlus")

required

Returns:

Type Description
List[ModelCapability]

List of ModelCapability objects for models in that series

Source code in scpi_control/models.py
def get_model_by_series(series: str) -> List[ModelCapability]:
    """Get all models in a specific series.

    Args:
        series: Series identifier (e.g., "SDS1000XE", "SDS2000XPlus")

    Returns:
        List of ModelCapability objects for models in that series
    """
    return [cap for cap in MODEL_REGISTRY.values() if cap.series == series]

See Also

  • Oscilloscope - Main oscilloscope control class for SCPI communication