Karana.KUtils.DataStruct#

Classes and functions related to DataStruct.

DataStruct is a wrapper around pydantic.BaseModel. It contains extra functionality to:
  • Easily save/load `DataStruct`s from various file types.

  • Compare DataStruct`s with one another either identically, using `__eq__, or approximately, using isApprox.

  • Populate a Kclick CLI applications options from a DataStruct

  • Create an instance of a DataStruct from Kclick CLI application’s options.

  • Generate an asciidoc with the data of a DataStruct.

The saving/loading and comparison can be done recursively, meaning they accept DataStruct`s whose fields are other `DataStructs. In addition, they supported nested Python types, such as a dict of lists of numpy arrays.

Attributes#

Classes#

DataStruct

Wrapper around pydantic.BaseModel that adds functionality useful for modeling and simulation.

SentinelValueClass

Dummy class uses as a sentinel value.

DSLinker

Class used to populate a CLI application with DataStruct fields and create a DataStruct instance from CLI options.

AllObjsBase

Base class for the IdMixin.

IdMixin

Mixin to add ID tracking to a DataStruct.

NestedBaseMixin

A mixin used by DataStructs that are the base class for other DataStructs.

Module Contents#

class Karana.KUtils.DataStruct.DataStruct(/, **data: Any)[source]#

Bases: pydantic.BaseModel

Wrapper around pydantic.BaseModel that adds functionality useful for modeling and simulation.

This class adds functionality to the pydantic.BaseModel, including:
  • Easily save/load `DataStruct`s from various file types.

  • Compare DataStruct`s with one another either identically, using `__eq__, or approximately, using isApprox.

  • Generate an asciidoc with the data of a DataStruct.

The saving/loading and comparison can be done recursively, meaning they accept DataStruct`s whose fields are other `DataStructs. In addition, they supported nested Python types, such as a dict of lists of numpy arrays.

Parameters:

version (tuple[int, int]) – Holds the version of this DataStruct. Users should override the current version using the _version_default class variable. DataStructs that use this should also add a field validator or model validator to handle version mismatches.

version: tuple[int, int] = None#
model_config#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

classmethod generateAsciidoc() str[source]#

Generate asciidoc for the DataStruct.

classmethod cli(exclude: list[str] = [], extra_info: dict[str, Any] = {})[source]#

Add this DataStruct’s fields to a cli.

Parameters:
  • exclude (list[str]) – List of fields to exclude from the cli.

  • extra_info (dict[str, Any]) – Extra information that is used to generate the cli. Examples include: * name - Name the field. * help - Description for the field. * type - Type for the field. * default - Default for the field.

classmethod fromLinker(vals_orig: dict[str, Any], excluded_vals: dict[str, Any] = {}, ds_linker: DSLinker | None = None) Self[source]#

Create an instance of the DataStruct from a CLI dictionary.

Parameters:
  • vals_orig (dict[str, Any]) – CLI dictionary to use to build the DataStruct.

  • excluded_vals (dict[str, Any]) – Included any vals that were excluded from the DSLinker.

  • ds_linker (Optional[DSLinker]) – DSLinker to use to build the DataStruct. This is optional, and is only necessary if there are multiple DSLinker’s for a DataStruct.

toFile(file: pathlib.Path | str | IO[bytes], suffix: Literal['.json', '.yaml', '.yml', '.h5', '.hdf5', '.pickle', '.pck', '.pcl'] | None = None) None[source]#
toFile(g: h5py.Group) None

Write the DataStruct to a H5 group.

See overloads for details.

classmethod fromFile(file: pathlib.Path | str | IO[bytes], suffix: Literal['.json', '.yaml', '.yml', '.h5', '.hdf5', '.pickle', '.pck', '.pcl'] | None = None) Self[source]#
classmethod fromFile(g: h5py.Group) Self

Create an instance of this DataStruct a file.

See overloads for details.

isApprox(other: Self, prec: float = MATH_EPSILON) bool[source]#

Check if this DataStruct is approximately equal to another DataStruct of the same type.

This recursively moves through the public fields only. Note that Pydantic’s __eq__ checks private and public fields. Recursively here means if the field is an iterator, another DataStruct, an iterator of DataStructs, etc. we will go into the nested structure calling isApprox where appropriate on the items in the iterator, fields in the DataStruct, etc. If the field (or iterated value, etc.) does not have an isApprox method, then we fallback to using the __eq__. If all values of isApprox (or __eq__) return True, then this returns True; otherwise, this returns false.

Parameters:
  • other (Self) – A DataStruct of the same type.

  • prec (float) – The precision to use. Karana.Math.MATH_EPSILON is the default.

Returns:

True if the two DataStructs are approximately equal. False otherwise.

Return type:

bool

model_copy(*args, **kwargs) Self[source]#

Create a copy of the model.

This uses the typical pydantic model_copy method, but iterates through everything to call .copy() on numpy arrays. This creates an actual copy of the array, rather than keeping the data members linked.

Returns:

A copy of this DataStruct.

Return type:

Self

__eq__(other: object) bool[source]#

Check if this DataStruct is equal to another DataStruct of the same type.

First a normal == is tried on the fields. If that doesn’t work, then we recurse into the fields looking for numpy arrays. Recursively here means if the field is an iterator, another DataStruct, an iterator of DataStructs, etc. we will go into the nested structure calling the appropriate operator on the items in the iterator, fields in the DataStruct, etc. This is done mainly for numpy arrays, where we want to call np.array_equal rather than use ==.

Parameters:

other (object) – The object to compare with.

Returns:

True if the two DataStructs are equal. False otherwise.

Return type:

bool

class Karana.KUtils.DataStruct.SentinelValueClass[source]#

Bases: object

Dummy class uses as a sentinel value.

Karana.KUtils.DataStruct.SentinelValue#
class Karana.KUtils.DataStruct.DSLinker(data_struct: type[DataStruct], exclude: list[str], extra_info: dict[str, Any])[source]#

Class used to populate a CLI application with DataStruct fields and create a DataStruct instance from CLI options.

data_struct#
exclude#
extra_info#
toCli()[source]#

Use to convert a DataStruct to a Kclick cli.

Karana.KUtils.DataStruct.T#
class Karana.KUtils.DataStruct.AllObjsBase[source]#

Base class for the IdMixin.

Pydantic re-writes the namespace of the class each time, which means we can’t have a shared class variable across all IdMixins. Having a non-pydantic base class allows for this.

_all_objects_from_ids#

Shared dictionary of all objects created from classes that use the IdMixin.

Type:

dict[int, ref[“IdMixin”]]

class Karana.KUtils.DataStruct.IdMixin(/, **data: Any)[source]#

Bases: AllObjsBase, pydantic.BaseModel, Generic[T]

Mixin to add ID tracking to a DataStruct.

For book keeping, it is common to want to track the id of the object used to create the DataStruct. This mixin makes it easy to do so. It adds the private _id variable with default value None, adds a KaranaId property for it, and overrides the appropriate methods so that _id is serialized/deserialized if set. It is class using the Mixin, it is its job to add objects to via the addObjectFromId(…) method whenever appropriate.

property karana_id: int | None#

Retrieve the private _id variable.

property objects_from_id: list[Karana.Core.CppWeakRef[T]]#

Get any objects created from this DataStruct.

Returns:

A list of CppWeakRefs to objects created from this DataStruct.

Return type:

list[CppWeakRef[T]]

addObjectFromId(obj: T)[source]#

Store a CppWeakRef to an object created from this DataStruct.

This is used internally to find objects created from this DataStruct.

Parameters:

obj (T) – The object created from this DataStruct.

classmethod resetAllObjectsFromIds()[source]#

Reset the global bookkeeping for objects created from IDs.

This should rarely be needed. Only in cases were you are doing something like creating two simulations, two StatePropagators, etc. should you need this.

__getstate__()[source]#

Override __getstate__ to include _id if set.

classmethod getObjectsCreatedById(id: int, /) list[Any] | None[source]#
classmethod getObjectsCreatedById(val: Any, id: int, /) list[T] | None

Find objects created by DataStructs that match the given ID.

  1. Find any object created by any DataStruct since the last reset.

See resetAllObjectsFromIds for details on how to perform a reset.

This assumes unique IDs (and a unique DataStruct with that ID). Therefore, the search stops at the first ID.

Parameters:
  • id (int) – The ID to use in the search.

  • val (Any) – The data structure to recurse through. This can be a composite type consisting of DataStructs, lists, tuples, sets, and dictionaries.

  • id – The ID to use in the search.

Returns:

  • list[Any] | None – None if the ID was not found. Otherwise, a list of objects created with the ID.

  • 2. Find any objects in the val data structure that were created for the ID given by id.

  • This assumes unique IDs (and a unique DataStruct with that ID). Therefore, the search stops

  • at the first ID.

Returns:

None if the ID was not found. Otherwise, a list of objects created with the ID.

Return type:

list[T] | None

classmethod objectHasDS(id: int, /) bool[source]#
classmethod objectHasDS(obj: T, /) bool

Return True if this was turned into a DataStruct, False otherwise.

  1. Perform search by ID.

See resetAllObjectsFromIds for details on how to perform a reset.

This assumes unique IDs (and a unique DataStruct with that ID). Therefore, the search stops at the first ID.

Parameters:
  • id (int) – The ID to use in the search.

  • val (T) – The object to check if was turned into a DataStruct.

Returns:

  • bool – True if an object with this ID was turned into a DataStruct, False otherwise.

  • 2. Perform search by object.

  • This assumes unique IDs (and a unique DataStruct with that ID). Therefore, the search stops

  • at the first ID.

Returns:

True if an object with this ID was turned into a DataStruct, False otherwise.

Return type:

bool

class Karana.KUtils.DataStruct.NestedBaseMixin(/, **data: Any)[source]#

Bases: pydantic.BaseModel

A mixin used by DataStructs that are the base class for other DataStructs.

This ensures that the most derived type is used when serializing and deserializing.

property ds_python_class: str#

Get the fully qualified Python class name of the DataStruct.

Returns:

The fully qualified Python class name of the DataStruct.

Return type:

str