Skip to content

Commit

Permalink
Merge pull request #20 from SpectraCollab/main
Browse files Browse the repository at this point in the history
Merge main into test branch
  • Loading branch information
mkuczyns authored Apr 10, 2024
2 parents 4677400 + 380e4f8 commit 50016cf
Show file tree
Hide file tree
Showing 71 changed files with 12,592 additions and 1,537 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/draft-pdf.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
on: [push]

jobs:
paper:
runs-on: ubuntu-latest
name: ORMIR_XCT Paper Draft
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Build draft PDF
uses: openjournals/openjournals-draft-action@master
with:
journal: joss
paper-path: manuscript/paper.md
- name: Upload
uses: actions/upload-artifact@v1
with:
name: ORMIR_XCT Paper Draft
path: manuscript/paper.pdf
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,18 @@
# ORMIR_2022
This project was partially developed during the Jupyter Community Workshop “Building the Jupyter Community in Musculoskeletal Imaging Research”.
ORMIR_XCT is a Python package for processing high resolution peripheral computed tomography (HR-pQCT) scans. Development of this project began during the “Building the Jupyter Community in Musculoskeletal Imaging Research” workshop hosted by the Open and Reproducible Musculoskeletal Imaging Research (ORMIR) group.

## Installation
### Step 1: Install the ORMIR_XCT Anaconda Environment:
`conda env create -f environment.yml`

If using an Apple M1, M2, or M3 processor, run the following command instead:
`CONDA_SUBDIR=osx-64 conda env create -f environment.yml`

### Step 2: Activate the Anaconda Environment:
`conda activate ormir_xct`

### Step 3: Install the Package:
`pip install -e .`

### Step 4: Run Scripts:
The modules in the `ormir_xct` directory can now be run. Examples for each module are provided in the `examples` directory.
17 changes: 9 additions & 8 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ channels:
dependencies:
- itkwidgets=0.32.0
- numpy=1.23.3
- pandas=2.0.3
- pbr=5.4.2
- pip=21.2.4
- python=3.8.5
Expand All @@ -16,14 +17,14 @@ dependencies:
- simpleitk=2.0.2
- vtk=9.0.1
- pip:
- itk==5.2.1
- itk-core==5.2.1
- itk-filtering==5.2.1
- itk-io==5.2.1
- itk==5.3.0
- itk-core==5.3.0
- itk-filtering==5.3.0
- itk-io==5.3.0
- itk-ioscanco==0.9.2
- itk-numerics==5.2.1
- itk-registration==5.2.1
- itk-segmentation==5.2.1
- itk-numerics==5.3.0
- itk-registration==5.3.0
- itk-segmentation==5.3.0
- notebook==6.5.2
- numba==0.56.3
- kimimaro==3.3.0
- kimimaro==3.3.0
267 changes: 267 additions & 0 deletions examples/Automatic_Contour_Example.ipynb

Large diffs are not rendered by default.

165 changes: 165 additions & 0 deletions examples/Bone_Mineral_Density_Example.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "efbca20e",
"metadata": {},
"source": [
"# Bone Mineral Density Example\n",
"\n",
"This Jupyter Notebook provides an example of computing volumetric bone mineral density (vBMD) in an HR-pQCT joint image. vBMD is computed in the distal and proximal segments. The ORMIR_XCT autocontour script is used to generate the bone masks."
]
},
{
"cell_type": "markdown",
"id": "bcdc9bff",
"metadata": {},
"source": [
"# Step 1: Imports\n",
"\n",
"Import modules/packages and set the input image path. "
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "455536d4",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import numpy as np\n",
"import SimpleITK as sitk\n",
"\n",
"from matplotlib import pyplot as plt\n",
"\n",
"from ormir_xct.bone_mineral_density.bmd import bmd\n",
"from ormir_xct.bone_mineral_density.bmd_masked import bmd_masked\n",
"from ormir_xct.autocontour.autocontour import autocontour"
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "ed021614",
"metadata": {},
"outputs": [],
"source": [
"joint_seg_path = os.path.join(\"images\", \"GRAY_JOINT.nii\")\n",
"\n",
"gray_img = sitk.ReadImage(joint_seg_path, sitk.sitkFloat32)"
]
},
{
"cell_type": "markdown",
"id": "fbdc7d4f",
"metadata": {},
"source": [
"# Step 2: Run the ORMIR_XCT Automatic Contour\n",
"\n",
"Run the ORMIR_XCT automatic periosteal contour script on the input grayscale joint image. This script will return the distal, proximal, and full joint mask.\n",
"\n",
"When running the ORMIR_XCT automatic contour script, we need to provide the image units and parameters for unit conversion to get an accurate segmentation. Since we are using an AIM/ISQ image that has been converted to another file type using the ITKIOScanco module from ITK, the image units are Hounsfield Units (HU). For the sample image provided, the follow parameters taken from the AIM header are used:\n",
"\n",
"- mu_water = 0.24090\n",
"- mu_scaling = 8192\n",
"- resale_slope = 1603.51904 \n",
"- rescale_intercept = -391.209015\n",
"\n",
"These values may vary depending on your scanner."
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "ffc8695d",
"metadata": {},
"outputs": [],
"source": [
"mu_water = 0.24090\n",
"mu_scaling = 8192\n",
"rescale_slope = 1603.51904 \n",
"rescale_intercept = -391.209015\n",
"\n",
"dst_mask, prx_mask, ormir_mask = autocontour(gray_img, mu_water, rescale_slope, rescale_intercept)"
]
},
{
"cell_type": "markdown",
"id": "b81b793e",
"metadata": {},
"source": [
"# Step 3: Compute vBMD\n",
"\n",
"Now computed vBMD. We will calculate the vBMD for each bone segment."
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "a14d4d74",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Distal vBMD: 193.18 +/- 205.73 mg HA/cm^3\n",
"Proximal vBMD: 227.12 +/- 240.44 mg HA/cm^3\n"
]
}
],
"source": [
"# First mask the image with the distal and proximal joint masks\n",
"\n",
"# Distal vBMD\n",
"masked_gray_img = sitk.Mask(gray_img, dst_mask)\n",
"dst_bmd = bmd_masked(masked_gray_img, dst_mask, 'hu', mu_scaling, mu_water, rescale_slope, rescale_intercept)\n",
"\n",
"print('Distal vBMD: {:.2f} +/- {:.2f} mg HA/cm^3'.format(dst_bmd[0], dst_bmd[1]))\n",
"\n",
"\n",
"# Proximal vBMD\n",
"prx_gray_img = sitk.Mask(gray_img, prx_mask)\n",
"prx_bmd = bmd_masked(masked_gray_img, prx_mask, 'hu', mu_scaling, mu_water, rescale_slope, rescale_intercept)\n",
"\n",
"print('Proximal vBMD: {:.2f} +/- {:.2f} mg HA/cm^3'.format(prx_bmd[0], prx_bmd[1]))"
]
},
{
"cell_type": "markdown",
"id": "747bf6db",
"metadata": {},
"source": [
"# Step 4: Compare Between IPL and ORMIR_XCT\n",
"\n",
"Now compare vBMD results between IPL and ORMIR_XCT.\n",
"\n",
"The vBMD results from IPL have been pre-generated and are provided as:\n",
"- **Distal vBMD:** 203.84 +/- 212.96 mg HA/cm^3\n",
"- **Proximal vBMD:** 224.20 +/- 240.37 mg HA/cm^3"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
260 changes: 260 additions & 0 deletions examples/Trabecular_Segmentation_Example.ipynb

Large diffs are not rendered by default.

Loading

0 comments on commit 50016cf

Please sign in to comment.