Skip to main content

pyMSKT (Musculoskeletal Toolkit)

License: MIT
Build Status
|Documentation|

pyMSKT is an open-source library for performing quantitative analyses of the musculoskeletal system. It enables creation of surface meshes of musculoskeletal anatomy and then processes these meshes to get quantitative outcomes and visualizatons, like for cartilage thickness.

Installation

Pip install from pypi

    # create environment
    conda env create -n mskt
    conda activate mskt

    pip install mskt

Conda / pip install from source

    # clone repository
    git clone https://github.com/gattia/pymskt.git
    
    # move into directory
    cd pymskt
    
    # CREATE ENVIRONMENT:
    conda create -n mskt
    conda activate mskt

    # INSTALLING DEPENDENCIES
    # Recommend pip becuase cycpd and pyfocusr are available on pypi (but not conda)
    pip install -r requirements.txt

    # IF USING PIP
    pip install .
  1. Clone this repository & install dependencies:

    # clone repository
    git clone https://github.com/gattia/pymskt.git
    
    # move into directory
    cd pymskt
    
    # CREATE ENVIRONMENT:
    conda env create -n mskt
    conda activate mskt
    
    # Install all available requirements
    conda install --file requirements-conda.txt # pip (below) can alternatively be used to install dependencies in conda env
    
    # Return to root dir
    cd ..
    
  2. Clone cycpd & install: (ONLY NEEDED FOR CONDA INSTALL)

    git clone https://github.com/gattia/cycpd.git
    cd cycpd
    pip install .
    cd ..
    
  3. Clone pyfocusr & install: (ONLY NEEDED FOR CONDA INSTALL)

    git clone https://github.com/gattia/pyfocusr.git
    cd pyfocusr
    pip install .
    cd ..
    
  4. Install pymskt: (ONLY NEEDED FOR CONDA INSTALL)

    cd pymskt
    pip install .
    

Optional Dependencies

itkwidgets (for visualization)

If you are using jupyterlab instead of jupyter notebook, you also need to install an extension:

jupyter labextension install @jupyter-widgets/jupyterlab-manager jupyter-matplotlib jupyterlab-datawidgets itkwidgets

vtkbool (for boolean operations)

For fast and robust mesh boolean operations (union, intersection, difference), install vtkbool:

conda install -c conda-forge vtkbool

Note: vtkbool is only available via conda, not pip. It provides fast boolean operations (~30s for complex meshes) and avoids the memory errors that occur with VTK's native boolean operations.

Usage example:

from pymskt.mesh import Mesh

femur = Mesh('femur.stl')
patella = Mesh('patella.stl')

# Subtract patella from femur
result = femur.boolean_difference(patella)
# Or use standalone function
from pymskt.mesh.meshTools import boolean_difference
result = boolean_difference(femur, patella)

Examples

There are jupyter notebook examples in the directory /examples

pyMSKT allows you to easily create bone meshes and attribute cartilage to the bone for calculating quantitative outcomes.

femur = BoneMesh(path_seg_image=location_seg,  # path to the segmentation image being used.
                 label_idx=5,                  # what is the label of this bone.
                 list_cartilage_labels=[1]) # labels for cartilage associted with bone.   
# Create the bone mesh
femur.create_mesh()
# Calcualte cartialge thickness for the cartialge meshes associated with the bone
femur.calc_cartilage_thickness()
femur.save_mesh(os.path.expanduser'~/Downloads/femur.vtk')

The saved file can be viewed in many mesh viewers such as 3D Slicer or Paraview. Or, better yet they can be viewed in your jupyter notebook using itkwidgets:

from itkwidgets import view

view(geometries=[femur])

After creating the above mesh, creating cartilage subregions & an anatomical coordinate system is as simple as:

# Load in full seg image
seg_image = sitk.ReadImage(location_seg)
# break into sub regions. (weightbearing / trochlea / posterior condyles)
seg_image = mskt.image.cartilage_processing.get_knee_segmentation_with_femur_subregions(seg_image)

# assign femoral condyle cartilage sub regions to femur 
femur.seg_image = seg_image
femur.list_cartilage_labels=[11, 12, 13, 14, 15]
femur.assign_cartilage_regions()

# use cartilage regions to fit cylinder to condyles and create anatomic coordinate system 
femur_acs = FemurACS(femur, cart_label=(11, 12, 13, 14, 15))
femur_acs.fit()

The resulting anatomical coorindate system can be used to create arrows & visualize the result:

AP_arrow = get_arrow(femur_acs.ap_axis, origin=femur_acs.origin )
IS_arrow = get_arrow(femur_acs.is_axis, origin=femur_acs.origin)
ML_arrow = get_arrow(femur_acs.ml_axis, origin=femur_acs.origin)

view(geometries=[femur, AP_arrow, IS_arrow, ML_arrow])
Anatomical Coordinate System - Cartilage Thickness Anatomical Coordinate System - Cartilage Subregions

An example of how the cartilage thickness values are computed:

Meniscal Analysis

Compute meniscal extrusion and coverage metrics:

import pymskt as mskt

# Create tibia with cartilage labels
tibia = mskt.mesh.BoneMesh(
    path_seg_image='tibia.nrrd',
    label_idx=6,
    dict_cartilage_labels={'medial': 2, 'lateral': 3}
)
tibia.create_mesh()
tibia.calc_cartilage_thickness()
tibia.assign_cartilage_regions()

# Create meniscus meshes
med_meniscus = mskt.mesh.Mesh(path_seg_image='tibia.nrrd', label_idx=10)
med_meniscus.create_mesh()

lat_meniscus = mskt.mesh.Mesh(path_seg_image='tibia.nrrd', label_idx=9)
lat_meniscus.create_mesh()

# Set menisci (labels auto-inferred from dict_cartilage_labels)
tibia.set_menisci(medial_meniscus=med_meniscus, lateral_meniscus=lat_meniscus)

# Access metrics (auto-computes on first access)
print(f"Medial extrusion: {tibia.med_men_extrusion:.2f} mm")
print(f"Medial coverage: {tibia.med_men_coverage:.1f}%")
print(f"Lateral extrusion: {tibia.lat_men_extrusion:.2f} mm")
print(f"Lateral coverage: {tibia.lat_men_coverage:.1f}%")

Development / Contributing

General information for contributing can be found here

Tests

  • Running tests requires pytest (conda install pytest or pip install pytest)
  • Run tests using pytest or make test in the home directory.

Coverage

  • Coverage results/info requires coverage (conda install coverage or pip install coverage)
  • Can get coverage statistics by running:
    • coverage run -m pytest or if using make:
    • make coverage

Notes for development

  • When updating cython code, it is not re-built when we re-install using the basic python setup.py install. Therefore we force it to do this:
    • python setup.py build_ext -i --force

Tests

If you add a new function, or functionality to pymskt please add appropriate tests as well. The tests are located in /testing and are organized as: /testing/[pymskt_submodule]/[python_filename_being_tested]/[name_of_function_being_tested]_test.py

The tests use pytest. If you are not familiar with pytest a brief example is provided here.

Currently, 37 tests are being skipped for one of 2 (maybe 3) reasons. 1. They arent implemented yet and they are a placeholder. 2. They rely on a function that has small machine-to-machine differences so they dont pass or 3. A breaking change occured since result meshes were last saved. If you want to help but dont know how or where to start, filling in / fixing these tests would be a great place to start! And greatly appreciated.

Code of Conduct

We have adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community. For more information see the Code of Conduct.

Metadata

Release files for mskt 0.1.22

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mskt 0.1.22
File Size Uploaded Provenance
mskt-0.1.22.tar.gz 92.5 MB Without provenance Details

Release files / mskt-0.1.22.tar.gz

Download URL mskt-0.1.22.tar.gz
Size 92.5 MB
Tags Source
SHA-256 checksum
How to use checksums
b49ffa4924337e28dc08af2e7efab399e9248c9e7db477e593d5d6e254757308
BLAKE2b-256 checksum
How to use checksums
9ca5c7ee3ca88fdba99557aa44853b86be5d4542009d7cede093925b91cee8e9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.8

Security for mskt 0.1.22

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.22 This release

1 release file No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page