voidspace
Spacing-aware voidspace analysis for HR-pQCT segmentations.
voidspace is a standalone logic package. It does not segment bone, register
scans or create common regions. It expects inputs already in the same physical
space. File workflows place cropped masks on the reference grid with
nearest-neighbor resampling using origin, spacing, and direction; this does not
estimate registration between scans.
The command line interface reads common SimpleITK image formats and Scanco AIM masks. AIM masks are read in native scaling, interpreted as foreground where nonzero, and written back as native binary AIM masks using the input geometry.
Workflows
- Cross-sectional: pass a segmented bone image.
- Masked/common-region: pass a segmented bone image and a mask. If both a
periosteal contour and a common region are needed, combine them before calling
voidspace. - Registered: pass an already registered segmentation and optional registered mask.
- Dynamic change: pass already aligned baseline and follow-up voidspace masks.
When no periosteal mask is supplied, the segmentation-only workflow estimates the analysis domain from the closed segmentation by excluding background connected to lateral (in-plane) image borders, not the two scan ends. Supplying an explicit full bone mask remains preferred, especially for breached cortex.
Closing and erosion use edge continuation along the scan axis before cropping back to the acquired volume. This assumes the endpoint cross-sections continue beyond the scan, rather than treating acquisition ends as empty biological space. Physical morphology radii and volume thresholds are unchanged. This boundary policy is not a validation of exact scanner/IPL equivalence.
All voidspace includes large voidspace: the large map is a size-filtered subset.
For common-region reporting, compute maps on the full bone domain with run-case,
then use analyze-maps to clip and measure without recomputing morphology at the
common-region boundaries. Force-rerun old outputs to apply these corrections.
Algorithm
The algorithm follows the original IPL voidspace concept:
- Remove tiny disconnected bone components.
- Close segmented bone to fill normal trabecular spacing.
- Invert the closed bone region to candidate marrow void.
- Erode candidate void away from trabecular surfaces.
- Remove tiny candidate void components.
- Keep all surviving voids and large voids above a physical volume threshold.
Unlike the IPL scripts, morphology uses a spacing-aware spherical or ellipsoidal footprint. The default XtremeCT II settings are:
- closing radius:
0.738 mm - boundary erosion radius:
0.366 mm - minimum large-void volume:
16.5 mm3 - bone and void speckle cleanup:
6 voxels
The original IPL code used 72560 or 72660 voxels as scanner-specific large
void thresholds in different script/paper contexts. This package treats
16.5 mm3 as the default source of truth and converts it from the supplied
image spacing.
CLI
voidspace run-case \
--segmentation seg.AIM \
--mask analysis_domain.AIM \
--output-dir voidspace-out
voidspace analyze-maps \
--large-void voidspace-out/voidspace_large_mask.AIM \
--all-void voidspace-out/voidspace_all_mask.AIM \
--mask common_region.AIM \
--output-dir voidspace-common-region
voidspace compare \
--baseline-void baseline_voidspace_large_mask.AIM \
--followup-void followup_voidspace_large_mask.AIM \
--mask analysis_domain.AIM \
--output-dir voidspace-change
--mask is optional for run-case and compare, and required for
analyze-maps. Use --force to overwrite existing outputs.
Python
from voidspace import VoidspaceParameters, run_case
result = run_case(
segmentation_path="seg.AIM",
mask_path="analysis_domain.AIM",
output_dir="voidspace-out",
parameters=VoidspaceParameters.xtremectii_defaults(),
)
print(result.metrics.volume_mm3)
from voidspace import compare
result = compare(
baseline_void_path="baseline_voidspace_large_mask.AIM",
followup_void_path="followup_voidspace_large_mask.AIM",
mask_path="analysis_domain.AIM",
output_dir="voidspace-change",
)
print(result.metrics.net_change_volume_mm3)
from voidspace import analyze_maps
result = analyze_maps(
large_void_path="voidspace-out/voidspace_large_mask.AIM",
all_void_path="voidspace-out/voidspace_all_mask.AIM",
mask_path="common_region.AIM",
output_dir="voidspace-common-region",
)
print(result.metrics.vstv_percent)
Citation
For cross-sectional voidspace analysis, cite:
Whittier DE, Burt LA, Boyd SK. A new approach for quantifying localized bone loss by measuring void spaces. Bone. 2021 Feb;143:115785. doi: 10.1016/j.bone.2020.115785. Epub 2020 Dec 2. PMID: 33278655.
For dynamic voidspace analysis, cite:
Whittier DE, Walle M, Atkins PR, Collins CJ, Zumstein MA, Christen P, Lippuner K, Müller R. Structural alterations during fracture healing lead to void spaces developing in surrounding bone microarchitecture. Journal of Bone and Mineral Research. 2025 Jun;40(6):791-798. doi: 10.1093/jbmr/zjaf046.
Metadata
Release files for voidspace 0.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| voidspace-0.1.5.tar.gz | 19.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| voidspace-0.1.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 35.5 kB
Release files / voidspace-0.1.5.tar.gz
| Download URL | voidspace-0.1.5.tar.gz |
|---|---|
| Size | 19.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
49f42e66ecf817abd170dfc82f7b012733995a4c6476ecad972747c0c7046625
|
|
BLAKE2b-256 checksum How to use checksums |
301c4f36c3affe2cf890b77650493ec195c26e5d0eea57a17e537079b7687a8c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency logRelease files / voidspace-0.1.5-py3-none-any.whl
| Download URL | voidspace-0.1.5-py3-none-any.whl |
|---|---|
| Size | 15.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
00cd76e585113e9d761931eb1f1163d63a1ac43d743bd1d81211ee9e46468d83
|
|
BLAKE2b-256 checksum How to use checksums |
aaf62184ea1a934344fc83bbb888da221f90a7afbf436a9ae0346c44aab79134
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency log