caskade package#
Submodules#
caskade.backend module#
Backend abstraction for array operations.
Provides a unified Backend class that delegates array creation and
manipulation to one of three libraries: torch, jax, or numpy.
A module-level backend instance is created on import and serves as the
primary interface for users.
- class caskade.backend.Backend(backend=None)[source]#
Bases:
objectUnified interface for array operations across torch, jax, and numpy.
Provides a single API for creating and manipulating arrays regardless of the underlying library. Methods such as
make_array,concatenate,to,sigmoid, andlogitare dynamically bound when the backend is set, delegating to the appropriate library-specific implementation.- Parameters:
backend (str, optional) – Backend name:
"torch","jax", or"numpy". IfNone, reads from theCASKADE_BACKENDenvironment variable, defaulting to"torch".
Examples
Use the module-level
backendinstance to switch backends:from caskade import backend backend.backend = "numpy" arr = backend.make_array([1.0, 2.0, 3.0])
- all(array)[source]#
Test whether all elements evaluate to
True.- Parameters:
array (ArrayLike) – Input array.
- Returns:
Scalar result;
Trueif every element is non-zero.- Return type:
ArrayLike
- any(array)[source]#
Test whether any element evaluates to
True.- Parameters:
array (ArrayLike) – Input array.
- Returns:
Scalar result;
Trueif any element is non-zero.- Return type:
ArrayLike
- property array_type#
The array class for the active backend.
Returns
torch.Tensor,jax.numpy.ndarray, ornumpy.ndarraydepending on the current backend. Useful forisinstancechecks.- Returns:
The array class used by the active backend.
- Return type:
type
Examples
isinstance(my_array, backend.array_type)
- Type:
type
- property backend#
Name of the active backend (
"torch","jax", or"numpy").- Type:
str
- exp(array)[source]#
Compute the exponential element-wise.
- Parameters:
array (ArrayLike) – Input array.
- Returns:
Element-wise exponential of the input.
- Return type:
ArrayLike
caskade.base module#
- class caskade.base.Node(name: str | None = None, link: Node | tuple[Node] | None = None, description: str = '')[source]#
Bases:
objectBase graph node class for
caskadeobjects.The
Nodeobject is the base class for allcaskadeobjects. It is used to construct the directed acyclic graph (DAG). The primary function of theNodeobject is to manage the parent-child relationships between nodes in the graph. There is limited functionality for theNodeobject, though it implements the base versions of theactivestate andto/update_graphmethods. Theactivestate is used to communicate through the graph that the simulator is currently running. Thetomethod is used to move and/or cast the values of the parameter. Theupdate_graphmethod is used signal all parents that the graph below them has changed.Examples
Example making some
Nodeobjects and then linking/unlinking them:n1 = Node() n2 = Node() n1.link("subnode", n2) # link n2 as a child of n1, may use any str as the key n1.unlink("subnode") # alternately n1.unlink(n2) to unlink by object
- property active: bool#
Trueif the node is currently in an active simulation run.- Type:
bool
- add_memo(memo)[source]#
Add a memo string and propagate it to all children.
- Parameters:
memo (str) – The memo message to add. Children in
subgraphsreceive the memo with the child name appended (memo|child_name).
- append_state(saveto: str | File)[source]#
Append the current state to an existing HDF5 file.
The file must have been previously created by
save_statewithappendable=True. The graph structure in the file is verified before appending.- Parameters:
saveto (str or File) – Path to an HDF5 file (
'.h5'or'.hdf5') or an open HDF5Fileobject.- Raises:
GraphError – If the graph structure no longer matches the file.
NotImplementedError – If the file path does not end with a supported extension.
- graph_dict() dict[str, dict][source]#
Return a nested dictionary representation of the graph.
Each key is a string of the form
"name|node_type"and the value is a dict containing the same structure for that node’s children.- Returns:
Nested dictionary mirroring the DAG hierarchy.
- Return type:
dict[str, dict]
- graph_print(dag: dict, depth: int = 0, indent: int = 4, result: str = '') str[source]#
Recursively render a graph dictionary as an indented string.
- Parameters:
dag (dict[str, dict]) – A nested dictionary as returned by
graph_dict.depth (int, optional) – Current indentation depth (used during recursion). Defaults to
0.indent (int, optional) – Number of spaces per indentation level. Defaults to
4.result (str, optional) – Accumulator string (used during recursion). Defaults to
"".
- Returns:
A human-readable, indented representation of the graph.
- Return type:
str
- graphviz(saveto: str | None = None) graphviz.Digraph[source]#
Return a graphviz
Digraphrepresenting the DAG below this node.- Parameters:
saveto (str, optional) – If provided, save the rendered graph to this file path. The file extension determines the output format (e.g.
'.pdf','.png'). Defaults toNone.- Returns:
The constructed directed-graph object.
- Return type:
graphviz.Digraph
- property graphviz_style#
- hierarchical_link(key: str, child: Node)[source]#
Link the current
Nodeobject to anotherNodeobject as a child in a hierarchical manner. See link for more detail on linking. A hierarchical link will allow batching internally to the simulator.- Parameters:
key (str) – The key to link the child node with.
child (Node) – The child
Nodeobject to link to.
Examples
parent = Node(name="parent") child = Node(name="child") parent.hierarchical_link("child", child)
- link(key: str | tuple | Node, child: Node | tuple | None = None)[source]#
Link the current
Nodeobject to anotherNodeobject as a child.- Parameters:
key ((Union[str, Node])) – The key to link the child node with. This will also become the attribute to access the child node. After linking you will have node.key == child
child ((Optional[Node], optional)) – The child
Nodeobject to link to. Defaults to None in which case the key is used as the child and the child.name is used as the key.
Examples
Example making some
Nodeobjects and then linking/unlinking them, demonstrating multiple ways to link/unlink:n1 = Node() n2 = Node() n1.link("subnode", n2) # may use any str as the key n1.unlink("subnode") # Alternatively, link by object n1.link(n2) n1.unlink(n2)
- load_state(loadfrom: str | File, index: int = -1, **kwargs)[source]#
Load node state (and children) from an HDF5 file.
- Parameters:
loadfrom (str or File) – Path to an HDF5 file (
'.h5'or'.hdf5') or an open HDF5Fileobject.index (int, optional) – Sample index to load when the file was saved in appendable mode. Defaults to
-1(last sample).**kwargs – Additional keyword arguments forwarded to
h5py.File(e.g.driver).
- Raises:
GraphError – If the graph structure no longer matches the file.
NotImplementedError – If the file path does not end with a supported extension.
- property memos: set[str]#
Current set of memo strings held by this node.
- Type:
set[str]
- property name: str#
The name of this node.
- Type:
str
- property node_str#
- property online: bool#
Trueif the node is online within a hierarchical sub-graph.- Type:
bool
- remove_memo(memo)[source]#
Remove a memo string and propagate removal to all children.
- Parameters:
memo (str) – The memo message to remove. The same propagation rules as
add_memoapply.
- save_state(saveto: str | File, appendable: bool = False)[source]#
Save the state of the node and its children, currently only works for HDF5 file types (.h5 and .hdf5).
The “state” of a node is considered to be the value of its params, however it is also possible to save other attributes of the node by adding them to the Node.saveattrs set. Simply call Node.saveattrs.add(‘attribute’) and then Node.attribute will be saved if possible. The HDF5 file will be created with the same structure as the graph, even if there are multiple paths to the same node. For example if N1 has children N2 and N3, and both N2 and N3 have the child N4, the HDF5 file will reflect this. It will be possible to find the N4 params under both ‘N1/N2/N4’ and ‘N1/N3/N4’ if inspecting the HDF5 file manually. Specifically, if N4 has the param P1 then you could access its value like this:
If the save had been set as appendable, then the value will have an extra dimension for the number of samples, this will always be the first dimension. If appendable was false then the value will simply equal the param value.
Note
You need the optional h5py package installed to use this method.
- Parameters:
saveto ((Union[str, File])) – The file to save the state to. If a string, it should be the path to an HDF5 file (ending in ‘.h5’ or ‘.hdf5’). If a File object, it should be an open HDF5 file.
appendable ((bool, optional)) – Whether to save the state in an appendable format. If True, the values will have an extra dimension for the number of samples. Defaults to False.
- to(device=None, dtype=None)[source]#
Moves and/or casts the values of the
Nodeto a particular device and/or dtype.- Parameters:
device ((optional)) – The device to move the values to. Defaults to None.
dtype ((optional)) – The desired data type. Defaults to None.
- topological_ordering() tuple[Node][source]#
Return a topological ordering of the graph below the current node.
Performs a recursive depth-first search with post-order traversal to resolve dependencies. The result starts with this node and proceeds to its descendants in dependency order.
- Returns:
All nodes reachable from (and including) this node, ordered so that every parent appears before its children.
- Return type:
tuple[Node]
- unlink(key: str | Node | list | tuple | None = None)[source]#
Unlink one or more
Nodeobjects from thisNode.- Parameters:
key ((str, Node, list, tuple, or None, optional)) – The key,
Nodeobject, or collection of keys/nodes to unlink. If a string, the child with that key is unlinked. If aNodeobject, the matching child is located and unlinked. If a list or tuple, each element is unlinked in turn. IfNone(the default), all children are unlinked.- Raises:
GraphError – If the graph is currently active.
caskade.collection module#
- class caskade.collection.NodeCollection(name: str | None = None, link: Node | tuple[Node] | None = None, description: str = '')[source]#
Bases:
Node,GetSetValuesBase mixin for collections of nodes that track parameters.
Provides shared functionality for traversing, querying, and converting parameters within a graph of nodes. Subclasses such as
NodeTupleandNodeListcombine this mixin with a standard Python sequence type.- property dynamic#
Whether any node in this collection has dynamic parameters.
- Returns:
Trueif at least one contained node is dynamic.- Return type:
bool
- property dynamic_param_groups: tuple[int]#
Sorted unique group identifiers of all dynamic parameters.
- Returns:
Sorted group indices present among the dynamic parameters.
- Return type:
tuple of int
- property dynamic_params: tuple[Param]#
All dynamic parameters in the graph below this node.
- Returns:
Dynamic (non-static, non-pointer) parameters found via topological ordering.
- Return type:
tuple of Param
- property pointer_params: tuple[Param]#
All pointer parameters in the graph below this node.
- Returns:
Parameters that act as pointers to other parameters, found via topological ordering.
- Return type:
tuple of Param
- property static#
Whether all nodes in this collection are static.
- Returns:
Trueif no contained node is dynamic.- Return type:
bool
- property static_params: tuple[Param]#
All static parameters in the graph below this node.
- Returns:
Static (non-dynamic, non-pointer) parameters found via topological ordering.
- Return type:
tuple of Param
- class caskade.collection.NodeDict(mapping=None, name=None)[source]#
Bases:
NodeCollection,dictMutable, keyed collection of nodes.
Behaves like a standard
dictbut also participates in the caskade node graph. All elements must beNodeinstances. Graph links are automatically updated whenever the dict is modified.- Parameters:
mapping (mapping of str to Node, optional) – Nodes to include in the dict. Defaults to an empty dict.
name (str, optional) – Human-readable name for this collection of nodes.
- property dynamic#
Whether any node in this collection has dynamic parameters.
- Returns:
Trueif at least one contained node is dynamic.- Return type:
bool
- property graphviz_style#
- popitem()[source]#
Remove and return an arbitrary (key, node) pair from the dict (the last one inserted) and update graph links.
- class caskade.collection.NodeList(iterable=(), name=None)[source]#
Bases:
NodeCollection,listMutable, ordered collection of nodes.
Behaves like a standard
listbut also participates in the caskade node graph. All elements must beNodeinstances. Graph links are automatically updated whenever the list is modified.- Parameters:
iterable (iterable of Node, optional) – Nodes to include in the list. Defaults to an empty iterable.
name (str, optional) – Human-readable name for this collection node.
- property graphviz_style#
- class caskade.collection.NodeTuple(iterable=None, name=None)[source]#
Bases:
NodeCollection,tupleImmutable, ordered collection of nodes.
Behaves like a standard
tuplebut also participates in the caskade node graph. All elements must beNodeinstances and are automatically linked as children upon construction.- Parameters:
iterable (iterable of Node, optional) – Nodes to include in the tuple.
name (str, optional) – Human-readable name for this collection node.
- property graphviz_style#
caskade.context module#
- class caskade.context.ActiveContext(module: Module)[source]#
Bases:
objectContext manager to activate a module for a simulation.
Only inside an
ActiveContextis it possible to fill or clear the dynamic and live parameters. On entry, the module is marked as active (or its current parameter state is saved if already active). On exit, the state is restored.- Parameters:
module (Module) – The module to activate for the duration of the context.
- Raises:
ActiveStateError – If the module is already running a simulation (
module.onlineisTrue).
Examples
Activate a module, fill parameters, and run a forward pass:
with ActiveContext(my_module): my_module.fill_params(params) result = my_module.my_forward(x)
- class caskade.context.OverrideParam(param: Param, value)[source]#
Bases:
objectContext manager to override a parameter value.
Only inside an
OverrideParamwill the parameter be set to the new value. The original value (and the values of any parent pointer parameters) are saved on entry and restored on exit.- Parameters:
param (Param) – The parameter whose value should be temporarily overridden.
value (object) – The temporary value to assign to param.
Examples
Override a parameter inside a
@forwardmethod so that it usesnew_valueregardless of what was passed viaparams:class MySim(Module): def __init__(self): super().__init__() self.a = Param("a", None) self.b = Param("b", None) @forward def __call__(self, x, a=None, b=None): with OverrideParam(self.b, 5.0): # b will always be 5.0 here, ignoring params return x + a + self.b.value
- class caskade.context.ValidContext(module: Module)[source]#
Bases:
objectContext manager that transforms parameter values to an unconstrained space.
Inside a
ValidContext, all parameter values are automatically mapped into the range(-inf, inf)via each parameter’sto_valid/from_validtransformations. This is useful when interfacing with samplers or optimizers that expect unconstrained parameters—any value they propose will be mapped back into the parameter’s original valid range on exit.- Parameters:
module (Module) – The module whose parameters should be transformed.
Examples
Get unconstrained parameter values for use with an optimizer:
with ValidContext(my_module): unconstrained_params = my_module.get_values() # unconstrained_params live in (-inf, inf)
caskade.decorators module#
- class caskade.decorators.active_cache(func)[source]#
Bases:
objectCaches the first evaluated result of a Module method for the duration of a simulation.
This decorator ensures that an expensive method is executed exactly once per active simulation run. Once calculated, subsequent calls to the decorated method will return the stored value, ignoring any arguments passed to it.
Warning
If the method is called multiple times with different arguments in one simulation, the cached result will still be returned, which may lead to unexpected behavior. Use with caution!
Notes
If you are stacking multiple decorators on a method (such as
@forwardor@jax.jit),@active_cacheMUST be the outermost (top) decorator.Examples
class FluxModel(Module): def __init__(self, nodes, x, M): super().__init__() self.nodes = nodes self.x = Param("x", x) self.M = Param("M", M) @active_cache @jax.jit # Notice active_cache is placed at the top @forward def compute_intrinsic_sed(self, w, x, M): print("Computing SED...") return jnp.interp(w, self.nodes, x * M) @forward def compute_flux(self, wavelengths): sed = self.compute_intrinsic_sed(wavelengths) # Cached after first call flux = jnp.sum(sed) sed = self.compute_intrinsic_sed(wavelengths) # Returns cached result, no print peak = jnp.max(sed) return flux, peak model = FluxModel(np.linspace(400, 700, 10), x=1.0, M=np.random.rand(10)) # Compute flux only calls compute_intrinsic_sed once due to caching flux, peak = model.compute_flux(wavelengths)
- caskade.decorators.forward(method)[source]#
Decorator to define a forward method for a module.
Manages parameter passing and activation for the decorated method. When called, it automatically fills keyword arguments from the module’s
Paramchildren and handles parameter overrides and active context.- Parameters:
method ((Callable)) – The forward method to be decorated.
- Returns:
The decorated forward method.
- Return type:
Callable
Examples
Standard usage of the forward decorator:
class ExampleSim(Module): def __init__(self, a, b, c): super().__init__("example_sim") self.a = a self.b = Param("b", b) self.c = Param("c", c) @forward def example_func(self, x, b=None): return x + self.a + b E = ExampleSim(a=1, b=None, c=3) print(E.example_func(4, params=[5])) # Output: 10
caskade.errors module#
- exception caskade.errors.ActiveStateError[source]#
Bases:
CaskadeExceptionException for active-state errors in
caskade.Raised when an operation requires a node to be in a particular active state (enabled or disabled) and that condition is not met.
- exception caskade.errors.BackendError[source]#
Bases:
CaskadeExceptionException for backend-related errors in
caskade.Raised when the selected numerical backend encounters an unsupported operation or configuration issue.
- exception caskade.errors.CaskadeException[source]#
Bases:
ExceptionBase class for all exceptions in
caskade.All custom exceptions raised by
caskadeinherit from this class, allowing users to catch anycaskade-specific error with a single except clause.
- exception caskade.errors.FillParamsArrayError(name, input_params, params)[source]#
Bases:
FillParamsErrorException raised when filling parameters with an array fails.
Raised when the shape of the input array does not match the total number of flattened parameters registered on a node.
- Parameters:
name (str) – Name of the node whose parameters are being filled.
input_params (ArrayLike) – The input array that was provided.
params (tuple of Param) – Registered parameters whose shapes are compared against the input.
- exception caskade.errors.FillParamsError[source]#
Bases:
CaskadeExceptionBase exception for errors when filling parameters in
caskade.Raised when the input data provided to fill node parameters is invalid. Subclasses handle specific input types (array, sequence, mapping).
- exception caskade.errors.FillParamsMappingError(name, children, missing_key=None)[source]#
Bases:
FillParamsErrorException raised when filling parameters with a mapping fails.
Raised when a key in the input dictionary does not correspond to any registered child node.
- Parameters:
name (str) – Name of the node whose parameters are being filled.
children (dict) – Dictionary of registered child nodes.
missing_key (str, optional) – The key from the input mapping that was not found among the node’s children.
- exception caskade.errors.FillParamsSequenceError(name, input_params, dynamic_params)[source]#
Bases:
FillParamsErrorException raised when filling parameters with a sequence fails.
Raised when the length of the input sequence does not match the number of dynamic parameters registered on a node.
- Parameters:
name (str) – Name of the node whose parameters are being filled.
input_params (sequence) – The input sequence (list, tuple, etc.) that was provided.
dynamic_params (tuple of Param) – Registered dynamic parameters expected by the node.
- exception caskade.errors.GraphError[source]#
Bases:
CaskadeExceptionException for graph-related errors in
caskade.Raised when an operation on the computational graph is invalid, such as creating cycles or referencing nonexistent nodes.
- exception caskade.errors.LinkToAttributeError[source]#
Bases:
GraphErrorException raised when linking to an attribute fails.
Raised when an attempt is made to create a link to a node attribute that does not exist or is not a valid link target.
- exception caskade.errors.NodeConfigurationError[source]#
Bases:
CaskadeExceptionException for node configuration errors in
caskade.Raised when a node is configured with invalid or incompatible settings.
- exception caskade.errors.ParamConfigurationError[source]#
Bases:
NodeConfigurationErrorException for parameter configuration errors in
caskade.Raised when a parameter is defined with an invalid shape, type, or constraint.
- exception caskade.errors.ParamTypeError[source]#
Bases:
CaskadeExceptionException for parameter type errors in
caskade.Raised when a value assigned to a parameter does not match its expected type.
caskade.mixins module#
- class caskade.mixins.GetSetValues[source]#
Bases:
objectMixin providing methods for getting and setting parameter values.
Provides array, list, and dict interfaces for reading and writing dynamic (or static) parameter values on a
ModuleorNodeCollection. Also includes helpers for locating parameters by index and for converting between raw and valid (transformed) parameter spaces.- find_index(param: Param | tuple[Param] | Module, scheme: str = 'array') int | slice[source]#
Identify what index is associated with a param in the dynamic params array.
- Parameters:
- Returns:
param_info – A int giving the index associated with the provided Param object. If the param is multi-dimensional then the result will be a slice over all indices associated with that param.
- Return type:
Union[int, slice]
- find_param(idx: int | tuple[int], group: int | None = None, scheme: str = 'array') tuple[Param, tuple[int]][source]#
Identify which param is associated with the provided index in the dynamic params array.
- Parameters:
idx (Union[int, tuple[int]]) – The index in the params array at which we wish to find the associated param.
group (Optional[int]) – If the dynamic params have multiple group values, then this argument specifies which group to check.
scheme (str) – Whether to search the array (default) params or list version of params. dict is currently unsupported.
- Returns:
param_info – A tuple with the Param object and the index within the Param value associated with idx (empty tuple if scalar). If idx is a tuple then the result is a tuple of these results.
- Return type:
tuple[Param, tuple[int]]
- from_valid(valid_params: ArrayLike | Sequence | Mapping, param_list: tuple[Param] | None = None, group: int | None = None) ArrayLike | Sequence | Mapping[source]#
Map parameter values from the unconstrained space back to their natural range.
Takes values in the unconstrained domain
(-inf, inf)(as produced byto_valid()or proposed by an optimizer/sampler) and maps them back into each parameter’s original valid range (e.g. 0-1 for an axis ratio).- Parameters:
valid_params (Union[ArrayLike, Sequence, Mapping]) – Parameter values in the unconstrained
(-inf, inf)domain, in any supported format (array, sequence, or mapping).param_list (tuple of Param or None, optional) – Subset of parameters to transform. Defaults to all dynamic parameters.
group (int or None, optional) – Restrict to a specific parameter group. When
Noneand multiple groups exist, all groups are transformed.
- Returns:
Inverse-transformed values in the same format as valid_params.
- Return type:
Union[ArrayLike, Sequence, Mapping]
- get_values(scheme: str = 'array', dynamic: bool = True, attribute: str | Callable = 'value', group: int | None = None, respect_valid: bool = True) ArrayLike | list[ArrayLike] | dict[str, dict | ArrayLike][source]#
Retrieve parameter values from the module.
- Parameters:
scheme (str, optional) –
Output format, one of
"array"(default),"list", or"dict"."array"/"tensor"- returns a single flat array with all parameter values concatenated along the last axis."list"- returns a list of raw parameter values."dict"- returns a nested dictionary mirroring the graph structure.
dynamic (bool, optional) – If
True(default), retrieves dynamic parameters; otherwise retrieves static parameters.attribute (Union[str, Callable], optional) – The
Paramattribute to read from, by default"value".group (int or None, optional) – Restrict to a specific parameter group. When
None(default) and multiple groups exist, returns a list of per-group results.respect_valid (bool, optional) – If
True(default), will apply to_valid transformation.
- Returns:
Parameter values in the format specified by scheme. When multiple groups exist and group is
None, a list of per-group results is returned.- Return type:
Union[ArrayLike, list[ArrayLike], dict[str, Union[dict, ArrayLike]]]
- set_values(params: ArrayLike | Sequence | Mapping, dynamic: bool = True, attribute: str = 'value', respect_valid: bool = True)[source]#
Fill parameter values of the module from the provided data.
- Parameters:
params (Union[ArrayLike, Sequence, Mapping]) –
Values to assign to the parameters. Accepted formats:
ArrayLike - a flat (or batched) array whose last dimension is concatenated parameter values in topological order.
Sequence - one element per parameter, matched by position.
Mapping - keys matching child names, values being the parameter data (may be nested).
When multiple dynamic parameter groups exist,
paramsshould be a sequence of per-group containers.dynamic (bool, optional) – If
True(default), sets dynamic parameters; otherwise sets static parameters.attribute (str, optional) – The
Paramattribute to write to, by default"value".respect_valid (bool, optional) – If
True(default), will apply from_valid transformations before assignment.
- Raises:
ActiveStateError – If the module is currently in an active (tracing) state.
- to_valid(params: ArrayLike | Sequence | Mapping, param_list: tuple[Param] | None = None, group: int | None = None) ArrayLike | Sequence | Mapping[source]#
Map parameter values from their natural range to an unconstrained space.
Takes parameter values that lie within each parameter’s valid range (e.g. 0-1 for an axis ratio) and maps them into the unconstrained domain
(-inf, inf). The inverse mappingfrom_valid()will map any value in(-inf, inf)back into the original valid range. This is useful for interfacing with samplers and optimizers that require unconstrained parameters.- Parameters:
params (Union[ArrayLike, Sequence, Mapping]) – Raw parameter values in any supported format (array, sequence, or mapping).
param_list (tuple of Param or None, optional) – Subset of parameters to transform. Defaults to all dynamic parameters.
group (int or None, optional) – Restrict to a specific parameter group. When
Noneand multiple groups exist, all groups are transformed.
- Returns:
Transformed values in the same format as params.
- Return type:
Union[ArrayLike, Sequence, Mapping]
- property valid_context: bool#
Return True if the module is in a valid context.
caskade.module module#
- class caskade.module.Module(name: str | None = None, **kwargs)[source]#
Bases:
Node,GetSetValuesNode to represent a simulation module in the graph.
The
Moduleobject is used to represent a simulation module in the graph. These are python objects that contain the calculations for a simulation, they also hold theParamobjects that are used in the calculations. TheModuleobject has additional functionality to manage theParamobjects below it in the graph, it keeps track of alldynamicParamobjects so that at runtime their values may be filled. TheModuleobject manages its links to other nodes through attributes of the class.Examples
Example of a nested pair of
Moduleobjects and how their@forwardmethods are called:class MySim(Module): def __init__(self, a, b=None): super().__init__() self.a = a self.b = Param("b", b) @forward def myfunc(self, x, b=None): return x * self.a.otherfun(x) + b class OtherSim(Module): def __init__(self, c=None): super().__init__() self.c = Param("c", c) @forward def otherfun(self, x, c = None): return x + c othersim = OtherSim() mysim = MySim(a=othersim) # b c params = [torch.tensor([1.0, 2.0]), torch.tensor([3.0, 4.0])] result = mysim.myfunc(3.0, params=params) # result is tensor([19.0, 23.0])
- property all_params#
All parameters below this module in the DAG.
- Returns:
Concatenation of static, dynamic, and pointer parameters.
- Return type:
tuple of Param
- clear_state()[source]#
Clear the active state _value for all params below this Module in the DAG. This should not be used by a user under normal circumstances.
- property dynamic: bool#
Return True if the module has dynamic parameters as direct children.
- Returns:
True if any direct children are dynamic parameters.
- Return type:
bool
- fill_kwargs(keys: tuple[str]) dict[str, ArrayLike][source]#
Fill the kwargs for an
@forwardmethod with the values of the dynamic parameters. The requested keys are matched to names ofParamobjects owned by theModule. This should not be used by the user under normal circumstances.
- fill_params(params: ArrayLike | Sequence | Mapping, dynamic=True)[source]#
Fill the dynamic/static parameters of the module with the input values from params.
- Parameters:
params ((Union[ArrayLike, Sequence, Mapping])) – The input values to fill the dynamic parameters with. The input can be an ArrayLike, a Sequence, or a Mapping.
dynamic (bool) – Operate on dynamic parameters (True, default) or static parameters (False).
- property graphviz_style#
- property node_str: str#
Returns a string representation of the node for graph visualization.
- param_order()[source]#
Return a human-readable string of dynamic parameter ordering.
Each line corresponds to a parameter group and lists the parameters in the format
parent_name: param_name.- Returns:
Multi-line string describing the dynamic parameter order.
- Return type:
str
- remove_memo(memo)[source]#
Remove a memo string and propagate removal to all children.
- Parameters:
memo (str) – The memo message to remove. The same propagation rules as
add_memoapply.
- property static: bool#
Return True if the module has no dynamic parameters as direct children.
- Returns:
True if none of the direct children are dynamic parameters.
- Return type:
bool
- to_dynamic(children_only=True)[source]#
Change all parameters to dynamic parameters.
- Parameters:
children_only ((bool, optional)) – If True, only convert the children of this module to dynamic. If False, convert all parameters in the graph below this module. Defaults to True.
caskade.param module#
- class caskade.param.Param(name: str, value: ArrayLike | float | int | None = None, shape: tuple[int, ...] | None = None, cyclic: bool = False, valid: tuple[ArrayLike | float | int | None] | None = None, units: str | None = None, dynamic: bool | None = None, group: int = 0, batch_shape: tuple[int] | None = None, dtype: Any | None = None, device: Any | None = None, **kwargs)[source]#
Bases:
NodeNode to represent a parameter in the graph.
The
Paramobject is used to represent a parameter in the graph. During runtime this will represent a value which can be used in various calculations. TheParamobject can be set to a constant value (static);Nonemeaning the value is to be provided at runtime (dynamic); anotherParamobject meaning it will take on that value at runtime (pointer); or a function of otherParamobjects to be computed at runtime (alsopointer, see user guides). These options allow users to flexibly set the behavior of the simulator.Examples
Example making some
Paramobjects:p1 = Param("test", (1.0, 2.0)) # constant value, length 2 vector p2 =Param("p2", None, (2,2)) # dynamic 2x2 matrix value p3 = Param("p3", p1) # pointer to another parameter p4 = Param("p4", lambda p: p.children["other"].value * 2) # arbitrary function of another parameter p5 = Param("p5", valid=(0.0,2*pi), units="radians", cyclic=True) # parameter with metadata
- Parameters:
name ((str)) – The name of the parameter.
value ((Optional[Union[ArrayLike, float, int]], optional)) – The value of the parameter. Defaults to None meaning dynamic.
shape ((Optional[tuple[int, ...]], optional)) – The shape of the parameter. Defaults to () meaning scalar.
cyclic ((bool, optional)) – Whether the parameter is cyclic, imposing periodic boundary conditions. Such as a rotation from 0 to 2pi. Defaults to False.
valid ((Optional[tuple[Union[ArrayLike, float, int, None]]], optional)) – The valid range of the parameter. Defaults to None meaning all of -inf to inf is valid.
units ((Optional[str], optional)) – The units of the parameter. Defaults to None.
dynamic ((bool, optional)) – Force param to be dynamic if True. If a value is provided and param is dynamic then it has a default value at call time.
(bool (batched) – If True, the param is assumed batched and the shape may now take the form (*B, *D) where *D is the shape of the value.
optional) – If True, the param is assumed batched and the shape may now take the form (*B, *D) where *D is the shape of the value.
dtype ((Optional[Any], optional)) – The data type of the parameter. Defaults to None meaning the data type will be inferred from the value.
device ((Optional[Any], optional)) – The device of the parameter. Defaults to None meaning the device will be inferred from the value.
- property batch_shape: tuple[int, ...]#
The batch dimensions of the parameter value.
Batch dimensions are the leading dimensions of the value that precede the event
shape. If an explicit batch shape was set it is returned directly; otherwise it is inferred from the value.- Returns:
The batch shape, or
()if the parameter is not batched.- Return type:
tuple of int
- property batched: bool#
Whether this parameter carries batch dimensions.
- Returns:
Trueifbatch_shapeis non-empty.- Return type:
bool
- property cyclic: bool#
Whether the parameter has cyclic (periodic) boundary conditions.
When
True, values wrap around thevalidrange (e.g. an angle from 0 to 2π).- Returns:
Trueif the parameter is cyclic.- Return type:
bool
- property device: str | None#
The device on which the parameter value resides.
If no explicit device was set, the device is inferred from the current value.
- Returns:
The device, or
Noneif unknown.- Return type:
device or None
- property dtype: str | None#
The data type of the parameter value.
If no explicit dtype was set, the dtype is inferred from the current value.
- Returns:
The data type, or
Noneif unknown.- Return type:
dtype or None
- property dynamic: bool#
Whether this parameter is dynamic.
- Returns:
Trueif the parameter’s value is provided at runtime.- Return type:
bool
- property graphviz_style#
- property group: int#
The group index of this parameter.
Parameters that share the same group index are collected together into a single
paramsobject when calling a simulator’s@forwardmethod, as well as when usingget_valuesorset_values.- Returns:
The group index (default
0).- Return type:
int
- is_valid(value=None) bool[source]#
Check whether a value lies within the allowed range.
- Parameters:
value (ArrayLike or None, optional) – The value to check. If
None(default), the parameter’s current value is used.- Returns:
Trueif the value is within the valid range or if no constraints are set.Falseotherwise; a warning is also emitted.- Return type:
bool
- property node_str: str#
Returns a string representation of the node for graph visualization.
- property node_type#
The current type of this parameter node.
- Returns:
One of
"static","dynamic", or"pointer".- Return type:
str
- property npvalue: ndarray#
The current value converted to a NumPy array.
- Returns:
The value as a NumPy
ndarray.- Return type:
numpy.ndarray
- property pointer: bool#
Whether this parameter is a pointer.
- Returns:
Trueif the parameter points to anotherParamor a callable that is evaluated at runtime.- Return type:
bool
- property shape: tuple[int, ...]#
The event (non-batch) shape of the parameter value.
Wildcard dimensions (
None) in the declared shape are resolved using the current value. If no shape was declared, the shape of the current value is returned directly.- Returns:
The resolved shape of the parameter.
- Return type:
tuple of int
- property static: bool#
Whether this parameter is static.
- Returns:
Trueif the parameter holds a fixed value that does not change at runtime.- Return type:
bool
- to(device=None, dtype=None) Param[source]#
Moves and/or casts the values of the parameter.
- Parameters:
device ((optional)) – The device to move the values to. Defaults to None.
dtype ((optional)) – The desired data type. Defaults to None.
- to_dynamic(value=<object object>)[source]#
Change this parameter to a dynamic parameter.
If a value is provided, it is stored as the default dynamic value. When called without arguments the existing value (if any) is kept.
- Parameters:
value (ArrayLike, float, int, None, or sentinel, optional) – The default value for the dynamic parameter. Must not be a
Paramor callable. By default the current value is retained.- Raises:
ActiveStateError – If the parameter is currently active.
ParamTypeError – If value is a
Paramor callable.ParamConfigurationError – If the value shape does not match the declared shape.
- to_pointer(value, link=())[source]#
Change this parameter to a pointer parameter.
The parameter’s value will be computed at runtime by dereferencing another
Paramor by calling a user-supplied function.- Parameters:
- Raises:
ActiveStateError – If the parameter is currently active.
ParamTypeError – If value is not a
Paramor callable.
- to_static(value=<object object>)[source]#
Change this parameter to a static parameter.
If a value is provided, it is stored as the fixed static value. When called without arguments the existing value (if any) is kept.
- Parameters:
value (ArrayLike, float, int, None, or sentinel, optional) – The constant value for the static parameter. Must not be a
Paramor callable. By default the current value is retained.- Raises:
ActiveStateError – If the parameter is currently active.
ParamTypeError – If value is a
Paramor callable.ParamConfigurationError – If the value shape does not match the declared shape.
- property valid: tuple[ArrayLike | None, ArrayLike | None]#
The valid range of the parameter value.
- Returns:
(lower_bound, upper_bound). Either bound may beNoneindicating no constraint on that side.- Return type:
tuple of (ArrayLike or None, ArrayLike or None)
- property value: ArrayLike | None#
The current value of the parameter.
For static and dynamic parameters the stored value is returned. For pointer parameters the linked callable is evaluated. During an active simulation the result is cached.
- Returns:
The parameter value, or
Noneif no value has been set.- Return type:
ArrayLike or None
- caskade.param.valid_shape(batch_shape, shape, value_shape)[source]#
Check whether a value’s shape is compatible with a parameter’s shape.
Validates that
value_shapeis consistent with the declaredshapeand optionalbatch_shape. Dimensions set toNoneinshapeact as wildcards and match any size.- Parameters:
batch_shape (tuple of int or None) – Leading batch dimensions, or
Noneif the parameter is not batched.shape (tuple of int or None, or None) – Expected event dimensions. Individual entries may be
None(wildcard). If the entire argument isNone, any shape is accepted.value_shape (tuple of int) – The actual shape of the value to validate.
- Returns:
Trueif the shapes are compatible,Falseotherwise.- Return type:
bool
caskade.tests module#
caskade.utils module#
- caskade.utils.broadcast_cat_jax(arrays, dim=-1)[source]#
Concatenates JAX arrays with broadcasting.
Behaves like jnp.concatenate, but first broadcasts the arrays to match on all dimensions EXCEPT the concatenation dimension.
- Parameters:
arrays (sequence of jnp.ndarray) – Arrays to concatenate.
dim (int) – The dimension along which to concatenate.
- Returns:
The concatenated array.
- Return type:
jnp.ndarray
- caskade.utils.broadcast_cat_numpy(arrays, dim=-1)[source]#
Concatenates NumPy arrays with broadcasting.
Behaves like np.concatenate, but first broadcasts the arrays to match on all dimensions EXCEPT the concatenation dimension.
- Parameters:
arrays (sequence of np.ndarray) – Arrays to concatenate.
dim (int) – The dimension along which to concatenate.
- Returns:
The concatenated array.
- Return type:
np.ndarray
- caskade.utils.broadcast_cat_torch(tensors, dim=-1)[source]#
Concatenates tensors with broadcasting.
It behaves like torch.cat, but first broadcasts the tensors to match on all dimensions EXCEPT the concatenation dimension.
- Parameters:
tensors (sequence of Tensors) – Tensors to concatenate.
dim (int) – The dimension along which to concatenate. Must be a negative index to ensure consistency across tensors of different ranks (e.g., -1 for the last dimension).
- Returns:
The concatenated tensor.
- Return type:
Tensor
caskade.warnings module#
- exception caskade.warnings.CaskadeWarning[source]#
Bases:
WarningBase warning class for
caskade.All custom warnings issued by
caskadeinherit from this class, allowing users to filter or catch anycaskade-specific warning.
- exception caskade.warnings.InvalidValueWarning(name, value, valid)[source]#
Bases:
CaskadeWarningWarning issued when a parameter value is outside its valid range.
Indicates that the assigned value may cause errors or unexpected behavior during computation.
- Parameters:
name (str) – Name of the parameter with the out-of-range value.
value (ArrayLike) – The value that was assigned.
valid (tuple) – A
(lower, upper)tuple defining the valid range, whereNonerepresents negative or positive infinity.
- exception caskade.warnings.SaveStateWarning[source]#
Bases:
CaskadeWarningWarning issued when saving state encounters a non-fatal problem.
Issued when the state serialization completes but with potential data loss or format issues that the user should be aware of.
Module contents#
caskade - Build scientific simulators as directed acyclic graphs.
Caskade provides a framework for constructing modular scientific simulators by composing computational steps into a directed acyclic graph (DAG). It handles parameter management, caching, and context-dependent evaluation.
Main Public API#
Node : Base class for building computational graph nodes. Module : High-level container for assembling simulator components. Param : Declare and manage parameters within nodes. forward : Decorator to define the forward computation of a node. active_cache : Decorator for caching intermediate results. NodeCollection, NodeList, NodeTuple : Collections of nodes. ActiveContext, ValidContext, OverrideParam : Context managers for evaluation. backend : Array backend abstraction (NumPy, PyTorch, etc.). utils : Utility functions.
- class caskade.ActiveContext(module: Module)[source]#
Bases:
objectContext manager to activate a module for a simulation.
Only inside an
ActiveContextis it possible to fill or clear the dynamic and live parameters. On entry, the module is marked as active (or its current parameter state is saved if already active). On exit, the state is restored.- Parameters:
module (Module) – The module to activate for the duration of the context.
- Raises:
ActiveStateError – If the module is already running a simulation (
module.onlineisTrue).
Examples
Activate a module, fill parameters, and run a forward pass:
with ActiveContext(my_module): my_module.fill_params(params) result = my_module.my_forward(x)
- exception caskade.ActiveStateError[source]#
Bases:
CaskadeExceptionException for active-state errors in
caskade.Raised when an operation requires a node to be in a particular active state (enabled or disabled) and that condition is not met.
- exception caskade.BackendError[source]#
Bases:
CaskadeExceptionException for backend-related errors in
caskade.Raised when the selected numerical backend encounters an unsupported operation or configuration issue.
- exception caskade.CaskadeException[source]#
Bases:
ExceptionBase class for all exceptions in
caskade.All custom exceptions raised by
caskadeinherit from this class, allowing users to catch anycaskade-specific error with a single except clause.
- exception caskade.CaskadeWarning[source]#
Bases:
WarningBase warning class for
caskade.All custom warnings issued by
caskadeinherit from this class, allowing users to filter or catch anycaskade-specific warning.
- exception caskade.FillParamsArrayError(name, input_params, params)[source]#
Bases:
FillParamsErrorException raised when filling parameters with an array fails.
Raised when the shape of the input array does not match the total number of flattened parameters registered on a node.
- Parameters:
name (str) – Name of the node whose parameters are being filled.
input_params (ArrayLike) – The input array that was provided.
params (tuple of Param) – Registered parameters whose shapes are compared against the input.
- exception caskade.FillParamsError[source]#
Bases:
CaskadeExceptionBase exception for errors when filling parameters in
caskade.Raised when the input data provided to fill node parameters is invalid. Subclasses handle specific input types (array, sequence, mapping).
- exception caskade.FillParamsMappingError(name, children, missing_key=None)[source]#
Bases:
FillParamsErrorException raised when filling parameters with a mapping fails.
Raised when a key in the input dictionary does not correspond to any registered child node.
- Parameters:
name (str) – Name of the node whose parameters are being filled.
children (dict) – Dictionary of registered child nodes.
missing_key (str, optional) – The key from the input mapping that was not found among the node’s children.
- exception caskade.FillParamsSequenceError(name, input_params, dynamic_params)[source]#
Bases:
FillParamsErrorException raised when filling parameters with a sequence fails.
Raised when the length of the input sequence does not match the number of dynamic parameters registered on a node.
- Parameters:
name (str) – Name of the node whose parameters are being filled.
input_params (sequence) – The input sequence (list, tuple, etc.) that was provided.
dynamic_params (tuple of Param) – Registered dynamic parameters expected by the node.
- exception caskade.GraphError[source]#
Bases:
CaskadeExceptionException for graph-related errors in
caskade.Raised when an operation on the computational graph is invalid, such as creating cycles or referencing nonexistent nodes.
- exception caskade.InvalidValueWarning(name, value, valid)[source]#
Bases:
CaskadeWarningWarning issued when a parameter value is outside its valid range.
Indicates that the assigned value may cause errors or unexpected behavior during computation.
- Parameters:
name (str) – Name of the parameter with the out-of-range value.
value (ArrayLike) – The value that was assigned.
valid (tuple) – A
(lower, upper)tuple defining the valid range, whereNonerepresents negative or positive infinity.
- exception caskade.LinkToAttributeError[source]#
Bases:
GraphErrorException raised when linking to an attribute fails.
Raised when an attempt is made to create a link to a node attribute that does not exist or is not a valid link target.
- class caskade.Memo(module: Node, memo: str)[source]#
Bases:
objectSends a “memo” (a small message) to all nodes below the current one in the graph. This can be used to communicate state changes in the graph with all lower nodes. By default, the message will skip any subgraphs (hierarchical graphs) but this can be changed to ensure all nodes hear the message.
Note that memos are stored as a python set, so duplicates will be merged. Depending on your use case, it may be wise to ensure that your memo is unique.
- Parameters:
module (Module) – The caskade Module object that will propogate the memo
memo (str) – The message to send down the graph
skip_subgraphs (bool) – If True (default) any subgraphs, otherwise known as hierarchical graphs, will not get the memo.
- class caskade.Module(name: str | None = None, **kwargs)[source]#
Bases:
Node,GetSetValuesNode to represent a simulation module in the graph.
The
Moduleobject is used to represent a simulation module in the graph. These are python objects that contain the calculations for a simulation, they also hold theParamobjects that are used in the calculations. TheModuleobject has additional functionality to manage theParamobjects below it in the graph, it keeps track of alldynamicParamobjects so that at runtime their values may be filled. TheModuleobject manages its links to other nodes through attributes of the class.Examples
Example of a nested pair of
Moduleobjects and how their@forwardmethods are called:class MySim(Module): def __init__(self, a, b=None): super().__init__() self.a = a self.b = Param("b", b) @forward def myfunc(self, x, b=None): return x * self.a.otherfun(x) + b class OtherSim(Module): def __init__(self, c=None): super().__init__() self.c = Param("c", c) @forward def otherfun(self, x, c = None): return x + c othersim = OtherSim() mysim = MySim(a=othersim) # b c params = [torch.tensor([1.0, 2.0]), torch.tensor([3.0, 4.0])] result = mysim.myfunc(3.0, params=params) # result is tensor([19.0, 23.0])
- property all_params#
All parameters below this module in the DAG.
- Returns:
Concatenation of static, dynamic, and pointer parameters.
- Return type:
tuple of Param
- clear_state()[source]#
Clear the active state _value for all params below this Module in the DAG. This should not be used by a user under normal circumstances.
- property dynamic: bool#
Return True if the module has dynamic parameters as direct children.
- Returns:
True if any direct children are dynamic parameters.
- Return type:
bool
- fill_kwargs(keys: tuple[str]) dict[str, ArrayLike][source]#
Fill the kwargs for an
@forwardmethod with the values of the dynamic parameters. The requested keys are matched to names ofParamobjects owned by theModule. This should not be used by the user under normal circumstances.
- fill_params(params: ArrayLike | Sequence | Mapping, dynamic=True)[source]#
Fill the dynamic/static parameters of the module with the input values from params.
- Parameters:
params ((Union[ArrayLike, Sequence, Mapping])) – The input values to fill the dynamic parameters with. The input can be an ArrayLike, a Sequence, or a Mapping.
dynamic (bool) – Operate on dynamic parameters (True, default) or static parameters (False).
- property graphviz_style#
- property node_str: str#
Returns a string representation of the node for graph visualization.
- param_order()[source]#
Return a human-readable string of dynamic parameter ordering.
Each line corresponds to a parameter group and lists the parameters in the format
parent_name: param_name.- Returns:
Multi-line string describing the dynamic parameter order.
- Return type:
str
- remove_memo(memo)[source]#
Remove a memo string and propagate removal to all children.
- Parameters:
memo (str) – The memo message to remove. The same propagation rules as
add_memoapply.
- property static: bool#
Return True if the module has no dynamic parameters as direct children.
- Returns:
True if none of the direct children are dynamic parameters.
- Return type:
bool
- to_dynamic(children_only=True)[source]#
Change all parameters to dynamic parameters.
- Parameters:
children_only ((bool, optional)) – If True, only convert the children of this module to dynamic. If False, convert all parameters in the graph below this module. Defaults to True.
- class caskade.Node(name: str | None = None, link: Node | tuple[Node] | None = None, description: str = '')[source]#
Bases:
objectBase graph node class for
caskadeobjects.The
Nodeobject is the base class for allcaskadeobjects. It is used to construct the directed acyclic graph (DAG). The primary function of theNodeobject is to manage the parent-child relationships between nodes in the graph. There is limited functionality for theNodeobject, though it implements the base versions of theactivestate andto/update_graphmethods. Theactivestate is used to communicate through the graph that the simulator is currently running. Thetomethod is used to move and/or cast the values of the parameter. Theupdate_graphmethod is used signal all parents that the graph below them has changed.Examples
Example making some
Nodeobjects and then linking/unlinking them:n1 = Node() n2 = Node() n1.link("subnode", n2) # link n2 as a child of n1, may use any str as the key n1.unlink("subnode") # alternately n1.unlink(n2) to unlink by object
- property active: bool#
Trueif the node is currently in an active simulation run.- Type:
bool
- add_memo(memo)[source]#
Add a memo string and propagate it to all children.
- Parameters:
memo (str) – The memo message to add. Children in
subgraphsreceive the memo with the child name appended (memo|child_name).
- append_state(saveto: str | File)[source]#
Append the current state to an existing HDF5 file.
The file must have been previously created by
save_statewithappendable=True. The graph structure in the file is verified before appending.- Parameters:
saveto (str or File) – Path to an HDF5 file (
'.h5'or'.hdf5') or an open HDF5Fileobject.- Raises:
GraphError – If the graph structure no longer matches the file.
NotImplementedError – If the file path does not end with a supported extension.
- graph_dict() dict[str, dict][source]#
Return a nested dictionary representation of the graph.
Each key is a string of the form
"name|node_type"and the value is a dict containing the same structure for that node’s children.- Returns:
Nested dictionary mirroring the DAG hierarchy.
- Return type:
dict[str, dict]
- graph_print(dag: dict, depth: int = 0, indent: int = 4, result: str = '') str[source]#
Recursively render a graph dictionary as an indented string.
- Parameters:
dag (dict[str, dict]) – A nested dictionary as returned by
graph_dict.depth (int, optional) – Current indentation depth (used during recursion). Defaults to
0.indent (int, optional) – Number of spaces per indentation level. Defaults to
4.result (str, optional) – Accumulator string (used during recursion). Defaults to
"".
- Returns:
A human-readable, indented representation of the graph.
- Return type:
str
- graphviz(saveto: str | None = None) graphviz.Digraph[source]#
Return a graphviz
Digraphrepresenting the DAG below this node.- Parameters:
saveto (str, optional) – If provided, save the rendered graph to this file path. The file extension determines the output format (e.g.
'.pdf','.png'). Defaults toNone.- Returns:
The constructed directed-graph object.
- Return type:
graphviz.Digraph
- property graphviz_style#
- hierarchical_link(key: str, child: Node)[source]#
Link the current
Nodeobject to anotherNodeobject as a child in a hierarchical manner. See link for more detail on linking. A hierarchical link will allow batching internally to the simulator.- Parameters:
key (str) – The key to link the child node with.
child (Node) – The child
Nodeobject to link to.
Examples
parent = Node(name="parent") child = Node(name="child") parent.hierarchical_link("child", child)
- link(key: str | tuple | Node, child: Node | tuple | None = None)[source]#
Link the current
Nodeobject to anotherNodeobject as a child.- Parameters:
key ((Union[str, Node])) – The key to link the child node with. This will also become the attribute to access the child node. After linking you will have node.key == child
child ((Optional[Node], optional)) – The child
Nodeobject to link to. Defaults to None in which case the key is used as the child and the child.name is used as the key.
Examples
Example making some
Nodeobjects and then linking/unlinking them, demonstrating multiple ways to link/unlink:n1 = Node() n2 = Node() n1.link("subnode", n2) # may use any str as the key n1.unlink("subnode") # Alternatively, link by object n1.link(n2) n1.unlink(n2)
- load_state(loadfrom: str | File, index: int = -1, **kwargs)[source]#
Load node state (and children) from an HDF5 file.
- Parameters:
loadfrom (str or File) – Path to an HDF5 file (
'.h5'or'.hdf5') or an open HDF5Fileobject.index (int, optional) – Sample index to load when the file was saved in appendable mode. Defaults to
-1(last sample).**kwargs – Additional keyword arguments forwarded to
h5py.File(e.g.driver).
- Raises:
GraphError – If the graph structure no longer matches the file.
NotImplementedError – If the file path does not end with a supported extension.
- property memos: set[str]#
Current set of memo strings held by this node.
- Type:
set[str]
- property name: str#
The name of this node.
- Type:
str
- property node_str#
- property online: bool#
Trueif the node is online within a hierarchical sub-graph.- Type:
bool
- remove_memo(memo)[source]#
Remove a memo string and propagate removal to all children.
- Parameters:
memo (str) – The memo message to remove. The same propagation rules as
add_memoapply.
- save_state(saveto: str | File, appendable: bool = False)[source]#
Save the state of the node and its children, currently only works for HDF5 file types (.h5 and .hdf5).
The “state” of a node is considered to be the value of its params, however it is also possible to save other attributes of the node by adding them to the Node.saveattrs set. Simply call Node.saveattrs.add(‘attribute’) and then Node.attribute will be saved if possible. The HDF5 file will be created with the same structure as the graph, even if there are multiple paths to the same node. For example if N1 has children N2 and N3, and both N2 and N3 have the child N4, the HDF5 file will reflect this. It will be possible to find the N4 params under both ‘N1/N2/N4’ and ‘N1/N3/N4’ if inspecting the HDF5 file manually. Specifically, if N4 has the param P1 then you could access its value like this:
If the save had been set as appendable, then the value will have an extra dimension for the number of samples, this will always be the first dimension. If appendable was false then the value will simply equal the param value.
Note
You need the optional h5py package installed to use this method.
- Parameters:
saveto ((Union[str, File])) – The file to save the state to. If a string, it should be the path to an HDF5 file (ending in ‘.h5’ or ‘.hdf5’). If a File object, it should be an open HDF5 file.
appendable ((bool, optional)) – Whether to save the state in an appendable format. If True, the values will have an extra dimension for the number of samples. Defaults to False.
- to(device=None, dtype=None)[source]#
Moves and/or casts the values of the
Nodeto a particular device and/or dtype.- Parameters:
device ((optional)) – The device to move the values to. Defaults to None.
dtype ((optional)) – The desired data type. Defaults to None.
- topological_ordering() tuple[Node][source]#
Return a topological ordering of the graph below the current node.
Performs a recursive depth-first search with post-order traversal to resolve dependencies. The result starts with this node and proceeds to its descendants in dependency order.
- Returns:
All nodes reachable from (and including) this node, ordered so that every parent appears before its children.
- Return type:
tuple[Node]
- unlink(key: str | Node | list | tuple | None = None)[source]#
Unlink one or more
Nodeobjects from thisNode.- Parameters:
key ((str, Node, list, tuple, or None, optional)) – The key,
Nodeobject, or collection of keys/nodes to unlink. If a string, the child with that key is unlinked. If aNodeobject, the matching child is located and unlinked. If a list or tuple, each element is unlinked in turn. IfNone(the default), all children are unlinked.- Raises:
GraphError – If the graph is currently active.
- class caskade.NodeCollection(name: str | None = None, link: Node | tuple[Node] | None = None, description: str = '')[source]#
Bases:
Node,GetSetValuesBase mixin for collections of nodes that track parameters.
Provides shared functionality for traversing, querying, and converting parameters within a graph of nodes. Subclasses such as
NodeTupleandNodeListcombine this mixin with a standard Python sequence type.- property dynamic#
Whether any node in this collection has dynamic parameters.
- Returns:
Trueif at least one contained node is dynamic.- Return type:
bool
- property dynamic_param_groups: tuple[int]#
Sorted unique group identifiers of all dynamic parameters.
- Returns:
Sorted group indices present among the dynamic parameters.
- Return type:
tuple of int
- property dynamic_params: tuple[Param]#
All dynamic parameters in the graph below this node.
- Returns:
Dynamic (non-static, non-pointer) parameters found via topological ordering.
- Return type:
tuple of Param
- property pointer_params: tuple[Param]#
All pointer parameters in the graph below this node.
- Returns:
Parameters that act as pointers to other parameters, found via topological ordering.
- Return type:
tuple of Param
- property static#
Whether all nodes in this collection are static.
- Returns:
Trueif no contained node is dynamic.- Return type:
bool
- property static_params: tuple[Param]#
All static parameters in the graph below this node.
- Returns:
Static (non-dynamic, non-pointer) parameters found via topological ordering.
- Return type:
tuple of Param
- exception caskade.NodeConfigurationError[source]#
Bases:
CaskadeExceptionException for node configuration errors in
caskade.Raised when a node is configured with invalid or incompatible settings.
- class caskade.NodeDict(mapping=None, name=None)[source]#
Bases:
NodeCollection,dictMutable, keyed collection of nodes.
Behaves like a standard
dictbut also participates in the caskade node graph. All elements must beNodeinstances. Graph links are automatically updated whenever the dict is modified.- Parameters:
mapping (mapping of str to Node, optional) – Nodes to include in the dict. Defaults to an empty dict.
name (str, optional) – Human-readable name for this collection of nodes.
- property dynamic#
Whether any node in this collection has dynamic parameters.
- Returns:
Trueif at least one contained node is dynamic.- Return type:
bool
- property graphviz_style#
- popitem()[source]#
Remove and return an arbitrary (key, node) pair from the dict (the last one inserted) and update graph links.
- class caskade.NodeList(iterable=(), name=None)[source]#
Bases:
NodeCollection,listMutable, ordered collection of nodes.
Behaves like a standard
listbut also participates in the caskade node graph. All elements must beNodeinstances. Graph links are automatically updated whenever the list is modified.- Parameters:
iterable (iterable of Node, optional) – Nodes to include in the list. Defaults to an empty iterable.
name (str, optional) – Human-readable name for this collection node.
- property graphviz_style#
- class caskade.NodeTuple(iterable=None, name=None)[source]#
Bases:
NodeCollection,tupleImmutable, ordered collection of nodes.
Behaves like a standard
tuplebut also participates in the caskade node graph. All elements must beNodeinstances and are automatically linked as children upon construction.- Parameters:
iterable (iterable of Node, optional) – Nodes to include in the tuple.
name (str, optional) – Human-readable name for this collection node.
- property graphviz_style#
- class caskade.OverrideParam(param: Param, value)[source]#
Bases:
objectContext manager to override a parameter value.
Only inside an
OverrideParamwill the parameter be set to the new value. The original value (and the values of any parent pointer parameters) are saved on entry and restored on exit.- Parameters:
param (Param) – The parameter whose value should be temporarily overridden.
value (object) – The temporary value to assign to param.
Examples
Override a parameter inside a
@forwardmethod so that it usesnew_valueregardless of what was passed viaparams:class MySim(Module): def __init__(self): super().__init__() self.a = Param("a", None) self.b = Param("b", None) @forward def __call__(self, x, a=None, b=None): with OverrideParam(self.b, 5.0): # b will always be 5.0 here, ignoring params return x + a + self.b.value
- class caskade.Param(name: str, value: ArrayLike | float | int | None = None, shape: tuple[int, ...] | None = None, cyclic: bool = False, valid: tuple[ArrayLike | float | int | None] | None = None, units: str | None = None, dynamic: bool | None = None, group: int = 0, batch_shape: tuple[int] | None = None, dtype: Any | None = None, device: Any | None = None, **kwargs)[source]#
Bases:
NodeNode to represent a parameter in the graph.
The
Paramobject is used to represent a parameter in the graph. During runtime this will represent a value which can be used in various calculations. TheParamobject can be set to a constant value (static);Nonemeaning the value is to be provided at runtime (dynamic); anotherParamobject meaning it will take on that value at runtime (pointer); or a function of otherParamobjects to be computed at runtime (alsopointer, see user guides). These options allow users to flexibly set the behavior of the simulator.Examples
Example making some
Paramobjects:p1 = Param("test", (1.0, 2.0)) # constant value, length 2 vector p2 =Param("p2", None, (2,2)) # dynamic 2x2 matrix value p3 = Param("p3", p1) # pointer to another parameter p4 = Param("p4", lambda p: p.children["other"].value * 2) # arbitrary function of another parameter p5 = Param("p5", valid=(0.0,2*pi), units="radians", cyclic=True) # parameter with metadata
- Parameters:
name ((str)) – The name of the parameter.
value ((Optional[Union[ArrayLike, float, int]], optional)) – The value of the parameter. Defaults to None meaning dynamic.
shape ((Optional[tuple[int, ...]], optional)) – The shape of the parameter. Defaults to () meaning scalar.
cyclic ((bool, optional)) – Whether the parameter is cyclic, imposing periodic boundary conditions. Such as a rotation from 0 to 2pi. Defaults to False.
valid ((Optional[tuple[Union[ArrayLike, float, int, None]]], optional)) – The valid range of the parameter. Defaults to None meaning all of -inf to inf is valid.
units ((Optional[str], optional)) – The units of the parameter. Defaults to None.
dynamic ((bool, optional)) – Force param to be dynamic if True. If a value is provided and param is dynamic then it has a default value at call time.
(bool (batched) – If True, the param is assumed batched and the shape may now take the form (*B, *D) where *D is the shape of the value.
optional) – If True, the param is assumed batched and the shape may now take the form (*B, *D) where *D is the shape of the value.
dtype ((Optional[Any], optional)) – The data type of the parameter. Defaults to None meaning the data type will be inferred from the value.
device ((Optional[Any], optional)) – The device of the parameter. Defaults to None meaning the device will be inferred from the value.
- property batch_shape: tuple[int, ...]#
The batch dimensions of the parameter value.
Batch dimensions are the leading dimensions of the value that precede the event
shape. If an explicit batch shape was set it is returned directly; otherwise it is inferred from the value.- Returns:
The batch shape, or
()if the parameter is not batched.- Return type:
tuple of int
- property batched: bool#
Whether this parameter carries batch dimensions.
- Returns:
Trueifbatch_shapeis non-empty.- Return type:
bool
- property cyclic: bool#
Whether the parameter has cyclic (periodic) boundary conditions.
When
True, values wrap around thevalidrange (e.g. an angle from 0 to 2π).- Returns:
Trueif the parameter is cyclic.- Return type:
bool
- property device: str | None#
The device on which the parameter value resides.
If no explicit device was set, the device is inferred from the current value.
- Returns:
The device, or
Noneif unknown.- Return type:
device or None
- property dtype: str | None#
The data type of the parameter value.
If no explicit dtype was set, the dtype is inferred from the current value.
- Returns:
The data type, or
Noneif unknown.- Return type:
dtype or None
- property dynamic: bool#
Whether this parameter is dynamic.
- Returns:
Trueif the parameter’s value is provided at runtime.- Return type:
bool
- property graphviz_style#
- property group: int#
The group index of this parameter.
Parameters that share the same group index are collected together into a single
paramsobject when calling a simulator’s@forwardmethod, as well as when usingget_valuesorset_values.- Returns:
The group index (default
0).- Return type:
int
- is_valid(value=None) bool[source]#
Check whether a value lies within the allowed range.
- Parameters:
value (ArrayLike or None, optional) – The value to check. If
None(default), the parameter’s current value is used.- Returns:
Trueif the value is within the valid range or if no constraints are set.Falseotherwise; a warning is also emitted.- Return type:
bool
- property node_str: str#
Returns a string representation of the node for graph visualization.
- property node_type#
The current type of this parameter node.
- Returns:
One of
"static","dynamic", or"pointer".- Return type:
str
- property npvalue: ndarray#
The current value converted to a NumPy array.
- Returns:
The value as a NumPy
ndarray.- Return type:
numpy.ndarray
- property pointer: bool#
Whether this parameter is a pointer.
- Returns:
Trueif the parameter points to anotherParamor a callable that is evaluated at runtime.- Return type:
bool
- property shape: tuple[int, ...]#
The event (non-batch) shape of the parameter value.
Wildcard dimensions (
None) in the declared shape are resolved using the current value. If no shape was declared, the shape of the current value is returned directly.- Returns:
The resolved shape of the parameter.
- Return type:
tuple of int
- property static: bool#
Whether this parameter is static.
- Returns:
Trueif the parameter holds a fixed value that does not change at runtime.- Return type:
bool
- to(device=None, dtype=None) Param[source]#
Moves and/or casts the values of the parameter.
- Parameters:
device ((optional)) – The device to move the values to. Defaults to None.
dtype ((optional)) – The desired data type. Defaults to None.
- to_dynamic(value=<object object>)[source]#
Change this parameter to a dynamic parameter.
If a value is provided, it is stored as the default dynamic value. When called without arguments the existing value (if any) is kept.
- Parameters:
value (ArrayLike, float, int, None, or sentinel, optional) – The default value for the dynamic parameter. Must not be a
Paramor callable. By default the current value is retained.- Raises:
ActiveStateError – If the parameter is currently active.
ParamTypeError – If value is a
Paramor callable.ParamConfigurationError – If the value shape does not match the declared shape.
- to_pointer(value, link=())[source]#
Change this parameter to a pointer parameter.
The parameter’s value will be computed at runtime by dereferencing another
Paramor by calling a user-supplied function.- Parameters:
- Raises:
ActiveStateError – If the parameter is currently active.
ParamTypeError – If value is not a
Paramor callable.
- to_static(value=<object object>)[source]#
Change this parameter to a static parameter.
If a value is provided, it is stored as the fixed static value. When called without arguments the existing value (if any) is kept.
- Parameters:
value (ArrayLike, float, int, None, or sentinel, optional) – The constant value for the static parameter. Must not be a
Paramor callable. By default the current value is retained.- Raises:
ActiveStateError – If the parameter is currently active.
ParamTypeError – If value is a
Paramor callable.ParamConfigurationError – If the value shape does not match the declared shape.
- property valid: tuple[ArrayLike | None, ArrayLike | None]#
The valid range of the parameter value.
- Returns:
(lower_bound, upper_bound). Either bound may beNoneindicating no constraint on that side.- Return type:
tuple of (ArrayLike or None, ArrayLike or None)
- property value: ArrayLike | None#
The current value of the parameter.
For static and dynamic parameters the stored value is returned. For pointer parameters the linked callable is evaluated. During an active simulation the result is cached.
- Returns:
The parameter value, or
Noneif no value has been set.- Return type:
ArrayLike or None
- exception caskade.ParamConfigurationError[source]#
Bases:
NodeConfigurationErrorException for parameter configuration errors in
caskade.Raised when a parameter is defined with an invalid shape, type, or constraint.
- exception caskade.ParamTypeError[source]#
Bases:
CaskadeExceptionException for parameter type errors in
caskade.Raised when a value assigned to a parameter does not match its expected type.
- exception caskade.SaveStateWarning[source]#
Bases:
CaskadeWarningWarning issued when saving state encounters a non-fatal problem.
Issued when the state serialization completes but with potential data loss or format issues that the user should be aware of.
- class caskade.ValidContext(module: Module)[source]#
Bases:
objectContext manager that transforms parameter values to an unconstrained space.
Inside a
ValidContext, all parameter values are automatically mapped into the range(-inf, inf)via each parameter’sto_valid/from_validtransformations. This is useful when interfacing with samplers or optimizers that expect unconstrained parameters—any value they propose will be mapped back into the parameter’s original valid range on exit.- Parameters:
module (Module) – The module whose parameters should be transformed.
Examples
Get unconstrained parameter values for use with an optimizer:
with ValidContext(my_module): unconstrained_params = my_module.get_values() # unconstrained_params live in (-inf, inf)
- class caskade.active_cache(func)[source]#
Bases:
objectCaches the first evaluated result of a Module method for the duration of a simulation.
This decorator ensures that an expensive method is executed exactly once per active simulation run. Once calculated, subsequent calls to the decorated method will return the stored value, ignoring any arguments passed to it.
Warning
If the method is called multiple times with different arguments in one simulation, the cached result will still be returned, which may lead to unexpected behavior. Use with caution!
Notes
If you are stacking multiple decorators on a method (such as
@forwardor@jax.jit),@active_cacheMUST be the outermost (top) decorator.Examples
class FluxModel(Module): def __init__(self, nodes, x, M): super().__init__() self.nodes = nodes self.x = Param("x", x) self.M = Param("M", M) @active_cache @jax.jit # Notice active_cache is placed at the top @forward def compute_intrinsic_sed(self, w, x, M): print("Computing SED...") return jnp.interp(w, self.nodes, x * M) @forward def compute_flux(self, wavelengths): sed = self.compute_intrinsic_sed(wavelengths) # Cached after first call flux = jnp.sum(sed) sed = self.compute_intrinsic_sed(wavelengths) # Returns cached result, no print peak = jnp.max(sed) return flux, peak model = FluxModel(np.linspace(400, 700, 10), x=1.0, M=np.random.rand(10)) # Compute flux only calls compute_intrinsic_sed once due to caching flux, peak = model.compute_flux(wavelengths)
- caskade.forward(method)[source]#
Decorator to define a forward method for a module.
Manages parameter passing and activation for the decorated method. When called, it automatically fills keyword arguments from the module’s
Paramchildren and handles parameter overrides and active context.- Parameters:
method ((Callable)) – The forward method to be decorated.
- Returns:
The decorated forward method.
- Return type:
Callable
Examples
Standard usage of the forward decorator:
class ExampleSim(Module): def __init__(self, a, b, c): super().__init__("example_sim") self.a = a self.b = Param("b", b) self.c = Param("c", c) @forward def example_func(self, x, b=None): return x + self.a + b E = ExampleSim(a=1, b=None, c=3) print(E.example_func(4, params=[5])) # Output: 10