|
a/README.md |
|
b/README.md |
1 |
# pyMSKT (Musculoskeletal Toolkit) |
1 |
# pyMSKT (Musculoskeletal Toolkit)
|
2 |
<br> |
2 |
<br>
|
3 |
<br> |
3 |
<br>
|
4 |
|[Documentation](https://anthonygattiphd.com/pymskt/)| |
4 |
|[Documentation](https://anthonygattiphd.com/pymskt/)| |
5 |
|
5 |
|
6 |
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. |
6 |
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. |
7 |
|
7 |
|
8 |
<p align="center"> |
8 |
|
9 |
<img src="./images/whole_knee_1.png" width="300"> |
|
|
10 |
</p> |
|
|
11 |
|
|
|
12 |
# Installation |
9 |
# Installation |
13 |
|
10 |
|
14 |
# Pip install from pypi |
11 |
# Pip install from pypi
|
15 |
```bash |
12 |
```bash
|
16 |
# create environment |
13 |
# create environment
|
17 |
conda env create -n mskt |
14 |
conda env create -n mskt
|
18 |
conda activate mskt |
15 |
conda activate mskt |
19 |
|
16 |
|
20 |
pip install mskt |
17 |
pip install mskt
|
21 |
``` |
18 |
``` |
22 |
|
19 |
|
23 |
### Conda / pip install from source |
20 |
### Conda / pip install from source
|
24 |
```bash |
21 |
```bash
|
25 |
# clone repository |
22 |
# clone repository
|
26 |
git clone https://github.com/gattia/pymskt.git |
23 |
git clone https://github.com/gattia/pymskt.git
|
27 |
|
24 |
|
28 |
# move into directory |
25 |
# move into directory
|
29 |
cd pymskt |
26 |
cd pymskt
|
30 |
|
27 |
|
31 |
# CREATE ENVIRONMENT: |
28 |
# CREATE ENVIRONMENT:
|
32 |
conda env create -n mskt |
29 |
conda env create -n mskt
|
33 |
conda activate mskt |
30 |
conda activate mskt |
34 |
|
31 |
|
35 |
# INSTALLING DEPENDENCIES |
32 |
# INSTALLING DEPENDENCIES
|
36 |
# Recommend pip becuase cycpd and pyfocusr are available on pypi (but not conda) |
33 |
# Recommend pip becuase cycpd and pyfocusr are available on pypi (but not conda)
|
37 |
pip install -r requirements.txt |
34 |
pip install -r requirements.txt |
38 |
|
35 |
|
39 |
# IF USING PIP |
36 |
# IF USING PIP
|
40 |
pip install . |
37 |
pip install .
|
41 |
``` |
38 |
``` |
42 |
|
39 |
|
43 |
### Conda only install (not-recommended) |
40 |
### Conda only install (not-recommended) |
44 |
|
41 |
|
45 |
1. Clone this repository & install dependencies: <br> |
42 |
1. Clone this repository & install dependencies: <br>
|
46 |
```bash |
43 |
```bash
|
47 |
# clone repository |
44 |
# clone repository
|
48 |
git clone https://github.com/gattia/pymskt.git |
45 |
git clone https://github.com/gattia/pymskt.git
|
49 |
|
46 |
|
50 |
# move into directory |
47 |
# move into directory
|
51 |
cd pymskt |
48 |
cd pymskt
|
52 |
|
49 |
|
53 |
# CREATE ENVIRONMENT: |
50 |
# CREATE ENVIRONMENT:
|
54 |
conda env create -n mskt |
51 |
conda env create -n mskt
|
55 |
conda activate mskt |
52 |
conda activate mskt |
56 |
|
53 |
|
57 |
# Install all available requirements |
54 |
# Install all available requirements
|
58 |
conda install --file requirements-conda.txt # pip (below) can alternatively be used to install dependencies in conda env |
55 |
conda install --file requirements-conda.txt # pip (below) can alternatively be used to install dependencies in conda env
|
59 |
|
56 |
|
60 |
# Return to root dir |
57 |
# Return to root dir
|
61 |
cd .. |
58 |
cd ..
|
62 |
|
59 |
|
63 |
``` |
60 |
``` |
64 |
|
61 |
|
65 |
2. Clone cycpd & install: (ONLY NEEDED FOR CONDA INSTALL)<br> |
62 |
2. Clone cycpd & install: (ONLY NEEDED FOR CONDA INSTALL)<br>
|
66 |
```bash |
63 |
```bash
|
67 |
git clone https://github.com/gattia/cycpd.git |
64 |
git clone https://github.com/gattia/cycpd.git
|
68 |
cd cycpd |
65 |
cd cycpd
|
69 |
pip install . |
66 |
pip install .
|
70 |
cd .. |
67 |
cd ..
|
71 |
``` |
68 |
```
|
72 |
3. Clone pyfocusr & install: (ONLY NEEDED FOR CONDA INSTALL)<br> |
69 |
3. Clone pyfocusr & install: (ONLY NEEDED FOR CONDA INSTALL)<br>
|
73 |
```bash |
70 |
```bash
|
74 |
git clone https://github.com/gattia/pyfocusr.git |
71 |
git clone https://github.com/gattia/pyfocusr.git
|
75 |
cd pyfocusr |
72 |
cd pyfocusr
|
76 |
pip install . |
73 |
pip install .
|
77 |
cd .. |
74 |
cd ..
|
78 |
``` |
75 |
```
|
79 |
4. Install pymskt: (ONLY NEEDED FOR CONDA INSTALL)<br> |
76 |
4. Install pymskt: (ONLY NEEDED FOR CONDA INSTALL)<br>
|
80 |
```bash |
77 |
```bash
|
81 |
cd pymskt |
78 |
cd pymskt
|
82 |
pip install . |
79 |
pip install .
|
83 |
``` |
80 |
``` |
84 |
|
81 |
|
85 |
|
82 |
|
86 |
### To install itkwidgets (for visualization): |
83 |
### To install itkwidgets (for visualization):
|
87 |
If you are using jupyterlab instead of jupyter notebook, you also need to install an extension: |
84 |
If you are using jupyterlab instead of jupyter notebook, you also need to install an extension:
|
88 |
``` |
85 |
```
|
89 |
jupyter labextension install @jupyter-widgets/jupyterlab-manager jupyter-matplotlib jupyterlab-datawidgets itkwidgets |
86 |
jupyter labextension install @jupyter-widgets/jupyterlab-manager jupyter-matplotlib jupyterlab-datawidgets itkwidgets
|
90 |
``` |
87 |
``` |
91 |
|
88 |
|
92 |
# Examples |
89 |
# Examples
|
93 |
There are jupyter notebook examples in the directory `/examples` |
90 |
There are jupyter notebook examples in the directory `/examples` |
94 |
|
91 |
|
95 |
pyMSKT allows you to easily create bone meshes and attribute cartilage to the bone for calculating quantitative outcomes. |
92 |
pyMSKT allows you to easily create bone meshes and attribute cartilage to the bone for calculating quantitative outcomes. |
96 |
|
93 |
|
97 |
```python |
94 |
```python
|
98 |
femur = BoneMesh(path_seg_image=location_seg, # path to the segmentation image being used. |
95 |
femur = BoneMesh(path_seg_image=location_seg, # path to the segmentation image being used.
|
99 |
label_idx=5, # what is the label of this bone. |
96 |
label_idx=5, # what is the label of this bone.
|
100 |
list_cartilage_labels=[1]) # labels for cartilage associted with bone. |
97 |
list_cartilage_labels=[1]) # labels for cartilage associted with bone.
|
101 |
# Create the bone mesh |
98 |
# Create the bone mesh
|
102 |
femur.create_mesh() |
99 |
femur.create_mesh()
|
103 |
# Calcualte cartialge thickness for the cartialge meshes associated with the bone |
100 |
# Calcualte cartialge thickness for the cartialge meshes associated with the bone
|
104 |
femur.calc_cartilage_thickness() |
101 |
femur.calc_cartilage_thickness()
|
105 |
femur.save_mesh(os.path.expanduser'~/Downloads/femur.vtk') |
102 |
femur.save_mesh(os.path.expanduser'~/Downloads/femur.vtk')
|
106 |
``` |
103 |
```
|
107 |
The saved file can be viewed in many mesh viewers such as [3D Slicer](https://www.slicer.org/) or [Paraview](https://www.paraview.org/). Or, better yet they can be viewed in your jupyter notebook using [itkwidgets](https://pypi.org/project/itkwidgets/): |
104 |
The saved file can be viewed in many mesh viewers such as [3D Slicer](https://www.slicer.org/) or [Paraview](https://www.paraview.org/). Or, better yet they can be viewed in your jupyter notebook using [itkwidgets](https://pypi.org/project/itkwidgets/):
|
108 |
```python |
105 |
```python
|
109 |
from itkwidgets import view |
106 |
from itkwidgets import view |
110 |
|
107 |
|
111 |
view(geometries=[femur.mesh]) |
108 |
view(geometries=[femur.mesh])
|
112 |
``` |
109 |
``` |
113 |
|
110 |
|
114 |
 |
111 |
 |
115 |
|
112 |
|
116 |
After creating the above mesh, creating cartilage subregions & an anatomical coordinate |
113 |
After creating the above mesh, creating cartilage subregions & an anatomical coordinate
|
117 |
system is as simple as: |
114 |
system is as simple as: |
118 |
|
115 |
|
119 |
```python |
116 |
```python
|
120 |
# Load in full seg image |
117 |
# Load in full seg image
|
121 |
seg_image = sitk.ReadImage(location_seg) |
118 |
seg_image = sitk.ReadImage(location_seg)
|
122 |
# break into sub regions. (weightbearing / trochlea / posterior condyles) |
119 |
# break into sub regions. (weightbearing / trochlea / posterior condyles)
|
123 |
seg_image = mskt.image.cartilage_processing.get_knee_segmentation_with_femur_subregions(seg_image) |
120 |
seg_image = mskt.image.cartilage_processing.get_knee_segmentation_with_femur_subregions(seg_image) |
124 |
|
121 |
|
125 |
# assign femoral condyle cartilage sub regions to femur |
122 |
# assign femoral condyle cartilage sub regions to femur
|
126 |
femur.seg_image = seg_image |
123 |
femur.seg_image = seg_image
|
127 |
femur.list_cartilage_labels=[11, 12, 13, 14, 15] |
124 |
femur.list_cartilage_labels=[11, 12, 13, 14, 15]
|
128 |
femur.assign_cartilage_regions() |
125 |
femur.assign_cartilage_regions() |
129 |
|
126 |
|
130 |
# use cartilage regions to fit cylinder to condyles and create anatomic coordinate system |
127 |
# use cartilage regions to fit cylinder to condyles and create anatomic coordinate system
|
131 |
femur_acs = FemurACS(femur, cart_label=(11, 12, 13, 14, 15)) |
128 |
femur_acs = FemurACS(femur, cart_label=(11, 12, 13, 14, 15))
|
132 |
femur_acs.fit() |
129 |
femur_acs.fit()
|
133 |
``` |
130 |
``` |
134 |
|
131 |
|
135 |
The resulting anatomical coorindate system can be used to create arrows & visualize the result: |
132 |
The resulting anatomical coorindate system can be used to create arrows & visualize the result: |
136 |
|
133 |
|
137 |
```python |
134 |
```python
|
138 |
AP_arrow = get_arrow(femur_acs.ap_axis, origin=femur_acs.origin ) |
135 |
AP_arrow = get_arrow(femur_acs.ap_axis, origin=femur_acs.origin )
|
139 |
IS_arrow = get_arrow(femur_acs.is_axis, origin=femur_acs.origin) |
136 |
IS_arrow = get_arrow(femur_acs.is_axis, origin=femur_acs.origin)
|
140 |
ML_arrow = get_arrow(femur_acs.ml_axis, origin=femur_acs.origin) |
137 |
ML_arrow = get_arrow(femur_acs.ml_axis, origin=femur_acs.origin) |
141 |
|
138 |
|
142 |
view(geometries=[femur.mesh, AP_arrow, IS_arrow, ML_arrow]) |
139 |
view(geometries=[femur.mesh, AP_arrow, IS_arrow, ML_arrow])
|
143 |
``` |
140 |
```
|
144 |
|*Anatomical Coordinate System - Cartilage Thickness* | *Anatomical Coordinate System - Cartilage Subregions* | |
141 |
|*Anatomical Coordinate System - Cartilage Thickness* | *Anatomical Coordinate System - Cartilage Subregions* |
|
145 |
|:---: |:---: | |
142 |
|:---: |:---: |
|
146 |
| |  | |
143 |
| |  | |
147 |
|
144 |
|
148 |
|
145 |
|
149 |
An example of how the cartilage thickness values are computed: |
146 |
An example of how the cartilage thickness values are computed: |
150 |
|
147 |
|
151 |
 |
148 |
 |
152 |
|
149 |
|
153 |
|
150 |
|
154 |
# Development / Contributing |
151 |
# Development / Contributing
|
155 |
General information for contributing can be found [here](https://github.com/gattia/pymskt/blob/main/CONTRIBUTING.md) |
152 |
General information for contributing can be found [here](https://github.com/gattia/pymskt/blob/main/CONTRIBUTING.md) |
156 |
|
153 |
|
157 |
## Tests |
154 |
## Tests
|
158 |
- Running tests requires pytest (`conda install pytest` or `pip install pytest`) |
155 |
- Running tests requires pytest (`conda install pytest` or `pip install pytest`)
|
159 |
- Run tests using `pytest` or `make test` in the home directory. |
156 |
- Run tests using `pytest` or `make test` in the home directory. |
160 |
|
157 |
|
161 |
## Coverage |
158 |
## Coverage
|
162 |
- Coverage results/info requires `coverage` (`conda install coverage` or `pip install coverage`) |
159 |
- Coverage results/info requires `coverage` (`conda install coverage` or `pip install coverage`)
|
163 |
- Can get coverage statistics by running: |
160 |
- Can get coverage statistics by running:
|
164 |
- `coverage run -m pytest` |
161 |
- `coverage run -m pytest`
|
165 |
or if using make: |
162 |
or if using make:
|
166 |
- `make coverage` |
163 |
- `make coverage` |
167 |
|
164 |
|
168 |
## Notes for development |
165 |
## Notes for development
|
169 |
- 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: |
166 |
- 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:
|
170 |
- `python setup.py build_ext -i --force` |
167 |
- `python setup.py build_ext -i --force` |
171 |
|
168 |
|
172 |
### Tests |
169 |
### Tests
|
173 |
If you add a new function, or functionality to `pymskt` please add appropriate tests as well. |
170 |
If you add a new function, or functionality to `pymskt` please add appropriate tests as well.
|
174 |
The tests are located in `/testing` and are organized as: |
171 |
The tests are located in `/testing` and are organized as:
|
175 |
`/testing/[pymskt_submodule]/[python_filename_being_tested]/[name_of_function_being_tested]_test.py` |
172 |
`/testing/[pymskt_submodule]/[python_filename_being_tested]/[name_of_function_being_tested]_test.py` |
176 |
|
173 |
|
177 |
The tests use `pytest`. If you are not familiar with `pytest` a brief example is provided [here](https://docs.pytest.org/en/6.2.x/getting-started.html). |
174 |
The tests use `pytest`. If you are not familiar with `pytest` a brief example is provided [here](https://docs.pytest.org/en/6.2.x/getting-started.html). |
178 |
|
175 |
|
179 |
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. |
176 |
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. |
180 |
|
177 |
|
181 |
## Code of Conduct |
178 |
## Code of Conduct
|
182 |
We have adopted the code of conduct defined by the [Contributor Covenant](https://www.contributor-covenant.org) to clarify expected behavior in our community. For more information see the [Code of Conduct](https://github.com/gattia/pymskt/blob/main/CODE_OF_CONDUCT.md). |
179 |
We have adopted the code of conduct defined by the [Contributor Covenant](https://www.contributor-covenant.org) to clarify expected behavior in our community. For more information see the [Code of Conduct](https://github.com/gattia/pymskt/blob/main/CODE_OF_CONDUCT.md).
|