Metadata-Version: 2.5
Name: fdg-pet-ct-mlx
Version: 0.2.1
Summary: Native MLX FDG PET image synthesis
Author: Joseph Sandoval, Alfredo Sandoval Jr.
License-Expression: Apache-2.0
License-File: LICENSE
License-File: THIRD_PARTY_NOTICES.md
Classifier: Operating System :: MacOS :: MacOS X
Requires-Python: <3.15,>=3.13
Requires-Dist: medmlx-core==0.2.3
Requires-Dist: mlx<1,>=0.32.4
Requires-Dist: numpy<3,>=2.0
Provides-Extra: conversion
Requires-Dist: torch<2.14,>=2.13; extra == 'conversion'
Provides-Extra: dev
Requires-Dist: pyright==1.1.414; extra == 'dev'
Requires-Dist: pytest<10,>=8.4; extra == 'dev'
Requires-Dist: ruff<1,>=0.13; extra == 'dev'
Requires-Dist: scipy-stubs<1.19,>=1.18; extra == 'dev'
Requires-Dist: scipy<2,>=1.13; extra == 'dev'
Description-Content-Type: text/markdown

# 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](https://github.com/MedMLX).
[Technical notes](https://github.com/MedMLX/fdg-pet-ct-mlx/blob/main/docs/technical.md)

[Quick start](#quick-start) · [Input and output](#input-and-output) · [Technical details](#technical-details) · [License](#license)

## Requirements

Apple Silicon Mac with Metal, Python 3.13 or 3.14 and [uv](https://docs.astral.sh/uv/).
No model weights are needed.

## Quick start

Install the current source branch:

```bash
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:

```python
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](https://github.com/MedMLX/fdg-pet-ct-mlx/blob/main/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](https://github.com/MedMLX/fdg-pet-ct-mlx/blob/main/LICENSE).
See [THIRD_PARTY_NOTICES.md](https://github.com/MedMLX/fdg-pet-ct-mlx/blob/main/THIRD_PARTY_NOTICES.md) for dependency attribution.

## Implementation mapping

[Central implementation map](https://github.com/MedMLX/Med-MLX/blob/main/implementation-maps/fdg-pet-ct-mlx.json) records upstream-to-native changes, source references and qualification scope.
