<!-- Badges -->

[![Build Status](https://github.com/ornlneutronimaging/bm3dornl/actions/workflows/test.yml/badge.svg?branch=next)](https://github.com/ornlneutronimaging/bm3dornl/actions/workflows/test.yml?query=branch?next)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6650/badge)](https://bestpractices.coreinfrastructure.org/projects/6650)
[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/ornlneutronimaging/bm3dornl/next.svg)](https://results.pre-commit.ci/latest/github/ornlneutronimaging/bm3dornl/next)
[![Documentation Status](https://readthedocs.org/projects/bm3dornl/badge/?version=latest)](https://bm3dornl.readthedocs.io/en/latest/?badge=latest)
[![PyPI](https://img.shields.io/pypi/v/bm3dornl)](https://pypi.org/project/bm3dornl/)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.18226146.svg)](https://doi.org/10.5281/zenodo.18226146)

<!-- End Badges -->
BM3D ORNL
=========

A high-performance BM3D denoising library for neutron imaging, optimized for streak/ring artifact removal from sinograms.

The BM3D algorithm was originally proposed by K. Dabov, A. Foi, V. Katkovnik, and K. Egiazarian in the paper "Image Denoising by Sparse 3D Transform-Domain Collaborative Filtering" (2007).

**BM3D ORNL** provides a Python API with a **Rust backend** for efficient, parallel processing of tomography data. Key features:

- **Streak/Ring Artifact Removal**: Specialized mode for removing vertical streak artifacts common in neutron and X-ray imaging
- **Stack Processing**: Efficient batched processing of 3D sinogram stacks
- **High Performance**: Rust backend with optimized block matching (integral images, early termination) and transforms (Hadamard, FFT)

How to install
--------------

**Using Pip**

```bash
# Core library only
pip install bm3dornl

# With GUI application
pip install bm3dornl[gui]
```

**Supported Platforms**

| Platform | Architecture | Library | GUI |
|----------|--------------|---------|-----|
| Linux | x86_64 | ✅ | ✅ |
| macOS | ARM64 (Apple Silicon) | ✅ | ✅ |

**Using Pixi (Development)**

```bash
pixi install
pixi run build
```

Usage
-----

```python
from bm3dornl import bm3d_ring_artifact_removal
import numpy as np

# Load sinogram data - 2D (H, W) or 3D stack (N, H, W)
sinogram = np.load("sinogram.npy")

# Standard BM3D denoising (generic white noise)
denoised = bm3d_ring_artifact_removal(sinogram, mode="generic", sigma_random=0.1)

# Streak artifact removal (recommended for ring artifacts)
denoised = bm3d_ring_artifact_removal(sinogram, mode="streak", sigma_random=0.1)

# With custom parameters (all parameters are flat, no dict wrapping)
denoised = bm3d_ring_artifact_removal(
    sinogram,
    mode="streak",
    sigma_random=0.1,
    patch_size=8,           # Patch size (7 or 8 recommended)
    step_size=4,            # Step size for patch extraction
    search_window=40,       # Max search distance
    max_matches=64,         # Similar patches per 3D group
    batch_size=32,          # Batch size for stack processing
)
```

Performance
-----------

The **Rust backend** provides high performance for tomography stacks:

| Metric | Value |
|--------|-------|
| **Speed** | ~0.63s per frame (512×512) on Apple Silicon |
| **Memory** | >50% reduction via chunked processing |
| **Parallelism** | Zero-overhead parallel processing via Rayon |

Key optimizations:
- Integral image pre-screening for fast block matching
- Early termination in distance calculations
- Pre-computed FFT plans
- Fast Walsh-Hadamard transform for 8×8 patches

Development
-----------

We use [pixi](https://prefix.dev) for development environment management.

1.  Clone repo.
2.  Run `pixi run build` to compile the Rust backend and install in editable mode.
3.  Run `pixi run test` to run tests.
4.  Run `pixi run bench` to run performance benchmarks.

```bash
git clone https://github.com/ornlneutronimaging/bm3dornl.git
cd bm3dornl
pixi run build
pixi run test
```

GUI Application
---------------

BM3DORNL includes a standalone GUI application for interactive ring artifact removal.

### Installation

```bash
pip install bm3dornl[gui]
```

Or install the GUI separately:

```bash
pip install bm3dornl-gui
```

### Launching

```bash
bm3dornl-gui
```

### Features

- Load HDF5 files with tree browser for dataset selection
- Interactive slice viewer with histogram
- Side-by-side comparison of original and processed images
- Real-time parameter adjustment
- ROI selection for histogram (Shift+drag to select region)
- Export processed data to TIFF or HDF5

### Keyboard Shortcuts

| Shortcut | Action |
|----------|--------|
| Shift+Drag | Select ROI for histogram |
| Scroll | Zoom in/out on image |
| Drag | Pan image |

Parameter Reference
-------------------

| Parameter | Default | Description |
|-----------|---------|-------------|
| `mode` | `"streak"` | `"generic"` for white noise, `"streak"` for ring artifacts |
| `sigma_random` | `0.1` | Noise standard deviation |
| `patch_size` | `8` | Patch size (7 or 8 recommended) |
| `step_size` | `3` | Step size for patch extraction |
| `search_window` | `39` | Maximum search distance for similar patches |
| `max_matches` | `16` | Maximum similar patches per 3D group |
| `batch_size` | `32` | Batch size for stack processing |
| `streak_sigma_smooth` | `1.0` | Smoothing for streak mode (streak mode only) |
