Operations API Reference¶
Custom operations for use in SciStanPy Stan models.
This module provides a framework for adding mathematical operations to the model
graph. Operations are built from
TransformedParameter
classes and can handle both immediate computation on NumPy/PyTorch data and deferred
computation within model graphs. This module should be the access point to all operations
available in SciStanPy–users should not need to directly interact with the underlying
transformation classes.
Operation Framework¶
The operations module provides a framework for creating mathematical operations from TransformedParameter
classes that work with both SciStanPy model components and raw numerical data (NumPy arrays/PyTorch tensors).
Core Classes:
- class scistanpy.operations.MetaOperation(name, bases, attrs)[source]¶
Bases:
type
Metaclass for dynamically creating operation classes.
This metaclass is responsible for creating operation classes from
TransformedParameter
classes. It validates that aDISTCLASS
attribute is provided and appropriate, then automatically inherits documentation from the underlying transformation class. In general, users will not need to interact with this metaclass directly.- Parameters:
name (str) – Name of the class being created
bases (tuple) – Base classes for the new class
attrs (dict) – Class attributes dictionary
- Raises:
ValueError – If
DISTCLASS
is not provided in class attributesTypeError – If
DISTCLASS
is not a subclass ofTransformedParameter
- The metaclass performs the following validations and setup:
Ensures
DISTCLASS
attribute existsValidates
DISTCLASS
inheritance fromTransformedParameter
Inherits documentation from the
DISTCLASS
to the__call__
method
- class scistanpy.operations.Operation[source]¶
Bases:
object
Base class for SciStanPy mathematical operations.
This class provides the foundation for all mathematical operations that can be used in SciStanPy models. Operations can handle both immediate computation on numerical data and deferred computation when used with model components.
The class should never be instantiated directly. Instead, use the
build_operation()
function to create specific operation instances fromTransformedParameter
classes.- Variables:
DISTCLASS – The
TransformedParameter
class this operation wraps.
Note
Operations automatically detect whether they are being called with SciStanPy model components or raw numerical data and handle each case appropriately.
- DISTCLASS: type[TransformedParameter]¶
- __call__(*args, **kwargs)[source]¶
Apply the operation to the provided inputs.
This method provides intelligent dispatching based on the input types. When called with SciStanPy model components, it returns a new
TransformedParameter
instance for deferred computation. When called with raw numerical data (numpy), it performs immediate computation.- Parameters:
args (tuple) – Positional arguments for the operation. Can be model components or numerical data.
kwargs (dict) – Keyword arguments for the operation. Can contain model components or numerical data.
- Returns:
Either a
TransformedParameter
instance (for deferred computation) or the immediate result of the operation on numerical data.- Return type:
Union[transformed_parameters.TransformedParameter, Any]
- The method behavior depends on input types:
If any argument is a SciStanPy model component: Returns a
TransformedParameter
instance for later evaluationIf all arguments are numerical data: Performs immediate computation using the underlying
TransformedParameter.run_np_torch_op()
method to compute and return the result directly.
Operation Builder:
The build_operation()
function allows users to create custom operations easily by wrapping a TransformedParameter
subclass. This is the main interface for creating new operations from custom TransformedParameter
classes and is what is used under the hood to create all built-in operations.
- scistanpy.operations.build_operation(
- distclass: type[TransformedParameter],
Build an operation instance from a TransformedParameter class.
This function creates a new operation class using the
MetaOperation
metaclass in combination with theOperation
base class, then returns an instance of that class. The resulting operation inherits documentation and behavior from the providedTransformedParameter
class.- Parameters:
distclass (type[transformed_parameters.TransformedParameter]) – The
TransformedParameter
class to build the operation from.- Returns:
A new operation instance that wraps the provided
TransformedParameter
class.- Return type:
- Raises:
ValueError – If distclass is not provided
TypeError – If distclass is not a subclass of TransformedParameter
Example:
from scistanpy.operations import build_operation from scistanpy.model.components.transformations.transformed_parameters import UnaryTransformedParameter class MyTransformation(UnaryTransformedParameter): # Custom mathematical transformation. def run_np_torch_op(self, x): # Implementation for numerical data return x**2 + 1 def write_stan_operation(self, x: str) -> str: # Stan code generation return f"square({x}) + 1" # Create operation my_operation = build_operation(MyTransformation) # Use the operation param = ssp.parameters.Normal(mu=0.0, sigma=1.0) transformed = my_operation(param)
Operation Usage Patterns¶
Operations can be used in two main contexts: with SciStanPy model components (Parameter
, TransformedParameter
, and Constant
) and with raw numerical data (NumPy arrays or PyTorch tensors). The operations automatically dispatch to the appropriate behavior based on the input type.
With Model Components:
# Operations with parameters create transformed parameters
base_param = ssp.parameters.Normal(mu=0.0, sigma=1.0)
transformed = ssp.operations.exp(base_param)
# Use in model definitions
observed = ssp.parameters.Normal(mu=transformed, sigma=0.1)
With Numerical Data:
# Operations with numerical data compute immediately
import numpy as np
data = np.array([1, 2, 3])
result = ssp.operations.exp(data) # Returns exp([1, 2, 3])
Intelligent Dispatching:
# Operations automatically detect input types
def my_function(x):
return ssp.operations.log(ssp.operations.exp(x) + 1)
# Works with both parameters and data
param_result = my_function(ssp.parameters.Normal(mu=0, sigma=1))
data_result = my_function(np.array([1, 2, 3]))
Available Operations¶
The following operations are available in the SciStanPy operations module. Each operation is documented with its usage patterns and examples.
If there’s a specific mathematical operation that you need which is not listed here (and, given that this is an evolving library, there are certainly many missing), please consider (A) raising an issue on the SciStanPy GitHub repository requesting its addition, or (B) creating a custom operation using the build_operation()
function. If you take the latter approach, also consider contributing your custom operation back to the SciStanPy project for inclusion in future releases!
Mathematical Functions¶
Below are the basic mathematical operations provided by SciStanPy.
- scistanpy.operations.abs_(*args, **kwargs)¶
Absolute value operation.
Computes the absolute value of the input parameter or numerical data. See also,
AbsParameter
.Usage:
# With model components param = ssp.parameters.Normal(mu=0.0, sigma=1.0) abs_param = ssp.operations.abs_(param) # With numerical data result = ssp.operations.abs_([-1.0, -2.0, 3.0]) # Returns [1.0, 2.0, 3.0]
- scistanpy.operations.exp(*args, **kwargs)¶
Exponential operation.
Computes the exponential (e^x) of the input parameter or numerical data. See also,
ExpParameter
.Usage:
# Exponential transformation log_rate = ssp.parameters.Normal(mu=0.0, sigma=1.0) rate = ssp.operations.exp(log_rate) # Ensures positive values
- scistanpy.operations.log(*args, **kwargs)¶
Natural logarithm operation.
Computes the natural logarithm of the input parameter or numerical data. See also,
LogParameter
.Usage:
# Natural logarithm positive_param = ssp.parameters.LogNormal(mu=0.0, sigma=1.0) log_param = ssp.operations.log(positive_param)
- scistanpy.operations.log1p_exp(*args, **kwargs)¶
\(\log(1 + \exp(x))\) operation.
Computes \(\log(1 + \exp(x))\) in a numerically stable way. See also,
Log1pExpParameter
.
- scistanpy.operations.sigmoid(*args, **kwargs)¶
Sigmoid operation.
Computes the sigmoid function \((1 + \exp(-x))^{-1}\) of the input. See also,
SigmoidParameter
.Usage:
# Convert logits to probabilities logits = ssp.parameters.Normal(mu=0.0, sigma=1.0) probabilities = ssp.operations.sigmoid(logits)
- scistanpy.operations.log_sigmoid(*args, **kwargs)¶
Log-sigmoid operation.
Computes the logarithm of the sigmoid function in a numerically stable way. See also,
LogSigmoidParameter
.
Normalization Operations¶
Normalization operations that can be used to build constrained transformed parameters from unconstrained parameters. Take care with these when sampling! It is easy to create non-identifiable models if the normalization is not used correctly.
Note
The normalization operations always operate over the last dimension of the input parameter when applied to SciStanPy parameters.
- scistanpy.operations.normalize(*args, **kwargs)¶
Normalization operation.
Normalizes input data to unit sum. Note that when applied to SciStanPy parameters, this operation is always performed over the last dimension. See also,
NormalizeParameter
.Usage:
# Normalize to unit sum (over last dimension) weights = ssp.parameters.LogNormal(mu=0.0, sigma=1.0, shape=(3, 9)) probabilities = ssp.operations.normalize(weights) # Each row sums to 1
- scistanpy.operations.normalize_log(*args, **kwargs)¶
Log-space normalization operation.
This function ensures that the sum of exponentials is equal to 1 over the last dimension of the input. See also,
NormalizeLogParameter
.Usage:
# Normalize to unit sum (over last dimension) weights = ssp.parameters.Normal(mu=0.0, sigma=1.0, shape=(3, 9)) probabilities = ssp.operations.exp( ssp.operations.normalize(weights) ) # Each row sums to 1
Reduction Operations¶
Reduction operations allow for aggregating values across dimensions of parameters or data. As with the normalization operations, these always operate over the last dimension of the input parameter when applied to SciStanPy parameters.
- scistanpy.operations.sum_(*args, **kwargs)¶
Summation operation.
Computes the sum over an input parameter dimension or over numerical data. Note that for SciStanPy operations, the sum is always performed over the last dimension. See also,
SumParameter
.Usage:
# Sum over last dimension values = ssp.parameters.Normal(mu=0.0, sigma=1.0, shape=(5, 3)) total = ssp.operations.sum_(values) # Shape = (5,) # Sum but keep dimensions total_keepdims = ssp.operations.sum_(values, keepdims=True) # Shape = (5, 1)
- scistanpy.operations.logsumexp(*args, **kwargs)¶
Log-sum-exp operation.
Note that for SciStanPy operations, the sum is always performed over the last dimension.
Computes log(sum(exp(x))) in a numerically stable way. See also,
LogSumExpParameter
.
Growth Model Operations¶
Growth model operations provide a set of mathematical transformations for modeling population growth and similar temporal dynamics. These operations can be used to define growth models in a probabilistic framework (e.g., for deep mutational scanning).
- scistanpy.operations.exponential_growth(*args, **kwargs)¶
Exponential growth operation.
Models exponential growth patterns in time series data. See also,
ExponentialGrowth
.Usage:
# Model exponential population growth time_points = np.array([0, 1, 2, 3, 4]) initial_pop = ssp.parameters.LogNormal(mu=np.log(100), sigma=0.1) growth_rate = ssp.parameters.Normal(mu=0.1, sigma=0.05) population = ssp.operations.exponential_growth( t=time_points, A=initial_pop, r=growth_rate )
- scistanpy.operations.binary_exponential_growth(*args, **kwargs)¶
Binary exponential growth operation.
Models exponential growth over two timepoints, taking in the population size at the starting time (assumed to be at t = 0) and outputting the population size at the ending time (assumed to be at t = 1). See also,
BinaryExponentialGrowth
.Usage:
# Two-timepoint exponential growth initial_size = ssp.parameters.LogNormal(mu=np.log(50), sigma=0.2) growth_rate = ssp.parameters.Normal(mu=0.2, sigma=0.1) final_size = ssp.operations.binary_exponential_growth( A=initial_size, r=growth_rate )
- scistanpy.operations.log_exponential_growth(*args, **kwargs)¶
Log-exponential growth operation.
Identical to ~scistanpy.operations.exponential_growth, only models the log of the population size. See also,
LogExponentialGrowth
.
- scistanpy.operations.binary_log_exponential_growth(*args, **kwargs)¶
Binary log-exponential growth operation.
Identical to
binary_exponential_growth()
, only models the log of the population size. See also,BinaryLogExponentialGrowth
.
- scistanpy.operations.sigmoid_growth(*args, **kwargs)¶
Sigmoid growth operation.
Models sigmoid growth patterns in time series data. See also,
SigmoidGrowth
.Usage:
# Logistic growth with carrying capacity time_points = np.array([0, 5, 10, 15, 20]) carrying_capacity = ssp.parameters.LogNormal(mu=np.log(1000), sigma=0.1) growth_rate = ssp.parameters.Normal(mu=0.3, sigma=0.1) inflection_time = ssp.parameters.Normal(mu=10.0, sigma=2.0) population = ssp.operations.sigmoid_growth( t=time_points, A=carrying_capacity, r=growth_rate, c=inflection_time )
- scistanpy.operations.log_sigmoid_growth(*args, **kwargs)¶
Log-sigmoid growth operation.
Identical to
log_sigmoid_growth()
, only models the log of the population size. See also,LogSigmoidGrowth
.
- scistanpy.operations.sigmoid_growth_init_param(*args, **kwargs)¶
An alternate parametrization of
sigmoid_growth()
parametrized using initial population abundance rather than carrying capacity. See also,SigmoidGrowthInitParametrization
.Usage:
# Alternative sigmoid parametrization using initial population time_points = np.array([0, 5, 10]) carrying_capacity = ssp.parameters.LogNormal(mu=np.log(1000), sigma=0.1) growth_rate = ssp.parameters.Normal(mu=0.3, sigma=0.1) init_pop = ssp.parameters.LogNormal(mu=np.log(10), sigma=0.2) population = ssp.operations.sigmoid_growth_init_param( t=time_points, A=carrying_capacity, r=growth_rate, A0=init_pop )
- scistanpy.operations.log_sigmoid_growth_init_param(*args, **kwargs)¶
An alternative parametrization of
log_sigmoid_growth()
parametrized using initial population abundance rather than carrying capacity. See also,LogSigmoidGrowthInitParametrization
.
Specialized Operations¶
Specialized operations provide additional mathematical transformations that are useful in specific modeling contexts. There is plenty of room for expansion in this category, and users are encouraged to contribute new operations as needed.
- scistanpy.operations.convolve_sequence(*args, **kwargs)¶
Sequence convolution operation.
Performs convolution operations on sequence data. See also,
ConvolveSequence
.Usage:
# Sequence convolution for pattern matching weights = Normal(mu=0, sigma=1, shape=(motif_length, 4)) # 4 nucleotides dna_sequence = Constant(encoded_dna) # 0,1,2,3 for A,C,G,T # Perform convolution of the sequence with the weights convolved = ssp.operations.convolve_sequence( weights=weights, ordinals=dna_sequence )