![Puma-logo](Images/Puma-logo.png)

## PUMA 1.0 🐾 -  One Image multiple perspectives 🎭
[![PyPI version](https://img.shields.io/pypi/v/pumaz?color=FF1493&style=flat-square&logo=pypi)](https://pypi.org/project/pumaz/) [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-red.svg?style=flat-square&logo=gnu&color=FF0000)](https://www.gnu.org/licenses/gpl-3.0) [![Monthly Downloads](https://img.shields.io/pypi/dm/pumaz?label=Downloads%20(Monthly)&color=9400D3&style=flat-square&logo=python)](https://pypi.org/project/pumaz/) [![Daily Downloads](https://img.shields.io/pypi/dd/pumaz?label=Downloads%20(Daily)&color=9400D3&style=flat-square&logo=python)](https://pypi.org/project/pumaz/) 
[![Commercial License](https://img.shields.io/badge/Commercial%20Use-Contact%20Zenta-orange?style=flat-square&logo=data:image/svg+xml;base64, )](mailto:lalith@zenta.solutions)

**🌈 PET Reimagined: From Monochrome to a Palette of Possibilities with PUMA 1.0**

Step into the vibrant new world of PET imaging with PUMA 1.0 🌟, where traditional monochrome scans are transformed into a dynamic spectrum of diagnostic data. 🎨

With PUMA 1.0, experience the power of multiplexing: a process that fuses multiple tracer images into a single, multicolored composite that reveals not just the presence of disease but its multifaceted physiological context. 🔄 The multiplexed approach provides a more comprehensive view, helping clinicians uncover nuanced insights about tumors and their microenvironments. 🔍

Whether you're in a high-tech lab or a remote clinic, PUMA 1.0 delivers high-quality, multiplexed PET scans that are as rich in detail as they are in color. 🏥 It’s not just an upgrade—it’s a whole new way of seeing PET data, turning every image into a detailed map of insight and opportunity. 🗺️

## 🎉 Key Features

### 🚀 Versatile and Powerful
Run PUMA 1.0 on any device, any OS, from x86 to ARM64 (hello, Apple Silicon fans!). Whether you’re on a high-end GPU or a humble CPU, PUMA adapts to your needs without breaking a sweat.

### 🔍 Precision Meets Speed
Harness the power of AI with MOOSE-driven segmentations and ‘greedy’ library’s wizardry for diffeomorphic image registration. PUMA 1.0 nails the perfect balance of sharp accuracy and zippy performance.

### 🎨 Art of Imaging
Why settle for ordinary when you can visualize in vibrant RGB? Each color shines a spotlight on a different tracer, turning complex data into a vivid, easy-to-interpret display. With processing times ranging from just 5 to 12 minutes, you're all set for a speedy yet thorough diagnostic journey.

## 🚀 Why PUMA?


https://github.com/ENHANCE-PET/PUMA/assets/48599863/03368642-a288-44cb-8eaf-4833380a26c8


## Requirements ✅

Before stepping into the future with PUMA 1.0, here's what you need for an optimal experience:

- **Operating System**: Windows, Mac, or Linux - PUMA 1.0 is versatile and works across all these platforms.

- **Memory**: Make sure your system has enough memory (8-16 GB) to run the tasks smoothly.

- **GPU**: You would benefit from a cuda-enabled GPU (NVIDIA), 8 GB or more, or MPS (Apple silicon) - if you like quick results ⚡️. But if you don't fret not, PUMA runs a cpu-tuned version if there is no GPU.

- **Python**: PUMA 1.0 operates the best with Python 3.10.

Once these specifications are met, you're all set to experience PUMA 1.0's capabilities.

## Installation Guide 🛠️

Pick the workflow that matches your tooling and operating system:

- **pip + virtualenv** — the classic approach. Works everywhere and keeps dependencies isolated.
- **uv sync** — fastest path to a fully managed `.venv` driven by `pyproject.toml`.
- **uv pip install** — drop-in replacement for `pip install` when you already manage the environment yourself.

Regardless of the route you choose, PUMA requires Python 3.10 or newer.

### Linux / macOS

1. Create a virtual environment (feel free to change `puma-env`).
   ```bash
   python3.10 -m venv puma-env
   ```
2. Activate it.
   ```bash
   source puma-env/bin/activate
   ```
3. Install PUMA from PyPI.
   ```bash
   pip install pumaz
   ```

### Windows 🪟

1. Create a virtual environment.
   ```powershell
   python3.10 -m venv puma-env
   ```
2. Activate it.
   ```powershell
   .\puma-env\Scripts\activate
   ```
3. Install PUMA.
   ```powershell
   pip install pumaz
   ```

### Using uv 🚀

Prefer the lightning-fast [uv](https://github.com/astral-sh/uv) workflow? The bundled `pyproject.toml` lets you bootstrap everything in one go:

```bash
uv sync               # create a managed .venv and install dependencies
uv run pumaz --help   # invoke the CLI without manually activating the environment
```

uv pins the environment in `.venv` by default. If you want to work inside it directly, run `source .venv/bin/activate` (or `.\.venv\Scripts\activate` on Windows) after `uv sync`.

Already have an environment and just want the package? Use `uv pip` (a drop-in pip replacement):

```bash
uv pip install pumaz
```

## Usage Guide 📚

Start your journey with PUMA 1.0 by using our straightforward command-line tool. It requires the directory path containing different tracer images, and each image should be stored in separate folders. Here's how you can get started:

```bash

   pumaz \
       -d   <path_to_image_dir>              # Directory path containing the images to be analyzed
       -ir  <regions_to_ignore>              # Regions to ignore: arms, legs, head, none
       -m                                    # Optional: Enable multiplexed RGB image output
       -cs  <color_selection>                # Optional: Custom color selection for RGB output (requires -m)
       -cm  <color_map>                      # Optional: Assign specific colors to each tracer (e.g., psma:R,fdg:G) (requires -m)
       -c2d <convert_back_to_dicom>          # Optional: Once set, the generated nifti images will be converted back to DICOM
```

- `<path_to_image_dir>` refers to the parent directory containing different tracer images in their respective sub-directories.

- `-ir` specifies the regions to be ignored during registration. If you don't want to ignore any regions, use `none`. If you want to ignore the arms, legs, or head during registration, pass the corresponding regions delimited by a `,`. For example: `-ir head,arms` to ignore the head and arms.

- `-m` will activate the output of a multiplexed RGB image of the combined tracer images.

- `-cs`, when passed along with `-m`, PUMA will ask you to provide a custom order of color channels for the corresponding tracer images. That way, you can freely decide which tracer image is associated with which channel.
- `-cm`, when passed along with `-m`, provides a predefined color channel assignment for each tracer using the format `tracer:color,....`. The `tracer` part must match the name of each subdirectory inside your image parent directory (e.g., `Tracer1`, `Tracer2`, etc.).  Valid colors are R, G, and B. Each color may only be used once.
Example: `-cm Tracer1:R,Tracer2:G` assigns Red to Tracer1 and Green to Tracer2. This option requires -m and is mutually exclusive with -cs.
- `-c2d`, when set the generated aligned nifti images will be converted back to DICOM.
  
For assistance or additional information, you can always type:

```bash
pumaz -h
```


### Example usage:
Apply PUMA to images in a directory, ignoring arms and legs, with multiplexed RGB output and custom colors:

```bash
pumaz -d /path/to/images -ir arms,legs -m -cs -c2d 
```


## Directory Structure and Naming Conventions for PUMA 📂🏷️

PUMA 1.0 requires your data to be structured in a certain way. It supports DICOM directories and NIFTI files. For NIFTI files, users need to ensure that the files are named with the correct modality tag at the start.

### Required Directory Structure 🌳

Here is the directory structure that PUMA 1.0 expects:

```
📁 Parent_Directory
│
└───📂 Tracer1 # can be named anything
│   │
│   └───📁 PET_DICOM_Directory or 🗃️ PT_xxxx.nii.gz # If it's DICOM, the folder name can be anything, but if nifti use a prefix 'PT' for PET
│   │
│   └───📁 CT_DICOM_Directory or 🗃️ CT_xxxx.nii.gz # If it's DICOM, the folder name can be anything, but if nifti use a prefix 'CT' for CT
│
└───📂 Tracer2
│   │
│   └───📁 PET_DICOM_Directory or 🗃️ PT_xxxx.nii.gz
│   │
│   └───📁 CT_DICOM_Directory or 🗃️ CT_xxxx.nii.gz
...

└───📂 Tracer3
    │
    └───📁 PET_DICOM_Directory or 🗃️ PT_xxxx.nii.gz
    │
    └───📁 CT_DICOM_Directory or 🗃️ CT_xxxx.nii.gz

```

### Naming Conventions 🏷️

- For DICOM directories, no specific naming is required.
- For NIFTI files, the file should start with the DICOM modality tag (e.g., 'PT_' or 'CT_') followed by the desired name. For example, 'PT_MySample.nii.gz'.

Note: All the PET and CT images related to a tracer should be placed in the same directory named after the tracer.

## Appendix: Apple Silicon (M1/M2/M3 with MPS Backend)

> Yes, it works — but it takes a few extra steps. Grab a ☕ or 🍺 and follow along carefully.

1. **Prepare a clean environment (Python 3.10 recommended).**

   ```bash
   python3.10 -m venv puma-env
   source puma-env/bin/activate
   ```

2. **Install PUMA and fetch the MPS-compatible PyTorch fork.**  
   Apple’s Metal backend (MPS) needs a custom PyTorch build without CUDA.

   ```bash
   pip install pumaz
   pip uninstall torch          # remove the stock wheel that ships with pumaz
   git clone https://github.com/LalithShiyam/pytorch-mps.git
   cd pytorch-mps
   ```

3. **Check your CMake version (IMPORTANT ⚠️).**  
   CMake 4.x triggers protobuf build failures. Stick to ≤3.29.2.

   ```bash
   cmake --version
   ```

   If the reported version is 4.x or newer:

   ```bash
   pip uninstall cmake -y
   pip install cmake==3.29.2
   ```

4. **Build the custom PyTorch fork for MPS.**  
   This step disables CUDA and can take a while — be patient!

   ```bash
   USE_CUDA=0 python setup.py develop --verbose 2>&1 | tee build.log
   ```

5. **Patch `nnUNetTrainer.py` (one-time fix).**  
   nnU-Net expects `GradScaler` in a CUDA module. Point it at the AMP helper instead.

   ```text
   File: ~/puma-env/lib/python3.10/site-packages/nnunetv2/training/nnUNetTrainer/nnUNetTrainer.py
   ```

   Replace line 43:

   ```python
   from torch import GradScaler
   ```

   with:

   ```python
   from torch.cuda.amp import GradScaler
   ```

✅ That’s it! You’re ready to run **PUMA on Apple Silicon** with MPS acceleration.  
If anything crashes, blame the silicon gods… or open an issue — we’re happy to help.

## 🚀 Benchmarks

To be updated.

## 📚 Citation

If you use PUMA in your research, please cite:

> Fully Automated Image-Based Multiplexing of Serial PET/CT Imaging for Facilitating Comprehensive Disease Phenotyping  
> Lalith Kumar Shiyam Sundar, Sebastian Gutschmayer, Manuel Pires, Daria Ferrara, Toni Nguyen, Yasser Gaber Abdelhafez, Benjamin Spencer, Simon R. Cherry, Ramsey D. Badawi, David Kersting, Wolfgang P. Fendler, Moon-Sung Kim, Martin Lyngby Lassen, Philip Hasbak, Fabian Schmidt, Pia Linder, Xingyu Mu, Zewen Jiang, Elisabetta M. Abenavoli, Roberto Sciagrà, Armin Frille, Hubert Wirtz, Swen Hesse, Osama Sabri, Dale Bailey, David Chan, Jason Callahan, Rodney J. Hicks, Thomas Beyer  
> Journal of Nuclear Medicine, September 2025, jnumed.125.269688; DOI: https://doi.org/10.2967/jnumed.125.269688

## A Note on QIMP Python Packages: The 'Z' Factor 📚🚀

All of our Python packages here at QIMP carry a special signature – a distinctive 'Z' at the end of their names. The 'Z' is more than just a letter to us; it's a symbol of our forward-thinking approach and commitment to continuous innovation.

Our PUMA package, for example, is named as 'pumaz', pronounced "puma-see". So, why 'Z'?

Well, in the world of mathematics and science, 'Z' often represents the unknown, the variable that's yet to be discovered, or the final destination in a series. We at QIMP believe in always pushing boundaries, venturing into uncharted territories, and staying on the cutting edge of technology. The 'Z' embodies this philosophy. It represents our constant quest to uncover what lies beyond the known, to explore the undiscovered, and to bring you the future of medical imaging.

Each time you see a 'Z' in one of our package names, be reminded of the spirit of exploration and discovery that drives our work. With QIMP, you're not just installing a package; you're joining us on a journey to the frontiers of medical image processing. Here's to exploring the 'Z' dimension together! 🚀
 
## 📄 License 
The open-source version of this software is released under the GPLv3 License.
For commercial use or integration into proprietary products, please contact us at lalith.shiyam@zenta.solutions to obtain a commercial license through Zenta.

[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Commercial License](https://img.shields.io/badge/Commercial--Use-Contact--Zenta-orange)](mailto:lalith.shiyam@zenta.solutions)

## Contributors ✨

Thanks goes to these wonderful people  ✨:

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
  <tbody>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/W7ebere"><img src="https://avatars.githubusercontent.com/u/166598214?v=4?s=100" width="100px;" alt="W7ebere"/><br /><sub><b>W7ebere</b></sub></a><br /><a href="https://github.com/LalithShiyam/PUMA/commits?author=W7ebere" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/mprires"><img src="https://avatars.githubusercontent.com/u/48754309?v=4?s=100" width="100px;" alt="Manuel Pires"/><br /><sub><b>Manuel Pires</b></sub></a><br /><a href="https://github.com/LalithShiyam/PUMA/commits?author=mprires" title="Code">💻</a> <a href="https://github.com/LalithShiyam/PUMA/commits?author=mprires" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Keyn34"><img src="https://avatars.githubusercontent.com/u/87951050?v=4?s=100" width="100px;" alt="Sebastian Gutschmayer"/><br /><sub><b>Sebastian Gutschmayer</b></sub></a><br /><a href="https://github.com/LalithShiyam/PUMA/commits?author=Keyn34" title="Code">💻</a> <a href="https://github.com/LalithShiyam/PUMA/commits?author=Keyn34" title="Documentation">📖</a></td>
    </tr>
  </tbody>
</table>

<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
