Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ title: >-
message: >-
If you use this software, please cite it using the
metadata from this file.
version: 0.9.5
date-released: 2026-06-21
version: 0.10.0
date-released: 2026-07-04
doi: 10.5281/zenodo.20791110
authors:
- given-names: Nathaniel
Expand Down
17 changes: 11 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@ uv sync --dev # include dev tools (pytest, ruff, etc.)
uv sync --group train # include training deps (lightning, h5py, etc.)

# Run the web app
python -m TokEye.app # starts on localhost:7860
python -m TokEye.app --port 8888 # custom port
python -m TokEye.app --share # public Gradio link
tokeye app # starts on localhost:7860 (or: python -m tokeye.app)
tokeye app --port 8888 # custom port
tokeye app --share # public Gradio link

# Headless CLI (no gradio import; safe for HPC/CI)
tokeye run "shots/*.npy" --output-dir results # batch inference
tokeye download big_tf_unet # pre-fetch weights, print cache path
tokeye example # write a synthetic demo signal

# Lint
uv run ruff check .
Expand All @@ -43,12 +48,12 @@ Shared building blocks in `models/modules/`: `unet.py` (base U-Net), `nn.py` (la
Model I/O: input `(B, 1, H, W)` → output `(B, 2, H, W)` where channel 0 = coherent activity, channel 1 = transient activity.

### App (`app/`)
Gradio web interface launched via `python -m TokEye.app`. Three tabs:
Gradio web interface launched via `tokeye app` (console script) or `python -m tokeye.app`. Three tabs:
- **Analyze** (`app/analyze/`) — load signals, compute STFT spectrograms, run inference
- **Annotate** (`app/tabs/annotate.py`) — manual labeling interface
- **Utilities** (`app/tabs/utilities.py`) — miscellaneous tools

Inference pipeline: `app/processing/` handles model loading, tiled inference for large spectrograms, and post-processing.
Shared core modules (used by both the app and the `tokeye` CLI) live directly under `src/tokeye/`: `hub.py` (model registry + Hugging Face auto-download), `transforms.py` (STFT), `inference.py` (model inference), `batch.py` (headless batch runner), `examples.py` (synthetic demo signal), `cli.py` (the `tokeye` console entry point).

### Training (`training/`)
Multi-step data pipelines (step_0 through step_7) for preparing training data from raw signals. Two regimes: `big_tf_unet/` (original) and `big_tf_unet_multiscale/` (enhanced). Uses PyTorch Lightning.
Expand All @@ -64,4 +69,4 @@ Domain-specific utilities: DIII-D tokamak helpers (`extra/D3D/`), evaluation too

## CI

GitHub Actions runs on push/PR to main: `uv run ruff check .` then `uv run pytest` across Python 3.10–3.14.
GitHub Actions runs on push/PR to main: `uv run ruff check .` then `uv run pytest` across Python 3.13–3.14.
133 changes: 92 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p align="center">
<img src="assets/logo.png" alt="TokEye Logo" width="400">
<img src="src/tokeye/app/assets/logo.png" alt="TokEye Logo" width="400">
</p>

# TokEye
Expand All @@ -18,6 +18,74 @@ Expected processing time:
- V100: < 0.5 seconds on any size spectrogram after warmup.
- CPU: ~5-10 seconds.

## Quickstart

```bash
pip install tokeye # or: uv tool install tokeye
tokeye app # opens web app on http://localhost:7860
```

- The default model downloads automatically from Hugging Face on first use (~30 MB, cached — no manual setup).
- No data handy? Click "Load Example Signal" in the app, or generate one from the shell with `tokeye example`.
- `pip install` requires Python >= 3.13; `uvx`/`uv tool install` fetch a compatible Python automatically.

Zero-install trial: `uvx tokeye app` runs the app without installing anything into your environment.

## Batch processing (CLI)

For headless / scripted use (no browser needed), run inference directly:

```bash
tokeye run "shots/*.npy" --output-dir results
```

`INPUT` arguments can be files, directories (all `*.npy` files inside are used), or quoted glob patterns. Each input is interpreted by its shape:
- **1D array** — a raw time series. TokEye computes its STFT spectrogram using the flags below before running inference.
- **2D array** — a precomputed spectrogram, fed to the model directly.

For each input file, `tokeye run` writes:
- `<stem>_mask.npy` — float32 array, shape `(2, H, W)`, sigmoid scores per pixel (channel 0 = coherent, channel 1 = transient).
- `<stem>_preview.png` — a grayscale spectrogram with the mask overlaid (green = coherent, red = transient), unless `--no-png` is passed.

The process exit code is the number of files that failed.

Flags:
| Flag | Default | Description |
| --- | --- | --- |
| `--model` | `big_tf_unet` | Registry name or path to a `.pt`/`.pt2` checkpoint. |
| `--output-dir` | `tokeye_output` | Directory for masks and previews. |
| `--n-fft` | `1024` | STFT window size (1D inputs only). |
| `--hop` | `256` | STFT hop size (1D inputs only). |
| `--keep-dc` | off | Keep the DC bin (dropped by default). |
| `--clip-low` / `--clip-high` | `1.0` / `99.0` | Percentile clip bounds applied to the spectrogram. |
| `--threshold` | `0.5` | Mask threshold used only for the preview PNG overlay. |
| `--no-png` | off | Skip preview PNGs; write masks only. |
| `--device` | `auto` | `cpu`, `cuda`, or `auto`. |

The released model was trained on spectrograms built with hop=128; for closest match to the training configuration use `--hop 128`.

On HPC clusters where compute nodes have no internet access, pre-fetch the weights on the login node, then run the batch job on the compute node:

```bash
tokeye download big_tf_unet # on the login node; prints the cached path
tokeye run ... --model big_tf_unet # on the compute node — model is already cached
```

## Web app guide

`tokeye app` (or `python -m tokeye.app`) launches a Gradio interface with three tabs:
- **Analyze** — load a signal, compute its spectrogram, run a model, and visualize the result. Guided for first-time use: the model dropdown defaults to the bundled `big_tf_unet` model, the STFT transform has working defaults, and "Load Example Signal" generates a synthetic demo signal so a brand-new user needs zero files. "Analyze" runs the whole load-model → infer → visualize pipeline in one click. View modes: Original, Enhanced (percentile-clipped amplitude), Mask (thresholded model output), Amplitude.
- **Annotate** — manually draw and save mask annotations over a read-only backdrop image.
- **Utilities** — audio-format conversion and `.npy` file inspection.

Flags: `tokeye app [--port 7860] [--share] [--open]` — `--share` creates a public Gradio link, `--open` opens a browser tab on launch.

If you're on a remote server (e.g. an HPC login node), forward the port over SSH instead of using `--share`:
```bash
ssh -L 7860:localhost:7860 user@remote
```
Then open `http://localhost:7860` in your local browser.

## Verified Datatypes
- DIII-D Fast Magnetics (cite)
- DIII-D CO2 Interferometer (cite)
Expand All @@ -32,64 +100,47 @@ Recall Scores:

With more data, comes better models. Please contribute to the project!

## Installation

[uv](https://docs.astral.sh/uv/) (recommended)
```bash
git clone git@github.com:PlasmaControl/TokEye.git
cd TokEye
uv sync
```

pip (from PyPI)
```bash
pip install tokeye
```
## Installation (from source / development)

pip (from source)
[uv](https://docs.astral.sh/uv/) is the dev tool for this repo:
```bash
git clone git@github.com:PlasmaControl/TokEye.git
cd TokEye
python3 -m venv .venv
source venv/bin/activate
pip install uv
uv sync
uv sync # core deps
uv sync --dev # + pytest, ruff, etc.
uv sync --group train # + training deps (lightning, h5py, etc.)
```

## Usage
```bash
python -m TokEye.app
```

This will start a web app on `http://localhost:8888`.

If you are on a remote server, you can use SSH port forwarding to access the web app on your local machine:
```bash
ssh -L 8888:localhost:7860 user@remote_server
```
Then open your web browser and navigate to `http://localhost:8888`.
This creates a `.venv/`; activate it with `source .venv/bin/activate`, or prefix commands with `uv run`.

## Models
Pre-trained models are available at [this link](https://huggingface.co/collections/nc1/tokeye).

(soon to be deprecated) Pre-trained models are available at [this link](https://drive.google.com/drive/folders/1rXllPXB3eWhMvSIlp0CDSFx68lJOQG1u?usp=drive_link).
| Registry name | HF file | Description |
| --- | --- | --- |
| `big_tf_unet` | `big_tf_unet_251210.pt` | Transformer U-Net trained on multiscale (multiwindow, multihop) spectrograms. |

Copy them into the `models/` directory after downloading them.
- big_mode_v1.pt: Original training regime (window = 1024, hop = 128)
- big_mode_v2.pt: Trained on multiscale (multiwindow, multihop) spectrograms
- big_tf_unet_251210.pt: Trained on multiscale (multiwindow, multihop) spectrograms
Weights are hosted on [Hugging Face](https://huggingface.co/PlasmaControl/tokeye) and download automatically the first time a registry name is used (cached in `~/.cache/huggingface`). Override the source repo with the `TOKEYE_HF_REPO` environment variable.

To use a local checkpoint instead, put `.pt`/`.pt2` files in a `model/` directory (picked up by the app's model dropdown) or pass a path directly via `--model PATH`.

Input should be a tensor that has shape (B, 1, H, W) where B, H, and W can vary
Output will be a tensor of shape (B, 2, H, W)

Best performance when spectrograms are oriented so that when they are plotted with matplotlib, the lowest frequency bin is oriented with the bottom when `origin='lower'`. Spectrograms should be standardized (mean = 0, std = 1). If baseline activity is very strong, clipping the input may help, but is generally not needed.

The first channel of the output will return preferential measurements of coherent activity (useful for most tasks)
THe second channel of the output will return preferential measurements of transient activity
The second channel of the output will return preferential measurements of transient activity

## Data
Right now, keep all data as 1d numpy float arrays. No need to normalize or preprocess them.
Copy them into the `data/` directory.
Keep signals as 1D numpy float arrays (raw time series) — no need to normalize or preprocess them. The CLI also accepts 2D arrays (precomputed spectrograms) directly. The app scans a signal directory for `.npy` files (default `data/input`, configurable in the Analyze tab).

## Development

```bash
uv sync --dev
uv run ruff check .
uv run pytest
```

## Citation
If you use this code in your research, please cite:
Expand All @@ -105,4 +156,4 @@ If you use this code in your research, please cite:
```

## Contact
Please check back for updates or reach out to Nathaniel Chen at nathaniel [at] princeton [dot] edu.
Nathaniel Chen nathaniel [at] princeton [dot] edu — https://nathanielchen.net
9 changes: 7 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ build-backend = "uv_build"

[project]
name = "tokeye"
version = "0.9.5"
description = "Add your description here"
version = "0.10.0"
description = "Automatic classification and localization of fluctuating signals in spectrograms"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
Expand All @@ -20,6 +20,8 @@ dependencies = [
"omegaconf",
"tables",
"pydantic",
"huggingface-hub>=0.30",
"tqdm",
]

[project.optional-dependencies]
Expand All @@ -42,6 +44,9 @@ train = [
"pandas",
]

[project.scripts]
tokeye = "tokeye.cli:main"

[tool.pytest.ini_options]
minversion = "9.0"
addopts = ["-ra", "-q"]
Expand Down
Loading
Loading