Skeleton Operations¶
Euler order conversion¶
# Change all joints at once
bvh_xyz = bvh.change_euler_order("XYZ")
# Change a single joint only
bvh_single = bvh.change_euler_order("XYZ", joint="Hips")
Skeleton scaling¶
Retargeting¶
reference = pybvh.read_bvh_file("reference_skeleton.bvh")
bvh_retarget = bvh.retarget(reference)
# With name mapping (when joint names differ)
bvh_retarget = bvh.retarget(reference, name_mapping={
"Hips": "pelvis", "Spine": "spine_01"
})
Joint extraction¶
The three skeleton operations on one shared scale — scaled to half, retargeted back to the original proportions, and reduced to 11 joints:

Frame operations¶
clip = bvh[10:50] # frame slicing (steps work too: bvh[::2])
combined = bvh + other_bvh # concatenation (same skeleton required)
bvh_30fps = bvh.resample(30)
Pandas integration¶
to_df_dict() exports the motion as labeled columns; to_hierarchy_dict() exports the skeleton as a plain dict. Together they carry everything needed to rebuild the Bvh with Bvh.from_df(hier, df) — hier accepts either the hierarchy dict or a bvh.nodes list (the module-level pybvh.df_to_bvh is the same function):
import pandas as pd
from pybvh import Bvh
df = pd.DataFrame(bvh.to_df_dict(mode="euler"))
hier = bvh.to_hierarchy_dict() # {name: {offset, parent, rot_channels, ...}}
bvh_from_df = Bvh.from_df(hier, df)
Inplace convention¶
All mutation methods default to inplace=False (return a new Bvh):
See also
Gallery — scale/retarget/extract_joints and resample drawn (section 4) · Bvh Class API — full signatures · Core Concepts — the index spaces these operations preserve