Skip to main content

A generic interface to generate a virtual buddy

Project description

biobuddy

BioBuddy is an open-source tool for translating, creating and personalizing musculoskeletal models across different formats (e.g., .osim, .bioMod). By enabling reliable interoperability between modeling environments, BioBuddy allows researchers to focus on scientific questions rather than technical constraints.

codecov Discord

How to install

Currently, the only way to install BioBuddy is from source. But it will be available on conda-forge and pip in the near future.

If you are a user, you can set up your environment with minimal dependencies.

conda install -c conda-forge python=3.11.11 pip
pip install scipy==1.15.1 numpy==1.25.2 lxml ezc3d

Note: On mac, you might need to add conda install conda-forge::libcxx

However, if you are a developer and want to contribute, you will need to set up your environment using the following command: Due to the OpenSim dependency used only in BioBuddy's tests, we recommend using python=3.11.

pip install pytest pytest-cov codecov
conda install -c opensim-org opensim=4.5.1
conda install -c conda-forge biorbd=1.11.2 deepdiff

Model translation

You can load the original model using one of the BiomechanicalModelReal().from_[format] methods, and then export it into another format using the BiomechanicalModelReal.to_[format] method (see example).

from biobuddy import BiomechanicalModelReal

# Read an .osim file
model = BiomechanicalModelReal().from_osim(
    filepath=osim_filepath,
    # Other optional parameters here
)

# Translate it into a .bioMod file
model.to_biomod(biomod_filepath)

Model creation

A model can also be created from scratch using the BiomechanicalModel. In this generic model, everything can be defined through functions (i.e., without numerical values). The subject specific model (a BiomechanicalModelReal) can then be generated by evaluating the generic model with a motion capture trial. This feature is especially useful for kinematic models where the joint centers are defined based on anatomical marker placement (like in the plug in gait, see full example).

Here is a simple example of how to add components to such a model:

# Create the model
model = BiomechanicalModel()
de_leva = DeLevaTable(total_mass=60, sex=Sex.FEMALE)

# Add components to build the kinematic chain
model.add_segment(
    Segment(
        name="HEAD",
        parent_name="TRUNK",
        segment_coordinate_system=SegmentCoordinateSystem(
            "BOTTOM_HEAD",
            first_axis=Axis(name=Axis.Name.Z, start="BOTTOM_HEAD", end="HEAD_Z"),
            second_axis=Axis(name=Axis.Name.X, start="BOTTOM_HEAD", end="HEAD_XZ"),
            axis_to_keep=Axis.Name.Z,
        ),
        mesh=Mesh(("BOTTOM_HEAD", "TOP_HEAD", "HEAD_Z", "HEAD_XZ", "BOTTOM_HEAD")),
        inertia_parameters=de_leva[SegmentName.HEAD],
    )
)
model.segments["HEAD"].add_marker(Marker("BOTTOM_HEAD"))
model.segments["HEAD"].add_marker(Marker("TOP_HEAD"))
model.segments["HEAD"].add_marker(Marker("HEAD_Z"))
model.segments["HEAD"].add_marker(Marker("HEAD_XZ"))

# Evaluate the model with a motion capture trial
model_real = model.to_real(C3dData(c3d_filepath))

There are many different components available to build a model (see this example to see how to add those components to your model).

Build_segment

Model personalization/modification

The current version of BioBuddy allows you to modify your BiomechanicalModelReal to personalize it to your subjects by:

Scaling:

The scaling is performed by the ScaleTool which can be initialized from scratch like this:

original_model = BiomechanicalModelReal()

# Create the scaling configuration
scaling_configuration = ScaleTool(original_model)

# Add a scaling segment for the pelvis
scaling_configuration.add_scaling_segment(
    SegmentScaling(
        name="pelvis",
        scaling_type= SegmentWiseScaling(
            axis=Translations.XYZ,
            marker_pairs=[
                ["RASIS", "LASIS"],
                ["RPSIS", "LPSIS"],
            ]
        )
    )
)

# Add marker weights for the pelvis segment
scaling_configuration.add_marker_weight(MarkerWeight(name="RASIS", weight=1.0))
scaling_configuration.add_marker_weight(MarkerWeight(name="LASIS", weight=1.0))
scaling_configuration.add_marker_weight(MarkerWeight(name="RPSIS", weight=0.5))
scaling_configuration.add_marker_weight(MarkerWeight(name="LPSIS", weight=0.5))

or by reading from an existing file (e.g., .xml or .biomod) using the appropriate ScaleTool.from_[format] method. Once the scaling configuration is set up, you can scale your model based on a static trial (.c3d file) and the total mass of your participant using the ScaleTool.scale like this:

# Performing the scaling based on a static trial
scale_tool = ScaleTool.from_biomod(biomod_filepath)
scaled_model = scale_tool.scale(static_c3d=C3dData(filepath), mass=mass)

For now, there are three scaling methods available:

  • BodyWiseScaling: scales the entire body based on the total height of the participant.
  • SegmentWiseScaling: scales the segment based on the distance between marker pairs.
  • AxisWiseScaling: scales each axis of the segment independently based on the distance between marker pairs. scaling_types

Joint center identification:

The JointCenterTool allows you to identify the joint centers of your model based on the movement of segments during functional trials. First, you need to define the joint center configuration using JointCenterTool.add() method to define the joint you want to modify. Then, you can use the JointCenterTool.replace_joint_centers() method to modify each joint.

from biobuddy import JointCenterTool

# Set up the joint center identification tool
joint_center_tool = JointCenterTool(scaled_model)
# Example for the right hip
joint_center_tool.add(
    Score(
        functional_c3d=C3dData(c3d_filepath, first_frame=100, last_frame=900),
        parent_name="pelvis",
        child_name="femur_r",
        parent_marker_names=["RASIS", "LASIS", "LPSIS", "RPSIS"],
        child_marker_names=["RGT", "RUB_Leg", "RUF_Leg", "FBF_Leg", "RMFE", "RLFE"],
    )
)
# Example for the right knee
joint_center_tool.add(
    Sara(
        functional_c3d=C3dData(c3d_filepath),
        parent_name="femur_r",
        child_name="tibia_r",
        parent_marker_names=["RGT", "RUB_Leg", "RUF_Leg", "FBF_Leg"],
        child_marker_names=["RATT", "RUB_Tib", "RDF_Tib", "RDB_Tib", "RSPH", "RLM"],
    )
)

# Perform the joint center identification
modified_model = joint_center_tool.replace_joint_centers()

For now, two algorithms were implemented SCoRE to locate the position of the joint center and SARA to identify the joint axis of rotation. Please note that in both cases, all segment components stay the same, only the joint position and axis are modified.

SCoRE_SARA

Merging segments:

The MergeSegmentTool allows you to merge two segments into one (including inertial parameters and all the components on the segment). You can define which segments you want to merge using SegmentMerge, which requires the names of the segments to merge and the name of the new segment.

merge_tool = MergeSegmentsTool(original_model)
# By default, segments merge together setting the new segment coordinate as the mean of the old coordinates
merge_tool.add(
   SegmentMerge(
      name="LOWER_ARMS", 
      first_segment_name="L_LOWER_ARM", 
      second_segment_name="R_LOWER_ARM",
   )
)
# But you can also merge one segment on top of another one by specifying the segment coordinate system to keep
merge_tool.add(
   SegmentMerge(
      name="R_LOWER_ARM_AND_HAND", 
      first_segment_name="R_LOWER_ARM", 
      second_segment_name="R_HAND", 
      merged_origin_name="R_LOWER_ARM",
   )
)
modified_model = merge_tool.merge()

merge_segments

Modifying the kinematic chain:

The ModifyKinematicChainTool allows you to modify the kinematic chain of your model. For now, the only modification available is to change which segment is the first segment of the kinematic chain (ChangeFirstSegment). It inverts all segments between the original first segment and the new first segment.

kinematic_chain_modifier = ModifyKinematicChainTool(original_model)
kinematic_chain_modifier.add(ChangeFirstSegment(first_segment_name="FOOT"))
modified_model = kinematic_chain_modifier.modify()

kinematic_chain_modifier

Note

Understandably, not all modeling formats have the same functionalities, so some features may not be available for all formats. We will try to keep here a list up to date of the features that are available in BioBuddy that are not available for each format:

  • biorbd (.bioMod):
    • PathPointCondition is not implemented yet in biorbd. So if your BioBuddy model has this component, we recommend running BiomechanicalModelReal.fix_via_points(q) before BiomechanicalModelReal.to_biomod(path). This will evaluate the via point conditions at the desired posture (which should be close to the range of motion during the movement studied). If the condition is not meet, the via point is inactive, so it is removed from the model. Please note that this is a destructive operation, once the conditions are evaluated, they are removed from the model and the remaining via points are fixed on the segments.
    • PathPointMovement are not implemented yet in biorbd. So if your BioBuddy model has this components, we recommend running BiomechanicalModelReal.fix_via_points(q) before BiomechanicalModelReal.to_biomod(path). This will fix the position of the moving via points, muscle origin, and muscle insertion by evaluating the position function at the desired posture (which should be close to the range of motion during the movement studied). Please note that this is a destructive operation, once the movements are evaluated, they are removed from the model and the remaining via points are fixed on the segments.

How to cite

@software{biobuddy_2025,
  author       = {Eve Charbonneau, Pierre Puchaud, Teddy Caderby, Mickael Begon, Amedeo Ceglia, Benjamin Michaud},
  title        = {Bringing the musculoskeletal modeling community together with BioBuddy},
  month        = april,
  year         = 2025,
  publisher    = {submitted to Congrès de la Société de biomécanique},
  url          = {https://github.com/pyomeca/biobuddy}
}

How to contribute

Our goal is to support as many musculoskeletal model formats as possible, so do not hesitate to contact us if you'd like to see your favorite format supported by BioBuddy. If you are using BioBuddy and encounter any problem, please open an issue on this GitHub repository. We are also open to suggestions for new features or improvements to existing functionality. All contributions are welcome!

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

biobuddy-0.1.0.tar.gz (167.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

biobuddy-0.1.0-py3-none-any.whl (141.4 kB view details)

Uploaded Python 3

File details

Details for the file biobuddy-0.1.0.tar.gz.

File metadata

  • Download URL: biobuddy-0.1.0.tar.gz
  • Upload date:
  • Size: 167.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for biobuddy-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3e6b0eb3280e872d56945ec986ef7b468f53f4b1b1124c5f899f6fd493e22f30
MD5 58dd92cb923a79420e69d2a2b485c25b
BLAKE2b-256 04e118cb921e65b694c8dbab34bbb91b5031b154dee716da628d88439424e439

See more details on using hashes here.

File details

Details for the file biobuddy-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: biobuddy-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 141.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for biobuddy-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 700489138661c93e5967abdc20e7ca3bd93a299227768cdb3aa83c30aa8f3723
MD5 7e851868a6f245c0a348d6757ab9e19f
BLAKE2b-256 88243a7127ba9beca21c7608cc54cab03ae121c21c844df0a8208874aa7dc509

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page