Metadata-Version: 2.4
Name: nikon-browser-qt
Version: 0.1.0
Summary: Reusable PyQt6 browser dialog for Nikon ND2 image files.
Author: NL-BioImaging contributors
License: Apache-2.0
Keywords: microscopy,nd2,nikon,pyqt6
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Image Processing
Requires-Python: >=3.10
Requires-Dist: nd2
Requires-Dist: numpy
Requires-Dist: pyqt6
Provides-Extra: dev
Requires-Dist: build; extra == 'dev'
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Description-Content-Type: text/markdown

# nikon-browser-qt

A reusable PyQt6 browser dialog and viewer for Nikon ND2 microscopy files.

---

## Features

- **File browser dialog** — navigate directories, preview images, select one or multiple ND2 files
- **Zoomable viewer** — pan/zoom canvas with channel toggles, contrast controls, Z / T / S sliders, and projection modes (Slice, MIP, Sum, Mean, Median)
- **Full dimension support** — X · Y · Z (z-stack) · T (time) · C (channels) · S (multi-position / tiles)
- **Channel colors** — read from ND2 metadata (`colorRGB` or emission wavelength); per-channel toggle buttons
- **Scale bar** — auto-scaling overlay based on pixel size
- **Metadata summary** — Name, Date, Dimensions, Pixel size, FOV size, Image size, Pixel type shown in the browser
- **CLI entry points** — `nikon_browser` (headless JSON output) and `nikon_viewer` (interactive viewer)

---

## Installation

```bash
pip install nikon-browser-qt
```

Or install from source:

```bash
git clone https://github.com/your-org/nikon-browser-qt
cd nikon-browser-qt
pip install -e .
```

**Requirements**: Python ≥ 3.10, PyQt6, numpy, nd2.

---

## Quick start

### Open the viewer from the command line

```bash
nikon_viewer                          # open empty viewer
nikon_viewer path/to/images/          # open with a folder pre-loaded
nikon_viewer file.nd2                 # open a specific file
```

### Launch the browser dialog and print selected metadata

```bash
nikon_browser                         # single-select, prints JSON to stdout
nikon_browser --multiple              # multi-select mode
nikon_browser path/to/images/
```

---

## Python API

### Single image selection

```python
from PyQt6.QtWidgets import QApplication
from nikon_browser_qt import NikonBrowserDialog

app = QApplication([])
ctx = NikonBrowserDialog.select_image_context()
if ctx is not None:
    print(ctx.name, ctx.size_x, ctx.size_y, ctx.size_z)
    print(ctx.to_dict())
```

### Multi-image selection

```python
from PyQt6.QtWidgets import QApplication
from nikon_browser_qt import NikonBrowserDialog

app = QApplication([])
contexts = NikonBrowserDialog.select_image_contexts()
for ctx in contexts:
    print(ctx.name, ctx.container_path)
```

### Pre-load a folder or file

```python
ctx = NikonBrowserDialog.select_image_context(roots=["path/to/data/"])
```

### Embed the browser dialog in your own application

```python
from nikon_browser_qt import NikonBrowserDialog

dialog = NikonBrowserDialog(roots=["data/"], selection_mode="single", parent=self)
if dialog.exec():
    ctx = dialog.selected_context()
```

### Open the viewer programmatically

```python
from PyQt6.QtWidgets import QApplication
from nikon_browser_qt.nikon_viewer import NikonViewerWindow

app = QApplication([])
win = NikonViewerWindow(roots=["data/"])
win.show()
app.exec()
```

---

## Reading pixel data

`NikonImageContext` provides three pixel-reading methods via `open()`:

```python
ctx = NikonBrowserDialog.select_image_context()
if ctx is not None:
    handle = ctx.open()

    plane = handle.read_plane(z=0, c=0, t=0)          # 2-D numpy array (Y × X)
    stack = handle.read_stack(c=0, t=0)                # 3-D array (Z × Y × X)
    arr   = handle.read_array()                        # 5-D array (T × C × Z × Y × X)
```

For multi-position files pass `s=<position_index>` (0-based) or set `ctx.selected_s` before calling.

---

## `NikonImageContext` fields

| Field | Type | Description |
|---|---|---|
| `name` | `str` | Image name (ND2 file stem) |
| `container_path` | `Path` | Path to the `.nd2` file |
| `internal_path` | `str` | `"<filename>/<image_name>"` |
| `image_id` | `str \| None` | File stem used as identifier |
| `kind` | `str` | `"nikon-image"` |
| `size_x` / `size_y` | `int \| None` | Width / height in pixels |
| `size_z` | `int \| None` | Number of z-planes (1 if no z-stack) |
| `size_c` | `int \| None` | Number of channels |
| `size_t` | `int \| None` | Number of time points |
| `size_s` | `int \| None` | Number of positions (P dimension) |
| `pixel_size_x_um` | `float \| None` | Pixel width in µm |
| `pixel_size_y_um` | `float \| None` | Pixel height in µm |
| `pixel_size_z_um` | `float \| None` | Z-step in µm |
| `selected_s` | `int \| None` | Fixed position index (`None` = all) |
| `channel_names` | `list[str]` | Channel names from ND2 metadata |
| `metadata` | `dict` | Raw metadata dict |

---

## Dimension mapping (ND2 → nikon-browser-qt)

| ND2 `f.sizes` key | Field | Slider |
|---|---|---|
| `X` | `size_x` | — |
| `Y` | `size_y` | — |
| `Z` | `size_z` | Z slider |
| `C` | `size_c` | Channel buttons |
| `T` | `size_t` | T slider |
| `P` (positions) | `size_s` | S slider |

The S slider is visible only for multi-position files (`size_s > 1`). In the browser dialog the S control lets you fix a position or pass `selected_s=None` to export all positions together.

---

## Viewer controls

| Control | Action |
|---|---|
| Scroll wheel | Zoom in / out |
| Left-drag | Pan |
| **Fit** button | Fit image to window |
| **100%** button | 1:1 pixel view |
| Channel buttons | Toggle channels on/off |
| Lo / Hi spinboxes | Percentile contrast limits |
| Z slider | Select z-plane |
| T slider | Select time point |
| S slider | Select position (multi-position files) |
| Projection combo | Slice · MIP · Sum · Mean · Median |

---

## Development

```bash
pip install -e ".[dev]"
```

Run the viewer directly from the repo:

```bat
run_viewer.cmd
run_viewer.cmd path\to\data\
```

---

## License

Apache-2.0
