# L2 Spec — CASSI Forward Operator

**ID:** `PWM-L2-em-cassi-forward`
**Parent Principle:** [`PWM-L1-em-maxwell-vacuum`](../principle/principle.md)
**Status:** ⊙ Testnet (genesis)
**Submitter:** _(wallet address)_

---

## 1. Operator Description

A forward operator that maps a 3-D hyperspectral cube `x ∈ ℝ^(H × W × λ)` (height × width × spectral bands) to a 2-D coded snapshot measurement `y ∈ ℝ^(H × W)` produced by a Coded Aperture Snapshot Spectral Imager (CASSI).

The pipeline is: scene → mask `M` modulates each spectral plane → dispersion shifts each plane by `δ_λ` pixels along the dispersion axis → sensor integrates over all bands.

This is the **forward** operator. The inverse problem (recover `x` from `y`) is solved by L4 Solutions registered against benchmarks under this spec.

## 2. Mathematical Form

For input cube `x` with `λ ∈ {λ_1, …, λ_B}` bands and binary mask `M ∈ {0,1}^(H × W)`:

$$
y[i, j] = \sum_{b=1}^{B} M[i, j - \delta_b] \cdot x[i, j - \delta_b, b]
\quad + \quad n[i, j]
$$

where `δ_b` is the integer dispersion shift for band `b` and `n` is sensor noise (Gaussian with σ given by the L3 benchmark instance).

Compactly: `y = Φ x + n` where `Φ: ℝ^(HWB) → ℝ^(HW)` is the CASSI forward operator.

## 3. Domain Ω (Parameter Ranges)

| Parameter | Symbol | Range | Unit | Notes |
|-----------|--------|-------|------|-------|
| Spatial resolution | H × W | 256×256 to 1024×1024 | px | Power-of-two strongly preferred |
| Spectral bands | B | 28 ≤ B ≤ 64 | bands | Uniformly spaced in wavenumber |
| Wavelength range | λ_min – λ_max | [400, 700] nm (visible) | nm | Other bands defined as variants |
| Dispersion shift | δ | 1 to 4 px per band | px/band | Linear in band index |
| Mask density | ρ | 0.4 – 0.6 | unitless | Fraction of mask cells = 1 |
| Sensor noise | σ | 1e-3 to 5e-2 | rel. intensity | Gaussian, zero-mean |

## 4. Tolerance ε

A reconstruction `x̂` is accepted iff:

$$
\text{PSNR}(\hat{x}, x) \ge \varepsilon \qquad \text{with} \qquad \varepsilon = 28 \text{ dB}
$$

evaluated band-by-band and averaged across all bands. Spec-level ε is the **minimum** acceptable tolerance; L3 benchmarks may raise ε for harder tiers.

## 5. I/O Signature

```
input:
  x: float32 tensor of shape (H, W, B)          # ground-truth hyperspectral cube
  mask: uint8 tensor of shape (H, W)            # binary coded aperture
  dispersion: int tensor of shape (B,)          # per-band pixel shift δ_b
  sigma: float                                  # noise standard deviation

output:
  y: float32 tensor of shape (H, W)             # coded snapshot
```

The inverse problem (the one solvers solve) takes `(y, mask, dispersion, sigma)` and returns `x̂`.

## 6. Pre-conditions

- Mask `M` must be binary (0 or 1 only) — grayscale masks belong to a different spec.
- Dispersion `δ_b` must be monotonically increasing in `b` — non-monotone dispersion (e.g. doubly-dispersive CASSI / DD-CASSI) belongs to a sibling spec.
- The cube `x` is non-negative everywhere (it represents radiance).

## 7. Operator Type

`linear-forward` — the operator `Φ` is linear in `x` (the mask and dispersion are deterministic, not data-dependent).

## 8. References

- Wagadarikar, A. et al. "Single disperser design for coded aperture snapshot spectral imaging." *Appl. Opt.* 47, B44–B51 (2008).
- Kittle, D. S. et al. "Multiframe image estimation for coded aperture snapshot spectral imagers." *Appl. Opt.* 49, 6824–6833 (2010).

---

## File Mapping

| File | Role | How to regenerate |
|------|------|-------------------|
| `spec.md` | Source of truth | Human or LLM |
| `spec.json` | Structured metadata + Ω schema | LLM regenerates from §1 Description, §2 Math, §3 Domain Ω, §4 Tolerance, §5 I/O, §6 Pre-conditions, §7 Operator Type |

**Prompt for your LLM after editing `spec.md`:**

> Read `spec.md`. Regenerate `spec.json` so every field matches.
> Schema:
> `{ id, principle_id, name, description, operator_type, omega: {parameters: [{name, symbol, min, max, unit, notes}]}, epsilon: {metric, threshold, unit}, io_signature: {inputs[], outputs[]}, preconditions[], references[] }`
> Output only the JSON object.
