Support utilities API¶
The ssms.support_utils namespace exports the kde_class and utils modules.
For the task-oriented likelihood workflow and its input prerequisites, see
Estimate a likelihood with the KDE class.
ssms.support_utils ¶
Modules:
-
kde_class– -
utils–This module provides utility functions for handling parameter dependencies and sampling
ssms.support_utils.kde_class ¶
Classes:
-
LogKDE–Class for generating kdes from (rt, choice) data. Works for any number of choices.
Functions:
-
bandwidth_silverman–Computes silverman bandwidth for an array of samples (rts in our context, but general).
LogKDE ¶
LogKDE(simulator_data: dict, bandwidth_type: str = 'silverman', auto_bandwidth: bool = True, displace_t: bool = False)
Class for generating kdes from (rt, choice) data. Works for any number of choices.
Only samples usable as log-RT KDE input are retained per choice: omission
sentinels, non-positive RTs and non-finite log-RTs are dropped from
data['rts'] and data['log_rts']. Non-positive RTs are legitimate
simulator output for models whose non-decision-time kernel has unbounded
support (a Normal(t, st) kernel, say). data['choice_proportions'] is
computed before this filter, so it still counts the dropped samples.
That is intentional and consistent with omissions, which also count towards
their choice's proportion while contributing no RT to its density.
Known limitation: a choice left with exactly one retained sample falls through
to bandwidth_silverman's std_n_1 default, yielding a bandwidth of about
10.59 that passes the bandwidth > 0 check. That choice's density estimate
is not meaningful.
Methods:
-
compute_bandwidths–Computes bandwidths for each choice from rt data. _generate_base_kdes(auto_bandwidth=True, bandwidth_type='silverman') Generates kdes from rt data. kde_eval(data=([], []), log_eval=True) Evaluates kde log likelihood at chosen points. kde_sample(n_samples=2000, use_empirical_choice_p=True, alternate_choice_p=0) Samples from a given kde. _attach_data_from_simulator(simulator_data={'rts':[0, 2, 4], 'choices':[-1, 1, -1], 'metadata':{}})) Helper function to transform ddm simulator output to dataset suitable for the kde function class.
-
Returns:–type: description
Arguments:
simulator_data: Dictionary containing simulation data with keys 'rts', 'choices', and 'metadata'.
Follows the format returned by simulator functions in this package.
bandwidth_type: Type of bandwidth to use for KDE. Currently only 'silverman' is supported.
Defaults to 'silverman'.
auto_bandwidth: Whether to automatically compute bandwidths based on the data.
If False, bandwidths must be set manually. Defaults to True.
displace_t: Whether to shift RTs by the t parameter from metadata.
Only works if all trials have the same t value and the model's
response times cannot fall below t (see ``KDE_NO_DISPLACE_T``
and the ``ndt_edge_shift`` config key). Defaults to False.
Raises:
ValueError: If displace_t is True but metadata contains multiple t
values, or names a model whose response times start below t.
compute_bandwidths ¶
Computes bandwidths for each choice from rt data.
Arguments:
bandwidth_type: str Type of bandwidth to use, default is 'silverman' which follows silverman rule. return_result: bool Whether to return the result. Defaults to False.
Returns:
bandwidths: list[float] | None List of bandwidths for each choice if return_result is True, otherwise None.
kde_eval ¶
kde_eval(data: dict, log_eval: bool = True, lb: float = -66.774, eps: float = 0.0001, filter_rts: float = OMISSION_SENTINEL) -> np.ndarray
Evaluates kde log likelihood at chosen points.
Arguments:
data: dict Dictionary with keys 'rts', and/or 'log_rts' and 'choices' to evaluate the kde at. If 'rts' is provided, 'log_rts' is ignored. log_eval: boolean Whether to return log likelihood or likelihood, default is True. lb: float Lower bound for log likelihoods, default is -66.774. (This is the log of 1e-29) eps: float Epsilon value to use for lower bounds on rts. filter_rts: float Value to filter rts by, default is OMISSION_SENTINEL (-999). This is the sentinel value returned by simulators when a trial exceeds max_t or deadline (i.e., an omission).
Returns:
log_kde_eval: array Array of log likelihoods for each (rt, choice) pair.
kde_sample ¶
kde_sample(n_samples: int = 2000, use_empirical_choice_p: bool = True, alternate_choice_p: ndarray | float = 0.0, random_state: int | None = None) -> dict[str, np.ndarray | dict]
Samples from a given kde.
Arguments:
n_samples: int Number of samples to draw. use_empirical_choice_p: bool Whether to use empirical choice proportions, default is True. (Note 'empirical' here, refers to the originally attached datasets that served as the basis to generate the choice-wise kdes) alternate_choice_p: np.ndarray | float Array of choice proportions to use, default is 0. (Note 'alternate' here refers to 'alternative' to the 'empirical' choice proportions) random_state: int | None Random seed for reproducibility. If None, uses non-reproducible random behavior.
Returns:
dict[str, np.ndarray | dict] Dictionary containing: - 'rts': np.ndarray - Response times - 'log_rts': np.ndarray - Log of response times - 'choices': np.ndarray - Choices made - 'metadata': dict - Simulator information
bandwidth_silverman ¶
bandwidth_silverman(sample: Iterable[float] = (0, 0, 0), std_cutoff: float = 0.001, std_proc: str = 'restrict', std_n_1: float = 10.0) -> np.float64
Computes silverman bandwidth for an array of samples (rts in our context, but general).
Arguments:
sample: np.ndarray Array of samples to compute bandwidth for. std_cutoff: float Cutoff for std, default is 1e-3. (If sample-std is smaller than this, we either kill it or restrict it to this value) std_proc: str How to deal with small stds, default is 'restrict'. (Options: 'kill', 'restrict') std_n_1: float Value to use if n = 1, default is 10.0. (Not clear if the default is sensible here)
Returns:
float Silverman bandwidth for the given sample. This is applied as the bandwidth parameter when generating gaussian-based kdes in the LogKDE class.
ssms.support_utils.utils ¶
This module provides utility functions for handling parameter dependencies and sampling parameters within specified constraints.
Functions:
-
parse_bounds–Parse the bounds of a parameter and extract any dependencies.
-
build_dependency_graph–Build a dependency graph based on parameter bounds.
-
topological_sort_util–visited: Set[str], stack: List[str], graph: Dict[str, Set[str]], temp_marks: Set[str]) -> None Helper function for performing a depth-first search in the topological sort.
-
topological_sort–Perform a topological sort on the dependency graph to determine the sampling order.
-
sample_parameters_from_constraints–sample_size: int) -> Dict[str, np.ndarray] Sample parameters uniformly within specified bounds, respecting any dependencies.
build_dependency_graph ¶
Build a dependency graph based on parameter bounds.
The graph is structured as parent -> children, where children depend on parent. For example, if 'st' has upper bound 't', then graph['t'] contains 'st'.
Args: param_dict: Dictionary mapping parameter names to (lower, upper) bounds.
Returns: Dictionary where keys are parameters and values are sets of parameters that depend on them.
Raises: ValueError: If a dependency references an undefined parameter.
Example: >>> param_dict = {"a": (0, 1), "b": ("a", 2)} >>> build_dependency_graph(param_dict) {'a': {'b'}, 'b': set()}
parse_bounds ¶
Parse the bounds of a parameter and extract any dependencies.
Args: bounds: A tuple of (lower, upper) bounds. Can be numeric or strings (for dependencies).
Returns: Set of parameter names that this parameter depends on.
Example: >>> parse_bounds((0.0, 1.0)) set() >>> parse_bounds(("a", 1.0)) {'a'} >>> parse_bounds((0.0, "b")) {'b'} >>> parse_bounds(("c", "d"))
sample_parameters_from_constraints ¶
sample_parameters_from_constraints(param_dict: dict[str, tuple[Any, Any]], sample_size: int, random_state: int | None = None) -> Dict[str, np.ndarray]
Sample parameters uniformly within specified bounds, respecting any dependencies.
This is a backward-compatible wrapper around UniformParameterSampler.
Args: param_dict: Dictionary mapping parameter names to (lower, upper) bounds. Bounds can be numeric or strings (for dependencies). sample_size: Number of parameter sets to sample. random_state: Optional random seed for reproducibility.
Returns: Dictionary mapping parameter names to arrays of sampled values.
Raises: ValueError: If bounds are invalid (lower >= upper) or circular dependencies exist.
Example: >>> param_dict = {"v": (-1.0, 1.0), "a": (0.5, 2.0)} >>> samples = sample_parameters_from_constraints(param_dict, sample_size=10) >>> samples['v'].shape (10,)
topological_sort ¶
Perform a topological sort on the dependency graph to determine the sampling order.
Args: graph: Dependency graph where keys are parameters and values are sets of parameters that depend on them.
Returns: List of parameter names in sampling order (dependencies first).
Raises: ValueError: If circular dependencies are detected.
Example: >>> graph = {"a": {"b"}, "b": set()} >>> topological_sort(graph) ['a', 'b']
topological_sort_util ¶
topological_sort_util(node: str, visited: set[str], stack: list[str], graph: dict[str, set[str]], temp_marks: set[str]) -> None
Helper function for performing a depth-first search in the topological sort.
Args: node: Current node to visit visited: Set of permanently visited nodes stack: List to accumulate the topological order (prepended in post-order) graph: Dependency graph temp_marks: Set of temporarily marked nodes (for cycle detection)
Raises: ValueError: If a circular dependency is detected.
LogKDE¶
ssms.support_utils.kde_class.LogKDE ¶
LogKDE(simulator_data: dict, bandwidth_type: str = 'silverman', auto_bandwidth: bool = True, displace_t: bool = False)
Class for generating kdes from (rt, choice) data. Works for any number of choices.
Only samples usable as log-RT KDE input are retained per choice: omission
sentinels, non-positive RTs and non-finite log-RTs are dropped from
data['rts'] and data['log_rts']. Non-positive RTs are legitimate
simulator output for models whose non-decision-time kernel has unbounded
support (a Normal(t, st) kernel, say). data['choice_proportions'] is
computed before this filter, so it still counts the dropped samples.
That is intentional and consistent with omissions, which also count towards
their choice's proportion while contributing no RT to its density.
Known limitation: a choice left with exactly one retained sample falls through
to bandwidth_silverman's std_n_1 default, yielding a bandwidth of about
10.59 that passes the bandwidth > 0 check. That choice's density estimate
is not meaningful.
Methods:
-
compute_bandwidths–Computes bandwidths for each choice from rt data. _generate_base_kdes(auto_bandwidth=True, bandwidth_type='silverman') Generates kdes from rt data. kde_eval(data=([], []), log_eval=True) Evaluates kde log likelihood at chosen points. kde_sample(n_samples=2000, use_empirical_choice_p=True, alternate_choice_p=0) Samples from a given kde. _attach_data_from_simulator(simulator_data={'rts':[0, 2, 4], 'choices':[-1, 1, -1], 'metadata':{}})) Helper function to transform ddm simulator output to dataset suitable for the kde function class.
-
Returns:–type: description
Arguments:
simulator_data: Dictionary containing simulation data with keys 'rts', 'choices', and 'metadata'.
Follows the format returned by simulator functions in this package.
bandwidth_type: Type of bandwidth to use for KDE. Currently only 'silverman' is supported.
Defaults to 'silverman'.
auto_bandwidth: Whether to automatically compute bandwidths based on the data.
If False, bandwidths must be set manually. Defaults to True.
displace_t: Whether to shift RTs by the t parameter from metadata.
Only works if all trials have the same t value and the model's
response times cannot fall below t (see ``KDE_NO_DISPLACE_T``
and the ``ndt_edge_shift`` config key). Defaults to False.
Raises:
ValueError: If displace_t is True but metadata contains multiple t
values, or names a model whose response times start below t.
ssms.support_utils.kde_class.LogKDE.compute_bandwidths ¶
Computes bandwidths for each choice from rt data.
Arguments:
bandwidth_type: str Type of bandwidth to use, default is 'silverman' which follows silverman rule. return_result: bool Whether to return the result. Defaults to False.
Returns:
bandwidths: list[float] | None List of bandwidths for each choice if return_result is True, otherwise None.
ssms.support_utils.kde_class.LogKDE.kde_eval ¶
kde_eval(data: dict, log_eval: bool = True, lb: float = -66.774, eps: float = 0.0001, filter_rts: float = OMISSION_SENTINEL) -> np.ndarray
Evaluates kde log likelihood at chosen points.
Arguments:
data: dict Dictionary with keys 'rts', and/or 'log_rts' and 'choices' to evaluate the kde at. If 'rts' is provided, 'log_rts' is ignored. log_eval: boolean Whether to return log likelihood or likelihood, default is True. lb: float Lower bound for log likelihoods, default is -66.774. (This is the log of 1e-29) eps: float Epsilon value to use for lower bounds on rts. filter_rts: float Value to filter rts by, default is OMISSION_SENTINEL (-999). This is the sentinel value returned by simulators when a trial exceeds max_t or deadline (i.e., an omission).
Returns:
log_kde_eval: array Array of log likelihoods for each (rt, choice) pair.
ssms.support_utils.kde_class.LogKDE.kde_sample ¶
kde_sample(n_samples: int = 2000, use_empirical_choice_p: bool = True, alternate_choice_p: ndarray | float = 0.0, random_state: int | None = None) -> dict[str, np.ndarray | dict]
Samples from a given kde.
Arguments:
n_samples: int Number of samples to draw. use_empirical_choice_p: bool Whether to use empirical choice proportions, default is True. (Note 'empirical' here, refers to the originally attached datasets that served as the basis to generate the choice-wise kdes) alternate_choice_p: np.ndarray | float Array of choice proportions to use, default is 0. (Note 'alternate' here refers to 'alternative' to the 'empirical' choice proportions) random_state: int | None Random seed for reproducibility. If None, uses non-reproducible random behavior.
Returns:
dict[str, np.ndarray | dict] Dictionary containing: - 'rts': np.ndarray - Response times - 'log_rts': np.ndarray - Log of response times - 'choices': np.ndarray - Choices made - 'metadata': dict - Simulator information
ssms.support_utils.kde_class.bandwidth_silverman ¶
bandwidth_silverman(sample: Iterable[float] = (0, 0, 0), std_cutoff: float = 0.001, std_proc: str = 'restrict', std_n_1: float = 10.0) -> np.float64
Computes silverman bandwidth for an array of samples (rts in our context, but general).
Arguments:
sample: np.ndarray Array of samples to compute bandwidth for. std_cutoff: float Cutoff for std, default is 1e-3. (If sample-std is smaller than this, we either kill it or restrict it to this value) std_proc: str How to deal with small stds, default is 'restrict'. (Options: 'kill', 'restrict') std_n_1: float Value to use if n = 1, default is 10.0. (Not clear if the default is sensible here)
Returns:
float Silverman bandwidth for the given sample. This is applied as the bandwidth parameter when generating gaussian-based kdes in the LogKDE class.