soma.io#
The soma.io module provides the file-format boundary for the library.
The main responsibilities are:
USD mesh and skeleton import/export, and standalone joint animation import
SOMA NPZ save/load helpers
convenience export helpers built around
SOMALayer
Read a standalone UsdSkel joint animation without a skeleton or mesh:
from soma.io import load_usd_animation_sequence
animation = load_usd_animation_sequence("assets/example_animation.usd")
local_transforms = animation.local_transforms
times_seconds = animation.time_codes / animation.time_codes_per_second
The reader preserves source joint paths, units, axes, and scale. Unit conversion
and interpretation of the motion for a particular rig belong to the caller.
load_usd_animation retains its existing default-pose return contract.
For SOMA playback, load_soma_animation maps joints and converts translations
to meters. Set world_space=True to compose authored joint-path ancestors
before selecting joints. soma.body.SOMALayer.load_motion() and
soma.hand.SOMAHandLayer.load_motion() convert rotations and root translations
for their respective layers, with absolute or reference-relative output.
I/O helpers for SOMA: NPZ animation files and USD mesh/skeleton/animation I/O.
An .npz file contains everything needed to replay an animation with SOMALayer: identity model type, identity coefficients, poses, root translation, and metadata describing the representation.
- class soma.io.UVPrimvarEntry#
-
Serialized UV primvar data returned by
load_usd_mesh.Behaves like a
dictfor backwards compatibility (entry["coordinates"]) while also supporting attribute access (entry.coordinates).
- class soma.io.SOMANPZData#
-
Dictionary returned by
load_soma_npz.Behaves like a
dictfor backwards compatibility (data["poses"]) while also supporting attribute access (data.poses). Optional fields (scale_params,joint_orient,global_scale,hand_type) are present only if they were saved.
- class soma.io.AnimationUSDData#
-
Sampled joint animation returned by
load_usd_animation_sequence.Supports both dictionary and attribute access. Transforms use column vectors in the source stage’s units and axis convention; joint paths retain their authored order. No skeleton, mesh, or SOMA joint layout is required.
- class soma.io.RigUSDData#
-
Dictionary returned by
load_rig_from_usd.Behaves like a
dictfor backwards compatibility (rig["joint_names"]) while also supporting attribute access (rig.joint_names). Mesh-related fields (face_vert_indices,face_vert_counts,uv_data) are present only when the body skin mesh carries polygon/UV data.
- soma.io.list_usd_meshes(usd_file_path)#
Return prim paths of all Mesh prims in a USD file.
- soma.io.load_usd_mesh(usd_file_path, mesh_name)#
Load a mesh from a USD file.
- Parameters:
- Returns:
(vertices, face_vert_indices, face_vert_counts, uv_data)wherevertices:
(V, 3)float32face_vert_indices:
(sum(counts),)int32 — flattenedface_vert_counts:
(F,)int32 — verts-per-faceuv_data:
{name: {"coordinates": (M,2), "indices": ..., "interpolation": str}}
- Return type:
- soma.io.write_usd_mesh(
- usd_file_path,
- mesh_name,
- vertices,
- face_vert_indices,
- face_vert_counts,
- uv_data=None,
Write a mesh to a new USD file.
- soma.io.fan_triangulate(face_vert_indices, face_vert_counts)#
Convert a polygon soup to triangles via fan triangulation.
- soma.io.load_usd_skeleton(usd_file_path)#
Extract skeleton from a USD file.
- Parameters:
- Returns:
Tuple
(joint_paths, bind_transforms, parent_ids).joint_pathsis the list of J joint path strings (for example"Root/Hips"),bind_transformsis a(J, 4, 4)float32 array of world-space bind transforms in USD row-major convention (point * M), andparent_idscontains the J parent indices with-1for the root.- Return type:
- soma.io.load_usd_animation(usd_file_path)#
Extract SkelAnimation rotations and translations from a USD file.
- soma.io.load_usd_animation_sequence(
- usd_file_path,
- *,
- animation_prim_path=None,
- time_codes=None,
Read a UsdSkel joint animation without requiring a skeleton or mesh.
- Parameters:
animation_prim_path (str | None) – Select a SkelAnimation prim explicitly. If omitted, the stage must contain exactly one SkelAnimation.
time_codes (Sequence[float] | None) – Times to evaluate using USD interpolation and held values. By default, sample at one-time-code intervals across the inclusive stage playback range, without exceeding its end. If no playback range is authored, use the transform attributes’ sample range, or time zero for a static animation.
- Returns:
AnimationUSDDatawithjoint_pathsin authored order,local_transformsof shape(T, J, 4, 4)(float32, column-vector convention),scalesof shape(T, J, 3), and the sampledtime_codes. Translations remain in source-stage units. Metadata includesmeters_per_unit,up_axis, andtime_codes_per_second; elapsed seconds are time-code differences divided by the latter. Joint names, units, axes, and scale are not restricted to SOMA.- Return type:
Unlike
load_usd_animation(), which reads the default pose, this function reads a time sequence and returns its joint paths and metadata.
- soma.io.load_soma_animation(path, joint_names, *, world_space=False)#
Load a USD animation in the requested SOMA joint order and meter units.
USD animation is sampled once per time code over the stage playback range, including frames without authored keys. Joint paths determine the mapping; stage metadata determines translation units and playback speed.
- Parameters:
path (str | Path) – USD animation file. Legacy NPY motion files are unsupported.
joint_names (Sequence[str]) – Target joint leaf names in the desired output order.
world_space (bool) – Compose authored joint-path ancestors before selecting joints. Output is in the animation’s coordinate frame, without scene prim transforms. Missing leading path prefixes are allowed for animation roots; gaps between authored ancestors are rejected.
- Returns:
(transforms, fps)with float32 transforms of shape(T, J, 4, 4)in column-vector convention and translations in meters. Requires Y-up animation, unambiguous joint leaf names, and unit scale. Useload_usd_animation_sequence()to read other USD conventions.- Return type:
- soma.io.load_usd_skinning(usd_file_path, mesh_prim_path=None)#
Extract skinning weights from a skinned mesh in a USD file.
The mesh binding may define its own joint order (a subset of the skeleton joints). The returned weight matrix is indexed by the skeleton joint order so it aligns with
load_usd_skeleton.- Parameters:
- Returns:
(skinning_weights, num_joints)whereskinning_weights:
(V, J_skel)float32 dense weight matrixnum_joints: number of skeleton joints
- Return type:
- soma.io.missing_soma_neutral_rig_keys(data)#
Return rig keys absent from a loaded
SOMA_neutral.npzmapping.
- soma.io.find_lod_skin_mesh_name(usd_path, lod)#
Find the skinned mesh leaf name for a body LOD in a UsdSkel asset.
The SOMA templates use naming conventions such as
c_skin_xloorc_bodyRig_xlo. This helper keeps the runtime tolerant to small naming differences while still requiring a skinned mesh, not just any mesh whose name contains the LOD token.
- soma.io.load_lod_rig_from_usd(usd_path, lod, *, skin_mesh_name=None)#
Load rig data for a specific body LOD from a UsdSkel USD file.
- soma.io.load_lod_rigs_from_usd(usd_path, lods, *, skin_mesh_names=None)#
Load multiple LOD rigs from one UsdSkel USD file with a shared stage.
- soma.io.load_rig_from_usd(usd_path, *, skin_mesh_name=None)#
Load SOMA template rig data from a UsdSkel USD file.
Extracts the joint hierarchy, bind/T-pose transforms, bind-shape vertex positions, and skinning weights from the USD skeleton. Returns the rig-related keys that used to be stored in
SOMA_neutral.npzso they can be merged with the slim core asset when initializingSOMALayer.Shape PCA data (
mean,shapedirs,eigenvalues) and mesh topology (triangles,triangles_low, LOD maps, facial segments) are not included; they must still be loaded fromSOMA_neutral.npz.- Parameters:
usd_path (str | Path) – Path to the
.usda,.usdc, or.usdtemplate rig.skin_mesh_name (str | None) – Name of the
UsdGeomMeshprim holding the body skin (leaf path component, not full path). IfNone(the default), look forDEFAULT_SKIN_MESH_NAMEfirst, and fall back to the firstUsdGeomMeshdescendant of anyUsdSkelRoot. Pass an explicit name to pin the search.
- Returns:
Dictionary with rig keys supplied by
SOMA_template_rig.usda–joint_names,joint_parent_ids,bind_pose_world,bind_pose_local,t_pose_world,t_pose_local,bind_shape,skinning_weights_data,skinning_weights_indices,skinning_weights_indptr, andskinning_weights_shape. When the body skin mesh carries polygon or UV data, the result also includesface_vert_indices,face_vert_counts, anduv_dataforsave_soma_usd.- Raises:
FileNotFoundError – if the USD file does not exist.
RuntimeError – if the file cannot be opened, has no
UsdSkelSkeleton, has nobindTransforms, has joint/ transform count mismatches, or has malformed skinning primvars.ValueError – if the skin mesh cannot be located under skin_mesh_name (or the auto-discovery fallback), or has no points.
- Return type:
- soma.io.add_npz_args(parser)#
Add common NPZ output arguments to an argparse parser.
- soma.io.load_soma_npz(path)#
Load a SOMA animation .npz saved by
save_soma_npz.Returns a dict with the following keys:
poses:(N, J, 3)rotvec or(N, J, 3, 3)matrices.transl:(N, 3)root translation.joint_names: list of J joint name strings.identity_model_type: e.g."mhr","smpl".identity_coeffs:(N, C)or(1, C).rotation_repr:"rotvec"or"matrix".absolute_pose: bool — True if poses are absolute (no joint orient).unit: unit label string (e.g."meters").keep_root: bool — whether the Root joint (index 0) is included.
Optional keys (present only if saved):
scale_params:(N, S)or(1, S).joint_orient:(J, 3, 3)per-joint orient (present whenabsolute_pose=False).global_scale: scalar uniform scale factor.hand_type:"left"or"right"(absent for body animations).
Any extra arrays stored via extra_arrays are included as-is.
- Parameters:
- Returns:
dict of numpy arrays and Python scalars.
- Return type:
- soma.io.save_soma_usd(
- out_path,
- rotations=None,
- root_translation=None,
- *,
- joint_names,
- joint_parent_ids,
- bind_transforms_world,
- bind_transforms_local,
- rest_shape,
- faces=None,
- face_vert_indices=None,
- face_vert_counts=None,
- uv_data=None,
- skinning_weights,
- unit='meters',
- fps=30.0,
- topk=8,
- root_joint_idx=None,
- skin_mesh_name=DEFAULT_SKIN_MESH_NAME,
Save a SOMA skeletal rig (and optionally animation) to a USD file with UsdSkel.
When rotations and root_translation are omitted, only the static rig is written (skeleton bind pose + skinned mesh) with no SkelAnimation prim.
The rotations and root_translation should come directly from
fit(local-space,absolute_pose=Trueconvention).- Parameters:
out_path (str | Path) – Output
.usd,.usda, or.usdcfile path.rotations (ndarray | Tensor | None) – (N, J, 3, 3) local rotation matrices, or
Nonefor a static rig.root_translation (ndarray | Tensor | None) – (N, 3) root joint local translation, or
Nonefor a static rig.joint_names (Sequence[str]) – list of J joint name strings (including Root).
joint_parent_ids (Sequence[int] | ndarray | Tensor) – (J,) parent index array.
bind_transforms_world (ndarray | Tensor) – (J, 4, 4) or (1, J, 4, 4) world-space bind transforms.
bind_transforms_local (ndarray | Tensor) – (J, 4, 4) or (1, J, 4, 4) local-space bind transforms.
rest_shape (ndarray | Tensor) – (V, 3) bind-pose vertex positions.
faces (ndarray | Tensor | None) – (F, 3) triangle face indices. Used as fallback when face_vert_indices/face_vert_counts are not provided.
face_vert_indices (ndarray | Tensor | None) – Flattened polygon face-vertex indices (e.g. quads from the template USD). Takes priority over faces when provided.
face_vert_counts (ndarray | Tensor | None) – Per-face vertex counts matching face_vert_indices.
uv_data (Mapping[str, UVPrimvarEntry] | None) – Optional UV sets in nested-dict format
{name: {"coordinates": (M,2), "indices": ..., "interpolation": str}}, as returned byload_usd_meshorload_rig_from_usd.skinning_weights (ndarray | Tensor) – (V, J) dense skinning weights.
unit (str) –
"meters","centimeters", or"millimeters".fps (float) – Frames per second (timeCodesPerSecond).
topk (int) – Max joint influences per vertex for sparse skinning.
root_joint_idx (int | None) – Index of the joint that receives root_translation. Defaults to 1 (SOMA body Hips); pass 0 for hand models.
skin_mesh_name (str) – Leaf name for the skinned mesh prim under the
UsdSkelRoot. Defaults toDEFAULT_SKIN_MESH_NAMEso that files written here round-trip cleanly throughload_rig_from_usd.
- soma.io.save_vertex_animation_usd(
- out_path,
- vertices,
- faces,
- *,
- unit='meters',
- fps=30.0,
- prim_path='/Mesh',
Save a mesh with per-frame vertex positions to USD.
No skeleton or skinning – just animated
Pointson aMeshprim. Useful for exporting target meshes, blendshape sequences, or any topology-constant vertex animation.- Parameters:
out_path (str | Path) – Output
.usd,.usda, or.usdcfile path.vertices (ndarray | Tensor) – (N, V, 3) per-frame vertex positions.
faces (ndarray | Tensor) – (F, 3) triangle face indices (constant across frames).
unit (str) –
"meters","centimeters", or"millimeters".fps (float) – Frames per second.
prim_path (str) – USD prim path for the mesh (default
"/Mesh").