opynsim#

Classes

DataFrame(*args, **kwargs)

Represents data as a table containing rows and columns, with metadata (attrs()).

ForwardDynamicsSolver(*args, **kwargs)

Integrates the forward dynamics of a Model + ModelState pair.

IntegratorSettings(*args, **kwargs)

Settings for a forward integrator (e.g. as used by ForwardDynamicsSolver).

Model

A compiled model of a physics system.

ModelSpecification(*args, **kwargs)

A high-level specification for a Model.

ModelState

Represents a single state of a Model.

ModelStateStage(*values)

Represents a stage of state realization (computation).

ModelStates(*args, **kwargs)

Represents a sequence of ModelStates.

Symbol(*args, **kwargs)

Represents an immutable, cheap-to-use, readable symbol.

class opynsim.DataFrame(*args, **kwargs)#

Bases: object

Represents data as a table containing rows and columns, with metadata (attrs()).

DataFrame only supports storing float64 data. It enforces no constraints on the number/order/labels of columns, or the values it contains. However, other APIs in OPynSim may enforce stronger constraints (e.g. “The DataFrame supplied to this solver must contain a series named time with strongly monotonically increasing values”). In general, those constraints are checked at runtime and produce a validation error. Callers are expected to handle filtering/cleaning/fixing their DataFrames accordingly.

DataFrame’s functionality is limited to being just good enough for common OPynSim-related tasks. However, it the Arrow PyCapsule Protocol, which lets you import/export DataFrames to more-comprehensive libraries (e.g. DataFrame.from_arrow(), pandas.DataFrame.from_arrow, polars.from_arrow, pyarrow.table.__init__). If you want to do some fancy data manipulation, we recommend using one of those libraries.

__arrow_c_stream__(self, requested_schema: typing_extensions.CapsuleType | None = None) typing_extensions.CapsuleType#

Exports this DataFrame as an ArrowSchema (see: Apache Arrow PyCapsule Interface).

This is a low-level interface that other dataframe libraries (e.g. Pandas and Polars) can use to natively read DataFrames. For example, polars.DataFrame.__init__ accepts DataFrames because it implements this method, as does pandas.DataFrame.from_arrow.

Note: This method also exports metadata (attrs()), but third-party libraries handle metadata inconsistently. At time of writing, PyArrow encodes metadata into its table schema, but Pandas and Polars drop it. Therefore, we recommend that callers propagate metadata manually, or adjust their DataFrame to no need the metadata (e.g. use Model.convert_data_frame_to_radians() so that inDegrees isn’t needed).

Parameters:

requested_schema – An optional Arrow schema capsule (currently ignored).

Returns:

A PyCapsule called “arrow_array_stream” containing a C ArrowArrayStream struct.

__init__(self) None#

Constructs an empty DataFrame.

At the moment (WIP), the only way to construct a DataFrame that contains data is via methods like opynsim.read_sto().

property attrs#

Returns the attributes (metadata) associated with self.

In some cases, attributes can affect the behavior of functions that read data from DataFrames. Notably, functions like opynsim.Model.states_from_data_frame() look for attributes like 'inDegrees' to perform on-the-fly degrees-to-radians conversions on legacy data files.

from_arrow = <nanobind.nb_func object>#
property shape#

Returns the shape of the DataFrame.

to_pandas(self) object#

Returns a pandas.DataFrame constructed from self.

The pandas module is lazily imported when this method is called. It’s expected that the caller’s environment supplies a version of pandas that is compatible with the Arrow API (>= v2.2.0). This may require additionally supplying pyarrow, which pandas may internally use to implement the API.

See also: __arrow_c_stream__() and from_arrow().

to_polars(self) object#

Returns a polars.DataFrame constructed from self.

The polars module is lazily imported when this method is called. It’s expected that the callers have installed a version of polars that is compatible with the Arrow API (>= v0.20.4).

See also: __arrow_c_stream__() and from_arrow().

class opynsim.ForwardDynamicsSolver(*args, **kwargs)#

Bases: object

Integrates the forward dynamics of a Model + ModelState pair.

The solver stores a ModelState that it integrates forward in time to a caller-specified timepoint (see integrate_to()).

__init__(self, model: opynsim._core.Model, model_state: opynsim._core.ModelState, integrator_settings: opynsim._core.IntegratorSettings | None = None) None#

Constructs a ForwardDynamicsSolver of model in model_state.

Parameters:
  • model – The Model that is being integrated.

  • model_state – The state of model that the solver begins integration from.

  • integrator_settings – The IntegratorSettings that the solvers’s integrator uses for integration.

integrate_to(self, time: float, realized_to: opynsim._core.ModelStateStage = ModelStateStage.REPORT) opynsim._core.ModelState#

Integrates the solvers’s internal ModelState forwards to time and returns a copy of the internal state realized to at least realized_to.

class opynsim.IntegratorSettings(*args, **kwargs)#

Bases: object

Settings for a forward integrator (e.g. as used by ForwardDynamicsSolver).

Note: Modifying integrator settings can have a large effect on its performance and behavior. When tweaking the settings, it is recommended to re-validate outcomes.

__init__(self) None#
class opynsim.Model#

Bases: object

A compiled model of a physics system.

A Model can only be created from a ModelSpecification via the ModelSpecification.compile() function. Therefore, editing a Model requires editing its associated ModelSpecification and recompiling it to create a new Model.

__init__(*args, **kwargs)#
column_to_state_variable_mappings(self, data_frame: opynsim._core.DataFrame) dict[str, opynsim._core.Symbol]#

Returns associative mappings between the names of columns in data_frame and state variables in this Model, where the correspondence can be found.

This mapping uses a variety of heuristics, including (e.g.) accounting for legacy column headers supported by earlier files in SIMM and OpenSim. It is how states_from_data_frame() maps dataframes into ModelStates, so this method can be useful for debugging why states aren’t being read correctly.

convert_data_frame_to_radians(self, data_frame: opynsim._core.DataFrame) opynsim._core.DataFrame#

Returns a new DataFrame with all rotational columns converted to radians (if applicable).

If data_frame.attrs["inDegrees"] != "yes", returns an identical clone of data_frame. Otherwise, creates a new DataFrame where rotational_columns_in() is used to scale all rotational columns from degrees to radians (other columns are left unmodified). The "inDegrees" key is cleared from the returned DataFrame's attributes.

property coordinates#

Returns a list of all the coordinates in the model.

get_coordinate_speed(self, model_state: opynsim._core.ModelState, coordinate: opynsim._core.Symbol) float#

Returns the value of the corresponding state variable in model_state for the speed of coordinate.

get_coordinate_value(self, model_state: opynsim._core.ModelState, coordinate: opynsim._core.Symbol) float#

Returns the value of the corresponding state variable in model_state for the value of coordinate.

get_output_value(self, model_state: opynsim._core.ModelState, output: opynsim._core.Symbol) float | numpy.ndarray[dtype=float64, shape=(3)]#

Returns the value of output for the given model_state.

initial_state(self, *, realized_to: opynsim._core.ModelStateStage = ModelStateStage.INSTANCE) opynsim._core.ModelState#

Returns a ModelState that represents the initial (default) state of this Model.

The initial state of a Model is dictated by the ModelSpecification used to compile it. For example, if a translational coordinate in the specification had a default_value of 1.0 then that would be written into the ModelState returned by this function.

The returned ModelState will be realized to at least realized_to as-if by calling Model.realize() on it.

is_coordinate_locked(self, model_state: opynsim._core.ModelState, coordinate: opynsim._core.Symbol) bool#

Returns True if coordinate is locked in model_state.

Locking a coordinate prevents it from changing its value/speed (e.g. by a solver).

is_coordinate_rotational(self, coordinate: opynsim._core.Symbol) bool#

Returns True if coordinate is rotational (i.e. not translational, coupled, or undefined).

property num_coordinates#

Returns the number of coordinates in the model.

A coordinate represents a single degree of freedom (DoF) in the model, such as a joint angle, translation, or rotational parameter that contributes to the configuration/pose of a model.

property num_outputs#

Returns the number of outputs the model has.

property outputs#

Returns a list of all outputs the model has.

realize(self, model_state: opynsim._core.ModelState, model_state_stage: opynsim._core.ModelStateStage) None#

Realizes model_state to the desired model_state_stage, which modifies model_state in-place.

“Realization” of the state involves taking a new set of values from the ModelState and performing computations that those new values enable. Realization is performed in-order one ModelStateStage at time. For example, ModelStateStage.POSITION is realized before ModelStateStage.VELOCITY,then ModelStateStage.DYNAMICS, and so on.

rotational_columns_in(self, data_frame: opynsim._core.DataFrame) set[str]#

Returns the names of columns in data_frame that can be mapped to rotational state variables in this Model in the column-order of data_frame.

This is how states_from_data_frame() automatically converts degrees to radians when data_frame.attrs["inDegrees"] == "yes", so it can be useful for debugging why states aren’t being read correctly.

set_coordinate_locked(self, model_state: opynsim._core.ModelState, coordinate: opynsim._core.Symbol, locked: bool = True) None#

Sets the locked state of coordinate in model_state to locked.

Locking a coordinate prevents it from changing its value/speed (e.g. by a solver).

set_coordinate_speed(self, model_state: opynsim._core.ModelState, coordinate: opynsim._core.Symbol, speed: float) None#

Sets the value corresponding state variable in model_state for the speed of coordinate to speed.

Changing the speed of a coordinate changes model_state’s ModelStateStage to ModelStateStage.POSITION. Therefore, you may need to use realize() to re-realize the state to a later stage if you intend on using the state with a method that requires a later stage (e.g. rendering).

set_coordinate_value(self, model_state: opynsim._core.ModelState, coordinate: opynsim._core.Symbol, value: float) None#

Sets corresponding state variable in model_state for the value of coordinate to value.

Changing the value of a coordinate changes model_state’s ModelStateStage to ModelStateStage.POSITION. Therefore, you may need to use realize() to re-realize the state to a later stage if you intend on using the state with a method that requires a later stage (e.g. rendering).

states_from_data_frame(self, data_frame: opynsim._core.DataFrame, *, realized_to: opynsim._core.ModelStateStage = ModelStateStage.INSTANCE) opynsim._core.ModelStates#

Returns ModelStates constructed from data_frame.

Columns in data_frame will be mapped to state variables in this Model (see: column_to_state_variable_mappings()). Each row in data_frame constructs one ModelState in the returned ModelStates, in row-order.

If data_frame.attrs["inDegrees"] == "yes" then rotational columns in data_frame will be automatically converted into radians internally (see: rotational_columns_in()). This is to support DataFrames loaded from legacy data sources.

Each of the returned ModelStates will be realized to at least realized_to as-if by calling Model.realize() on each of them.

class opynsim.ModelSpecification(*args, **kwargs)#

Bases: object

A high-level specification for a Model.

A ModelSpecification is what Python code can manipulate, scale, and customize before passing it to compile(), which returns a readonly Model.

Notes

OPynSim’s API design separates the specification of a model (ModelSpecification) from its validated, assembled, and optimized physics engine representation (Model) to ensure that the compilation process (compile()) can freeze and optimize internal datastructures at a single point in the process.

__init__(self) None#
compile(self) opynsim._core.Model#

Compiles this ModelSpecification into a Model.

The compilation process:

  • Validates this ModelSpecification’s components (properties, subcomponents, and sockets), throwing an exception if the specification is invalid in some way.

  • Assembles a physics system from the validated specification, throwing an exception if the physics system cannot be assembled (e.g. if the contains impossible-to-satisfy joints, or invalid muscle definitions).

Raises:

Exception – If the compilation process failed in some way. It is assumed that the provided ModelSpecification is valid.

class opynsim.ModelState#

Bases: object

Represents a single state of a Model.

A ModelState bundles together the state variables, cache variables, and other information necessary to describe a single state of a Model. Models can read/manipulate ModelStates in order to Model.realize() the state to a later stage (e.g. as part of forward integration) or read outputs values. However, ModelStates may also be created, read, and manipulated by downstream Python code and other utilities in OPynSim.

__init__(*args, **kwargs)#
property stage#

Returns the ModelStateStage of the state.

Notes

A state may be realized to a later stage with Model.realize().

property time#

Returns the time of the state.

class opynsim.ModelStateStage(*values)#

Bases: Enum

Represents a stage of state realization (computation).

When calling methods like Model.realize(), a ModelState is realized in-order through each ModelStateStage, starting at the lowest stage and ending at the highest stage.

Each time a ModelState advances through a ModelStateStage, more information is available in the state. For example, after a ModelState is realized to ModelStateStage.POSITION, positional quantities such as the positions of bodies and offset frames are known, and any positional output on the associated Model can then extract that information from the ModelState.

For convenience, the opynsim module defines aliases for each ModelStateStage:

ACCELERATION = 7#
DYNAMICS = 6#
INSTANCE = 2#
MODEL = 1#
POSITION = 4#
REPORT = 8#
TIME = 3#
TOPOLOGY = 0#
VELOCITY = 5#
class opynsim.ModelStates(*args, **kwargs)#

Bases: object

Represents a sequence of ModelStates.

ModelStates is typically returned from functions that produce sequences of ModelStates, such as Model.states_from_data_frame(). The API of ModelStates is list-like, meaning downstream code can iterate over each ModelState, use len with it, randomly access a state with model_states[idx] and so on.

__init__(self) None#
to_list(self) list[opynsim._core.ModelState]#
class opynsim.Symbol(*args, **kwargs)#

Bases: object

Represents an immutable, cheap-to-use, readable symbol.

Symbols are extensively used by the OPynSim API to accelerate associative lookups. They are the middle-ground between fast, but hard to read/introspect, integer handles and slow, simpler string handles.

From Python code’s point of view, symbols should be seen as string-like handles that OPynSim accepts/emits. You can safely store symbols independently of any larger data structure, and interchange them across your entire Python codebase, without having to worry about object lifetimes. OPynSim’s native code uses runtime-checked associative lookups, rather than pointers, to ensure that the Python API is memory-safe and can provide suitable feedback whenever a lookup fails.

__init__(self, id: str) None#

Constructs a symbol from a Python string.

opynsim.read_csv(source: str | os.PathLike) opynsim._core.DataFrame#

Returns a DataFrame parsed from an .csv file on the caller’s filesystem.

The CSV file must have a header section, delimited by ‘endheader`. This usually necessitates adding an endheader entry just above the header row (TODO: this limitation was inherited from OpenSim and shouldn’t be a thing long-term).

Raises:

RuntimeError – If the file cannot be found, read, or is invalid.

opynsim.read_jpeg(source: str | os.PathLike) opynsim._core.graphics.Texture2D#

Returns a graphics.Texture2D parsed from a .jpeg file on the caller’s filesystem.

Raises:

RuntimeError – If the file cannot be found, read, or is invalid.

opynsim.read_jpg(source: str | os.PathLike) opynsim._core.graphics.Texture2D#

An alias for read_jpeg()

opynsim.read_mot(source: str | os.PathLike) opynsim._core.DataFrame#

Returns a DataFrame parsed from an .mot file on the caller’s filesystem.

Raises:

RuntimeError – If the file cannot be found, read, or is invalid.

opynsim.read_obj(source: str | os.PathLike) opynsim._core.graphics.Mesh#

Returns a graphics.Mesh parsed from a .obj file on the caller’s filesystem.

Raises:

RuntimeError – If the file cannot be found, read, or is invalid.

opynsim.read_osim(source: str | os.PathLike) opynsim._core.ModelSpecification#

Returns a ModelSpecification parsed from an .osim file on the caller’s filesystem.

Raises:

RuntimeError – If the file cannot be found, read, or is invalid.

opynsim.read_png(source: str | os.PathLike) opynsim._core.graphics.Texture2D#

Returns a graphics.Texture2D parsed from a .png file on the caller’s filesystem.

Raises:

RuntimeError – If the file cannot be found, read, or is invalid.

opynsim.read_stl(source: str | os.PathLike) opynsim._core.graphics.Mesh#

Returns a graphics.Mesh parsed from a .stl file on the caller’s filesystem.

Raises:

RuntimeError – If the file cannot be found, read, or is invalid.

opynsim.read_sto(source: str | os.PathLike) opynsim._core.DataFrame#

Returns a DataFrame parsed from an .sto file on the caller’s filesystem.

Raises:

RuntimeError – If the file cannot be found, read, or is invalid.

opynsim.read_trc(source: str | os.PathLike) opynsim._core.DataFrame#

Returns a DataFrame parsed from an .trc file on the caller’s filesystem.

Raises:

RuntimeError – If the file cannot be found, read, or is invalid.

opynsim.read_vtp(source: str | os.PathLike) opynsim._core.graphics.Mesh#

Returns a graphics.Mesh parsed from a .vtp file on the caller’s filesystem.

Raises:

RuntimeError – If the file cannot be found, read, or is invalid.

Modules