Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

exacta

Metrics and differentiable losses for 2D and 3D medical-image segmentation, on CPU and GPU. Exacta provides reusable implementations of Dice, HD95, surface distances, lesion scores, probability metrics and training objectives, with explicit mathematical conventions.

CPU operations use C++ kernels where implemented; CUDA paths use Triton or native PyTorch. Definitions are checked against independent references such as SciPy, MONAI, MedPy, DeepMind's surface-distance, MeshMetrics, SimpleITK, Panoptica and the BraTS 2023 evaluation code. Where conventions differ, parameters select the intended definition.

Version: 0.0.1a5 (alpha). Documentation · Source · Issues

Installation

Exacta requires Python 3.10+, PyTorch 2.4+ and NumPy 1.22+. Install PyTorch for your CPU or CUDA environment, then install Exacta:

python -m pip install exacta==0.0.1a5

Binary wheels target Linux x86-64 with glibc 2.28 or newer: Python 3.10 and 3.11 wheels, plus a Python 3.12 stable-ABI wheel for Python 3.12 and newer. Other platforms install from source and require a C++17 compiler and Python development headers; OpenMP is optional. SciPy is an optional dependency for Hungarian lesion matching.

For distributed CPU evaluation with Gloo, use PyTorch 2.8+ to avoid an older process-group teardown deadlock. Multi-GPU NCCL support remains experimental.

Quickstart

Train with logits and evaluate hard labels. This synthetic 3D example runs on the available CPU or CUDA device; it demonstrates the API, not model accuracy:

import torch
import exacta.functional as EF
from exacta.losses import DiceCELoss

rng = torch.Generator().manual_seed(7)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
logits = torch.randn((2, 3, 16, 24, 24), generator=rng).to(device).requires_grad_()
target = torch.zeros((2, 16, 24, 24), dtype=torch.long, device=device)
target[:, 3:8, 4:12, 5:13] = 1
target[:, 9:13, 12:20, 12:20] = 2

loss = DiceCELoss(include_background=False)(logits, target)
loss.backward()

prediction = logits.detach().argmax(dim=1)
scores = EF.evaluate(
    prediction, target, num_classes=3, include_background=False,
    spacing=(1.5, 0.8, 0.8),  # spatial-axis order, in mm
    metrics={"dice": {}, "hd95": {}, "nsd": {"tolerance": 1.0}},
)
print("Loss:", loss.item())
print("Dice per case/class:", scores["dice"])  # shape (2, 2)
print("HD95 in mm:", scores["hd95"])

For 2D images, use logits (B,C,H,W), integer targets (B,H,W) and two-axis spacing. For independent overlapping labels, supported losses use activation="sigmoid" and target_format="one-hot" with same-shaped binary targets. The 2D medical-segmentation guide includes binary, multiclass and multilabel examples.

Metrics

Stateless functions live in exacta.functional. Their stateful counterparts in exacta.metrics accumulate across batches and support distributed evaluation.

Category Metrics
Overlap Dice / voxel F1; IoU / Jaccard
Classification rates Sensitivity / recall; precision; specificity
Relative size Volume similarity; signed or absolute relative volume difference
Physical size Predicted/target 3D volume and error in mm³ or mL; 2D area and error in mm² or cm²
Boundaries Hausdorff distance with configurable percentile; HD95; ASSD; normalized surface Dice (NSD)
Centreline Hard-skeleton clDice
Probability quality Brier score; negative log-likelihood (NLL)
Calibration Expected calibration error (ECE); reliability diagrams
Voxel ranking Average precision (AP); AUROC; precision–recall and ROC curves, exact or approximately binned
Lesion matching Lesion TP/FP/FN, precision, recall, F1, segmentation quality and panoptic quality
Lesion segmentation Lesion-wise Dice and HD95; BraTS 2023 evaluation conventions
Confidence-ranked detection Lesion AP and FROC curves

Use exacta.lesions.evaluate for lesion matching and exacta.detection.LesionDetection for confidence-ranked detection. Connected-component labeling, largest-component selection and small-component removal are available in exacta.components.

functional.evaluate and MetricCollection share confusion counts and compatible surface distances when evaluating multiple metrics. For accumulation across validation batches:

from exacta.metrics import MetricCollection

metrics = MetricCollection(
    metrics={"dice": {}, "hd95": {}}, num_classes=3, include_background=False,
)
metrics.update(prediction, target, spacing=(1.5, 0.8, 0.8))
result = metrics.compute()["dice"]
print(result.per_case, result.per_class, result.mean)
metrics.reset()

Functional APIs accept PyTorch, NumPy, CuPy and JAX arrays and return the prediction's array type. Stateful APIs use PyTorch. See Metrics and Lesion evaluation for arguments, formulas and matching protocols.

Training losses

Losses are PyTorch modules in exacta.losses. Choose the objective and target representation explicitly; different loss definitions produce different gradients.

Category Classes
Overlap DiceLoss, GeneralizedDiceLoss, TverskyLoss, FocalTverskyLoss
Class-confusion costs GeneralizedWassersteinDiceLoss
Voxel classification FocalLoss, TopKCELoss
Combined objectives DiceCELoss, DiceFocalLoss, GeneralizedDiceCELoss, DiceTopKCELoss
IoU surrogates LovaszSoftmaxLoss, LovaszHingeLoss
Boundary objectives BoundaryLoss, HausdorffDTLoss
Soft centreline objective SoftClDiceLoss

DeepSupervisionLoss combines a loss across explicitly paired prediction/target resolutions. DiceLoss(squared_pred=True) uses a squared denominator; Dice–CE, Dice–focal and Dice–top-k CE support the same option. Generalized Dice supports inverse-square, inverse-volume and uniform class weights. Standard cross-entropy and binary cross-entropy remain available in PyTorch.

Wasserstein Dice accepts integer labels and a symmetric, nonnegative class-cost matrix with zero diagonal and a positive maximum. The matrix is normalized by that maximum. Default weighting requires maximal background/foreground costs; weighting_mode="GDL" uses inverse observed class counts. These costs describe label confusion, not spatial distance.

HausdorffDTLoss is a distance-transform training surrogate, not HD95. Soft-clDice uses a finite-iteration soft skeleton and differs from the hard clDice evaluation metric. Geometry and topology objectives require complete target geometry; combine them with regional supervision where appropriate. See Losses for equations, smoothing, reductions, target formats and derivative support.

Partial annotations and probability channels

Overlap, area and volume metrics accept shared boolean voxel masks and index-target ignore_index. Excluded voxels contribute to none of TP, FP, FN or TN:

partial_target = target.clone()
partial_target[:, :2] = -1
observed_dice = EF.dice(
    prediction, partial_target, num_classes=3, include_background=False, ignore_index=-1,
)

Surface and hard-clDice metrics require complete segmentations: removing voxels would change boundaries or topology. Loss masking follows each objective's documented rules.

Brier, NLL, ECE, reliability diagrams and voxel rankings support multilabel=True for independent probability channels with same-shaped binary targets. Logit inputs then use independent sigmoids. Shared or per-label masks and explicit macro/micro reductions are available where documented.

Mathematical conventions

Specify the definition as part of your evaluation protocol. Empty inputs, aggregation and surface representations can change reported values even for identical segmentations.

Choice Default and options
Hard labels Index maps with num_classes, or binary channels with input_format="one-hot"; overlapping channels are allowed.
Background Channel/class zero is included unless include_background=False.
Spacing Spatial-axis order of the array; physical area/volume inputs use millimetres.
Surfaces Boundary voxel centres by default; surface="surfels" uses physical length/area weights, and "mesh" uses contour/triangle geometry.
HD95 Maximum of the two directed 95th percentiles; combine="pooled" instead pools distances before the percentile.
ASSD Pooled surface-element mean; combine="mean" averages the two directed means.
Empty masks Dice/IoU return NaN when both are empty; distance metrics default to infinity when exactly one is empty, except NSD, which returns zero. Parameters make these policies explicit.
Case aggregation Stateful per-case metrics skip NaNs, average cases per class, then average class means.
Pooled evaluation Calibration pools voxel bins; VoxelRanking pools voxel rankings. Case averages and pooled scores are different quantities.
AP Non-interpolated sum of recall increments times precision, not trapezoidal PR area. No-positive AP and single-outcome AUROC are NaN.

For distributed evaluation, every rank must participate in compute(), including ranks with no local cases. Avoid samplers that duplicate cases through padding. See Conventions for full definitions, reference-library variants and empty-input behavior.

Performance

Backend choice depends on shape, class count, dtype and hardware. Supported metric passes use C++/OpenMP on CPU and Triton on CUDA. Training losses use native PyTorch and, for supported objectives, fused Triton forward/backward. torch.compile can improve native PyTorch paths; measure complete forward/backward cost and account for compilation startup.

Mesh distances and hard skeletonization run on CPU, including transfers for CUDA inputs. Lesion matching uses CPU lesion tables. The CPU extension is independent of the PyTorch binary version. See Performance for measured workloads, memory behavior and backend limitations.

License

Apache License 2.0; see the license, notices and third-party licenses.

Metadata

Release files for exacta 0.0.1a5

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

Source distribution (sdist)

Source distribution for exacta 0.0.1a5
File Size Uploaded Provenance
exacta-0.0.1a5.tar.gz 139.6 kB With provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for exacta 0.0.1a5
File Interpreter ABI Platform
exacta-0.0.1a5-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.12 abi3 Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 Details
exacta-0.0.1a5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.27+ x86-64, Linux glibc 2.28+ x86-64 Details
exacta-0.0.1a5-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 Details

Total release size: 1.3 MB

Release files / exacta-0.0.1a5.tar.gz

Download URL exacta-0.0.1a5.tar.gz
Size 139.6 kB
Tags Source
SHA-256 checksum
How to use checksums
cbfc503cbfc7cb6d7276ca45ed9fa660c86c7c82d9830f5b1321a2b79a2b388f
BLAKE2b-256 checksum
How to use checksums
03ef876e9abc75e439abe334c2522f0758eb8a9087a47330db1e90675788354e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 26, 2026.

Transparency log

Release files / exacta-0.0.1a5-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL exacta-0.0.1a5-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 396.6 kB
Tags CPython 3.12 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
723b4d61ead1c744b9995bcb4fdbf24ef8623ed3694133254323b58f99d74ccb
BLAKE2b-256 checksum
How to use checksums
dbae9c67cd338c5947586f131d80d55cb8468e0906355d0c359db92f55e7bd43
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 26, 2026.

Transparency log

Release files / exacta-0.0.1a5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL exacta-0.0.1a5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 400.6 kB
Tags CPython 3.11 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
c1f080a186e1457c08c626ee0984c5f90a81426b1aad3d30cc3a21b6beb143de
BLAKE2b-256 checksum
How to use checksums
cfcaef1ca579f3c9c0e6539bfc70bb21978748dd50cfe8d4aa9f5fb3ad1b2722
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 26, 2026.

Transparency log

Release files / exacta-0.0.1a5-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL exacta-0.0.1a5-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 400.9 kB
Tags CPython 3.10 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
2e97ba2a7bb45dfae448984602755b4733782bc1266dffef076db4c5837562c9
BLAKE2b-256 checksum
How to use checksums
4c81575056c74fa51672708843718643570bdda86fd9a33c2068c9f2a4c8b347
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 26, 2026.

Transparency log

Security for exacta 0.0.1a5

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.

Full provenance

All 4 files in this release have been uploaded with provenance metadata.

Select from 4 files

Attestation for exacta-0.0.1a5.tar.gz

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 26, 2026.

Transparency log

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.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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