Metadata-Version: 2.4
Name: segsuite
Version: 0.1.0
Summary: Novel segmentation metrics and differentiable loss functions for PyTorch
License-Expression: MIT
Project-URL: Homepage, https://github.com/asitm55/segsuite
Project-URL: Repository, https://github.com/asitm55/segsuite
Project-URL: Bug Tracker, https://github.com/asitm55/segsuite/issues
Keywords: segmentation,metrics,loss,pytorch,deep-learning,medical-imaging
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Scientific/Engineering :: Image Recognition
Classifier: Intended Audience :: Science/Research
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: torch>=1.10
Requires-Dist: numpy>=1.20
Requires-Dist: scipy>=1.7
Requires-Dist: opencv-python>=4.5
Requires-Dist: albumentations>=1.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: black; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Provides-Extra: experiments
Requires-Dist: pandas; extra == "experiments"
Requires-Dist: seaborn; extra == "experiments"
Requires-Dist: tqdm; extra == "experiments"
Requires-Dist: scikit-learn; extra == "experiments"
Requires-Dist: matplotlib; extra == "experiments"
Dynamic: license-file

# Segsuite

**Semantic Segmentation Metrics & Differentiable Loss Functions**

Novel metrics (SABRE, U-Score) and their differentiable PyTorch surrogate losses,
along with baseline metrics (GAS, DFH, TEDS, MAGE, UGTS) and losses.

---

## Installation

### Option A — uv (recommended, fastest)
[uv](https://docs.astral.sh/uv/) is a drop-in replacement for pip/venv that resolves and
installs dependencies significantly faster.

```bash
# install uv (one-time), see https://docs.astral.sh/uv/getting-started/installation/
curl -LsSf https://astral.sh/uv/install.sh | sh        # macOS/Linux
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"   # Windows

git clone https://github.com/yourusername/segsuite
cd segsuite
uv venv                       # creates .venv
uv pip install -e .           # or: uv pip install -e ".[dev]" for tests/lint tooling
```

Once published to PyPI, end users can skip the clone entirely:
```bash
uv pip install segsuite
```

### Option B — pip (editable, for development)
```bash
git clone https://github.com/yourusername/segsuite
cd segsuite
pip install -e .
```

### Option C — From folder / zip
```bash
pip install /path/to/segsuite/
```

### Option D — Publish to PyPI (anyone can install)
```bash
pip install build twine
python -m build           # produces dist/
twine upload dist/*       # upload to PyPI
# then: pip install segsuite   OR   uv pip install segsuite
```

---

## Quick Start

```python
import torch
from segsuite.losses import get_loss, SoftSABRELoss, ULoss
from segsuite.metrics import sabre, u_score, compute_metrics

# ── Training ─────────────────────────────────────────────────────────────────
criterion = get_loss("sabre")   # or "uloss", "teds", "mage", "ugts", "dice" …

logits  = torch.randn(2, 1, 256, 256, requires_grad=True)
targets = torch.randint(0, 2, (2, 1, 256, 256)).float()

loss = criterion(logits, targets)
loss.backward()
print(f"Loss: {loss.item():.4f}")

# ── Validation ────────────────────────────────────────────────────────────────
import numpy as np
P = (torch.sigmoid(logits) > 0.5).float()
scores = compute_metrics(P, targets)
for k, v in scores.items():
    print(f"  {k:8s}: {v:.4f}")
```

---

## All Losses

| String key   | Class               | Description                                  |
|--------------|---------------------|----------------------------------------------|
| `dice`       | SoftDiceLoss        | Standard soft Dice                           |
| `iou`        | SoftIoULoss         | Standard soft IoU                            |
| `boundary`   | SoftBoundaryLoss    | Distance-map boundary (Kervadec 2019)        |
| `gas`        | SoftGASLoss         | Gradient alignment surrogate                 |
| `dfh`        | SoftDFHBaseLoss     | Dual-F harmonic + Euler topology gate        |
| `teds`       | SoftTEDSv2Loss      | Proper TEDS_v2 surrogate ✓ (recommended)     |
| `teds_orig`  | SoftTEDSLoss        | Original composite TEDS (compat.)            |
| `geo_f1`     | SoftGeoF1Loss       | Distance-weighted F1                         |
| `mage`       | SoftMAGEv2Loss      | Multi-scale adaptive geometric evaluation    |
| `ugts`       | SoftUGTSv4Loss      | Unified geometric-topological score          |
| `sabre`      | SoftSABRELoss       | **Novel** spatial-adaptive boundary & topo   |
| `uloss`      | ULoss               | **Novel** universal segmentation loss        |
| `bce`        | BCEWithLogitsLoss   | Standard BCE                                 |

---

## All Metrics

| Function        | Description                                    |
|-----------------|------------------------------------------------|
| `dice(P, G)`    | Dice / F1 coefficient                          |
| `iou(P, G)`     | Intersection over Union                        |
| `gas(P, G)`     | Gradient Alignment Score                       |
| `dfh(P, G)`     | Dual-F Harmonic + Euler gate                   |
| `teds(P, G)`    | Topological Energy Distance Score              |
| `mage(P, G)`    | Multi-scale Adaptive Geometric Evaluation      |
| `ugts(P, G)`    | Unified Geometric-Topological Score            |
| `sabre(P, G)`   | **Novel** SABRE metric                         |
| `u_score(P, G)` | **Novel** Universal Segmentation Score         |
| `compute_metrics(P, G)` | All metrics at once → `dict`           |

---

## Model

```python
from segsuite import UNet, build_model

model = build_model("unet", n_channels=3, n_classes=1,
                     features=[64, 128, 256, 512],
                     norm="batch", up_mode="bilinear", init="he")
```

## Datasets

```python
from segsuite import KvasirDataset, ISICDataset, get_dataset

train_ds = get_dataset("kvasir", mode="train", size=(256, 256))
val_ds   = get_dataset("isic",   mode="val")
```

## Benchmark

```python
from segsuite import MetricChallenge
ds = MetricChallenge(length=100, mode='fragmented', size=(128, 128))
gt, pred = ds[0]
```

Modes: `perfect`, `oversegmentation`, `undersegmentation`, `holes`,
`fragmented`, `boundary_jitter`, `alignment_shift`, `missed_object`,
`empty_gt_correct`, `empty_gt_fp`

---

## Experiments

`experiments/` ships two full training/evaluation pipelines from the thesis
(Kvasir-SEG and ISIC Part 1). They need extra dependencies not required by the
core library:

```bash
pip install "segsuite[experiments]"       # or: uv pip install "segsuite[experiments]"
```

Point the dataset root at your local data (`src/data/Kvasir`, `src/data/ISIC_Part_1`
by default — see `segsuite.dataset` for the expected folder layout), then run:

```bash
python -m experiments.train_kvasir
python -m experiments.train_isic
```

Each script trains against every loss in `CONFIG["losses_to_train"]` and evaluates
with every metric in `CONFIG["metrics_to_eval"]`, writing results under `Results_*/`.

---

## Project Structure

```
segsuite/
├── segsuite/
│   ├── __init__.py     ← all public exports
│   ├── losses.py       ← loss functions + get_loss()
│   ├── metrics.py      ← metric functions + compute_metrics()
│   ├── dataset.py      ← KvasirDataset, ISICDataset, get_dataset()
│   ├── benchmark.py    ← MetricChallenge synthetic benchmark
│   └── model.py        ← UNet, build_model()
├── experiments/         ← training scripts (install via segsuite[experiments])
├── tests/               ← not shipped in the wheel or sdist
└── pyproject.toml
```

---

## Citation

```bibtex
@mastersthesis{mishra2025lyingdice,
  author = {Mishra, Asit},
  title  = {Beyond Dice: Novel Metrics for Structural Correctness in Medical Image Segmentation},
  school = {Friedrich-Alexander-Universität Erlangen-Nürnberg},
  year   = {2025},
}
```
