Skip to content

External simulator API

SSMSToPyDDMMapper converts compatible ssms model configurations into PyDDM models for analytical Fokker–Planck solutions. See Simulation vs. analytical solutions for the compatibility trade-off and worked comparison.

ssms.external_simulators.SSMSToPyDDMMapper

Maps ssms model configurations to PyDDM models.

PyDDM can solve the Fokker-Planck equation for: - Single-particle, two-choice models - Gaussian noise only - Arbitrary drift functions (time-dependent, position-dependent, parameter-dependent) - Arbitrary boundary functions (time-dependent, parameter-dependent)

Compatible models include: - ddm and variants (without sv/sz/st) - angle, weibull (collapsing boundaries) - ornstein (leaky/unstable integration) - gamma_drift (time-dependent drift) - conflict_, attend_, shrink_spot_* (custom drift models)

Incompatible models: - race_, lca_, lba* (multi-particle) - levy (non-Gaussian noise) - full_ddm, ddm_sdv, ddm_st (inter-trial variability)

Methods:

ssms.external_simulators.SSMSToPyDDMMapper.build_pyddm_model classmethod

build_pyddm_model(model_config: dict[str, Any], theta: dict[str, Any], generator_config: dict[str, Any] | None = None)

Build PyDDM model for specific parameter values.

Args: model_config: Model structure (name, params, drift_config, boundary_config) theta: Specific parameter values for this instance generator_config: Simulation settings (delta_t, max_t). If None, uses defaults: {'delta_t': 0.001, 'max_t': 20.0}

Returns: pyddm.Model instance ready to solve()

Raises: ValueError: If model is not compatible with PyDDM ImportError: If pyddm package is not installed

ssms.external_simulators.SSMSToPyDDMMapper.create_boundary_function classmethod

create_boundary_function(model_config: dict[str, Any]) -> Callable

Create PyDDM boundary function from ssms model config.

Returns callable with signature: boundary(t, **theta)

Architecture: - Standard model configs specify boundary_name and boundary function - Metadata (params, multiplicative) is looked up from the boundary registry - Direct boundary_config dict is supported for custom runtime configurations

This design avoids duplicating metadata across 100+ model configs and ensures consistent behavior for all instances of a given boundary type (e.g., all "angle" boundaries work the same way).

Args: model_config: Model configuration dictionary from ssms.config

Returns: Callable that accepts (t, **theta) and returns boundary value

ssms.external_simulators.SSMSToPyDDMMapper.create_drift_function classmethod

create_drift_function(model_config: dict[str, Any]) -> Callable

Create PyDDM drift function from ssms model config.

Returns callable with signature: drift(t, x, **theta)

Handles: - Constant drift (v) - Position-dependent drift (Ornstein: v - g*x) - Custom time-dependent drift (gamma_drift, conflict models, etc.)

Architecture: - Standard model configs specify drift_name and drift_fun - Metadata (params) is looked up from the drift registry - Direct drift_config dict is supported for custom runtime configurations

This design avoids duplicating metadata across 100+ model configs.

Args: model_config: Model configuration dictionary from ssms.config

Returns: Callable that accepts (t, x, **theta) and returns drift rate

ssms.external_simulators.SSMSToPyDDMMapper.is_compatible classmethod

is_compatible(model_config: dict[str, Any]) -> tuple[bool, str]

Check if model can use PyDDM analytical solver.

Args: model_config: Model configuration dictionary from ssms.config

Returns: (is_compatible, reason_if_not)

ssms.external_simulators.SSMSToPyDDMMapper.transform_z_to_x0 classmethod

transform_z_to_x0(z: float, bound_at_t0: float, safety_margin: float = 0.99) -> float

Transform z from [0,1] to PyDDM starting position within valid bounds.

Args: z: Starting position in ssms format (0=lower, 0.5=center, 1=upper) bound_at_t0: Boundary value at t=0 (defines valid range) safety_margin: Scale factor to keep x0 away from exact boundaries (default 0.99)

Returns: Starting position in PyDDM format, within [-bound_at_t0, bound_at_t0]

Note: PyDDM requires starting position to be strictly within the bounds at t=0. The safety margin ensures x0 is not at the exact boundary, avoiding discretization issues with PyDDM's spatial grid. Formula: x0 = (2z - 1) * bound(0) * safety_margin