fdg-pet-ct-mlx
Native MLX FDG PET synthesis for Apple Silicon. Turn a CT and its organ labels into a synthetic FDG PET (SUV) volume, locally on Mac.
- Organ-level FDG activity from a label map
- Scanner blur, scatter, randoms and count noise
- Optional lesion uptake
- FP32 using MLX; every random draw is controlled by an explicit integer seed
Part of MedMLX. Technical notes
Quick start · Input and output · Technical details · License
Requirements
Apple Silicon Mac with Metal, Python 3.13 or 3.14 and uv. No model weights are needed.
Quick start
Install the current source branch:
uv pip install "fdg-pet-ct-mlx @ git+https://github.com/MedMLX/fdg-pet-ct-mlx.git"
Organ and scanner settings are passed as profile objects; any object with the fields below works. This example uses simple dataclasses and a synthetic volume:
from collections.abc import Mapping
from dataclasses import dataclass
import mlx.core as mx
from fdg_pet_ct_mlx.acquisition import apply_acquisition_model
from fdg_pet_ct_mlx.activity import synthesize_activity_map
@dataclass(frozen=True)
class Tissue:
suv_mean: float
suv_std: float
maisi_labels: tuple[int, ...]
@dataclass(frozen=True)
class Organs:
tissues: Mapping[str, Tissue]
def lookup_table(self, size: int) -> tuple[float, ...]:
table = [self.tissues["unclassified_soft_tissue"].suv_mean] * size
for tissue in self.tissues.values():
for label in tissue.maisi_labels:
if label < size:
table[label] = tissue.suv_mean
return tuple(table)
@dataclass(frozen=True)
class Scanner:
scatter_fraction: float = 0.05
randoms_fraction: float = 0.02
fwhm_mm: tuple[float, float, float] = (5.0, 5.0, 5.0)
counts_per_suv: float = 100.0
organ = Organs({
"background": Tissue(0.0, 0.0, (0,)),
"unclassified_soft_tissue": Tissue(1.0, 0.1, (1,)),
})
labels = mx.ones((16, 16, 16), dtype=mx.int32)
ct_hu = mx.zeros(labels.shape, dtype=mx.float32)
activity = synthesize_activity_map(labels, organ, seed=7, mx=mx)
pet = apply_acquisition_model(
activity,
ct_hu,
scanner=Scanner(),
count_level=1.0,
spacing_mm=(2.0, 2.0, 2.0),
seed=8,
mx=mx,
)
mx.eval(pet)
print(pet.shape, pet.dtype) # (16, 16, 16), float32
Input and output
Inputs are a nonnegative integer label volume and a CT volume in HU on the same 3D grid. Organ profiles give each tissue's SUV mean, standard deviation and label values; scanner profiles give resolution (FWHM), scatter, randoms and counts.
The output is a float32 SUVbw MLX array with the input shape. To add lesions, use
fdg_pet_ct_mlx.lesion.apply_lesion_uptake with a lesion profile.
Profile validation, resampling and file I/O are up to you. This is image-space synthesis; it does not simulate projection physics or reconstruction.
Technical details
Activity synthesis and scanner effects operate on MLX arrays in float32. The acquisition model approximates blur, scatter, randoms and count noise in image space. Profiles, numerical contracts and development commands are described in docs/technical.md.
Intended use
Research software, for research and education only; not for clinical diagnosis or treatment decisions. The output is a synthetic image from a simple image-space model, not a simulation of a real scanner. Outputs require human review.
License
Apache-2.0; see LICENSE. See THIRD_PARTY_NOTICES.md for dependency attribution.
Implementation mapping
Central implementation map records upstream-to-native changes, source references and qualification scope.
Metadata
Release files for fdg-pet-ct-mlx 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| fdg_pet_ct_mlx-0.2.1.tar.gz | 14.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fdg_pet_ct_mlx-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.6 kB
Release files / fdg_pet_ct_mlx-0.2.1.tar.gz
| Download URL | fdg_pet_ct_mlx-0.2.1.tar.gz |
|---|---|
| Size | 14.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2c19451e6dbdf3346ec5d0d2e423b49757da3303842f5cb3601eb5733294b74d
|
|
BLAKE2b-256 checksum How to use checksums |
c639e0b510c013d0f6d126d970912ba349b1fbb401077840facf914d069e3a62
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.17
|
Release files / fdg_pet_ct_mlx-0.2.1-py3-none-any.whl
| Download URL | fdg_pet_ct_mlx-0.2.1-py3-none-any.whl |
|---|---|
| Size | 17.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b0cc0eaba9f504d163d4c7118b0c51672e9362ed6ea632c71de947cb7f03385a
|
|
BLAKE2b-256 checksum How to use checksums |
0b35fdd86882cbbde2b6aa2ae570ae08a13868ba2cd6cdf7ae9348b40a816a83
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.17
|
Security for fdg-pet-ct-mlx 0.2.1
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.
To learn more about protecting yourself from malicious actors, visit our package security documentation.