Documentation

This page documents the lab's instruments: what each of the 39 tools computes, what it promises, and where those promises end. It is written for anyone pointing an agent at the server, whether to certify a palette, design a spectrum, or check our arithmetic against their own.

39 tools · 7 groups · one server

Quickstart

The install switcher above covers every supported client; the steps below assume you have completed one of them.

claude mcp add maryslab -- node mcp/dist/server.js

The engines

Two engines answer every call, and they are not allowed to disagree. A TypeScript reference engine defines the math; a C++20 core behind a stable C ABI reproduces it. Parity is enforced from both directions: 401 golden vectors, generated from the reference engine and checked by the native test suite, pin the numbers, while a shared suite of metamorphic relations (round trips, metric axioms, white-point preservation, spectral linearity) verifies that both engines obey the same algebra, not merely the same examples. Every response is stamped with its engine version, ABI version, and dataset snapshot, so a result can always be traced to the exact code and data that produced it.

401 golden vectors, three engines

Generated from the TypeScript reference engine, checked in CI against the native C++ build. This runs them through the WebAssembly build of that same core, in your browser, at the tolerance the native test uses.

the vectors · the harness · the CI job

The rest of what this site claims, and the command that reproduces it.

Native C++ suite 94 tests
cmake -B build -DMARY_BUILD_TESTS=ON && cmake --build build && ctest --test-dir build
TypeScript suite 194 tests
cd mcp && npx vitest run
Statement coverage 93.11%
cd mcp && npx vitest run --coverage
Fuzzing, every tool reached 0 findings
cd mcp && node test/fuzz/fuzz.mjs 60
Memory safety ASan + UBSan clean
cmake -B build-san -DMARY_SANITIZE=ON -DMARY_BUILD_TESTS=ON && ctest --test-dir build-san

Colorimetry Basics

Core color math: space conversions, perceptual difference, appearance under different lights, and the physical limits of surface color. These are the workhorse tools the rest of the surface builds on.

convert_color_space

Converts colors or spectra between representations (sRGB, XYZ, Oklab, raw SPDs, or dataset records) in batches. sRGB outputs carry explicit out-of-gamut flags instead of being clipped quietly.

inputs array of color inputs, 1..500
Colors or spectra: {space: srgb|xyz|oklab, value}, an SPD, or a dataset record id
to enum: xyz | oklab | srgb
Target color space
illuminant enum D65|D50|A|E, default D65
Illuminant used when integrating spectra
observer enum, default cie1931_2deg
Standard observer for spectral integration

returns Converted values in the target space, with out-of-gamut flags when the target is sRGB.

"Convert these five reflectance records to Oklab under illuminant A"

compute_delta_e

Computes perceptual color difference between a set of colors, either as a full pairwise matrix or along consecutive pairs, optionally as seen by a color-deficient observer. It also points out the closest pair.

colors array of color inputs, 2..200
Colors or spectra to compare
mode enum, default pairwise_matrix
pairwise_matrix or consecutive_pairs
metric enum, default delta_e_ok
delta_e_ok (Oklab) or ciede2000
under_cvd CVD profile, optional
Evaluate differences as perceived under protan/deutan/tritan at a given severity

returns The ΔE matrix or pair list plus the minimum-distance pair.

"Compute the pairwise ΔE matrix for my 8 chart colors as a full deutan would see them"

estimate_cct

Estimates correlated color temperature and Duv for light sources by finding the nearest point on the Planckian locus in CIE 1960 UCS with parabolic refinement.

inputs array of color inputs, 1..200
Light source colors or SPDs

returns CCT in kelvin and Duv per input.

Flags chromaticities with |Duv| > 0.05, where a CCT number is not physically meaningful.

"What is the CCT and Duv of this measured LED spectrum?"

adapt_chromatic

Predicts how a color seen under one illuminant will appear under another, using CAT16 von Kries chromatic adaptation with a controllable degree of adaptation.

inputs array of color inputs, 1..500
Colors to adapt
from_illuminant enum D65|D50|A|E
Illuminant the colors were viewed under
to_illuminant enum D65|D50|A|E
Illuminant to adapt to
degree number 0..1, default 1
Adaptation completeness (0 = none, 1 = full)
output_space enum xyz|oklab|srgb, default xyz
Space for the adapted result

returns Adapted colors in the requested output space.

"Predict how these brand colors will look when the viewer adapts from D65 daylight to incandescent A"

find_dominant_wavelength

Finds the dominant wavelength and excitation purity for colors using the standard CIE definitions, i.e. the monochromatic hue that matches each color. Purples get a complementary wavelength instead.

colors array of color inputs, 1..200
Colors to analyze
white_illuminant enum D65|D50|A|E
White point the definitions are taken against

returns Dominant (or complementary) wavelength in nm and excitation purity per color.

"Find the dominant wavelength and purity of this filter's transmitted color against D65"

check_gamut

Tests whether colors are physically realizable as diffuse surface colors, i.e. whether they lie inside the MacAdam object-color solid for a given illuminant. Returns signed margins rather than a bare yes/no.

colors array of color inputs, 1..500
Colors to test
illuminant enum D65|D50|A|E, default D65
Illuminant defining the object-color solid
resolution int 16..256, default 96
Solid discretization resolution

returns Per-color inside/outside verdicts with signed distance margins to the solid boundary.

"Are any of these paint targets physically impossible surface colors under D50?"

compute_macadam_solid

Builds the full MacAdam object-color solid mesh (the boundary of all physically possible surface colors, via two-transition optimal colors) for an illuminant.

illuminant enum D65|D50|A|E, default D65
Illuminant the solid is computed for
resolution int 16..256, default 96
Mesh resolution
output_space enum xyz|oklab, default oklab
Space the mesh vertices are expressed in

returns A mesh of the object-color solid boundary in XYZ or Oklab.

"Build the object-color solid under illuminant A in Oklab so I can plot it against sRGB"

map_to_gamut

Maps out-of-gamut colors into sRGB perceptually: Oklch lightness and hue are preserved and only chroma is compressed toward the gamut boundary. It reports exactly what was changed.

colors array of color inputs, 1..500
Colors to bring into the sRGB gamut

returns In-gamut sRGB colors plus a report of which inputs were modified and by how much.

"Bring these wide-gamut Oklab colors into sRGB without shifting their hue or lightness"

Dataset & Spectral Analysis

Access to the MARY-DATA spectral catalog (380..750 nm, 10 nm grid, 38 samples) and tools for representing, reconstructing, and decomposing spectra.

search_spectra

Searches the MARY-DATA catalog by metadata: free text, domain, source, license, Oklab color proximity, or sRGB gamut membership. Returns paginated record summaries; use get_spectrum for full values.

query string up to 200 chars, optional
Free-text search over record metadata
domain enum, optional
material_reflectance, biological, cvd_calibration, illuminant, or emission
oklab_near object {L, a, b, max_delta_e}, optional
Find records whose color is within a ΔE radius of a target Oklab point
in_srgb_gamut boolean, optional
Restrict to records whose color fits (or does not fit) in sRGB
limit int 1..200, default 25
Page size
offset int, default 0
Pagination offset

returns Record summaries (ids, names, domains, licenses) matching the filters.

"Find material reflectance records whose color is within ΔE 0.05 of this teal in Oklab"

get_spectrum

Fetches full spectral values on the canonical 380..750 nm, 10 nm grid, plus provenance metadata, for up to 50 catalog records at once.

ids array of 1..50 record ids
Catalog record identifiers
include_provenance boolean, default true
Include source and measurement provenance

returns Full 38-sample spectra with provenance for each requested id; unknown ids fail loudly.

"Get the full spectra and provenance for these three macbeth patch records"

get_dataset_info

Reports snapshot-level statistics for the dataset: record counts per domain and source, licenses, and the snapshot identifier.

returns Dataset snapshot statistics and license breakdown.

"How many records are in the current dataset snapshot and under what licenses?"

expand_spectrum_basis

Projects spectra onto a Chebyshev polynomial basis, giving a compact coefficient representation together with the reconstruction error incurred. Only accepts actual spectra (SPD or record inputs), not tristimulus colors.

inputs array of spd/record inputs, 1..200
Spectra to project
basis enum, default chebyshev
Functional basis (currently Chebyshev only)
order int 2..36, default 16
Basis order (number of coefficients)

returns Coefficient vectors plus per-spectrum reconstruction error.

"Compress these 40 measured reflectances to order-12 Chebyshev coefficients and tell me the worst reconstruction error"

synthesize_spectrum

Reconstructs spectra from Chebyshev coefficients on any wavelength grid you choose, optionally applying the analytic derivative first. The inverse of expand_spectrum_basis.

coefficients array of coefficient vectors (3..65 each), 1..200
Chebyshev coefficients per spectrum
operation enum none|derivative, default none
Optionally evaluate the analytic derivative instead of the function
grid object {start_nm, end_nm, step_nm}, default 380..750 @ 10
Output wavelength grid

returns Spectra evaluated on the requested grid.

"Rebuild these compressed spectra on a 1 nm grid and also give me their derivatives"

decompose_spectrum

Fits a spectrum as a sum of Gaussian peaks plus a flat baseline using Levenberg-Marquardt, for emission and fluorescence band analysis.

input one color input (spd or record)
The spectrum to decompose
max_peaks int 1..8, default 4
Maximum number of Gaussian components

returns Peak centers, FWHM widths, amplitudes, baseline, and the fit R squared.

"Decompose this fluorescence emission spectrum into its component bands"

estimate_spectrum

Reconstructs a plausible reflectance spectrum from a tristimulus color by picking the smoothest (curvature-minimizing) metamer consistent with it.

colors array of color inputs, 1..100
Colors to invert to spectra
illuminant enum D65|D50|A|E, default D65
Illuminant the colors were observed under

returns One smooth reflectance spectrum per input color; unrealizable targets fail with NO_SOLUTION.

The result is one of infinitely many metamers, not the true spectrum of any particular object.

"Give me a plausible reflectance curve for this sRGB swatch measured under D65"

CVD & Accessibility

Simulating color vision deficiency, remapping palettes for discriminability, and generating palettes with hard guarantees for every listed observer.

simulate_cvd

Simulates how colors appear to a color-deficient observer using the Machado 2009 physiological model, covering protan, deutan, and tritan at any severity from 0 to 1.

profile object {type: protan|deutan|tritan, severity 0..1 default 1}
Which deficiency and how severe
colors array of color inputs, 1..500
Colors to transform

returns The colors as perceived under the specified deficiency.

"Show me how my dashboard's 10 status colors look to a severity-0.7 protan observer"

compensate_cvd

Remaps a palette so its colors stay mutually distinguishable under a color vision deficiency, using constrained daltonization in Oklab with optional locked anchor colors.

profile CVD profile object
Deficiency to compensate for
colors array of color inputs, 2..64
The palette to remap
min_delta_e_ok number 0.01..0.5, default 0.06
Required minimum pairwise ΔE_OK under the deficiency
preserve_lightness_tolerance number 0..0.2, default 0.02
How much each color's lightness may move
anchored_indices int array, default []
Palette positions that must not change (e.g. brand colors)

returns A remapped palette meeting the separation floor, or an error carrying the best achievable bound.

Remaps for discriminability only; it cannot restore information lost to dichromacy. Infeasible constraints fail loudly with the achievable bound.

"Remap this 12-color categorical palette so a deutan observer can tell every pair apart, but keep colors 0 and 3 fixed"

render_telemetry_palette

Generates an N-class palette with a guaranteed minimum ΔE_OK under normal vision and under every CVD profile you list simultaneously. Built for safety-critical telemetry displays.

n_classes int 2..32
Number of palette classes
min_delta_e_ok number 0.01..0.5, default 0.15
Guaranteed separation floor (0.15 is safety-critical grade; JND is about 0.02)
cvd_profiles array of up to 3 CVD profiles, default full protan + deutan
Observer conditions the guarantee must also hold under
anchors array of {index, color}, up to 8
Fixed colors at specific palette positions
lightness_range [min, max], default [0.35, 0.85]
Allowed Oklab lightness band
seed int, default 42
Deterministic search seed

returns A palette certified to meet the floor for all listed observers, or a loud infeasibility error stating what was achievable.

The default floor is deliberately strict, so feasible class counts are small by design; infeasibility reports the achieved bound instead of silently relaxing.

"Generate a 7-class alarm palette that keeps ΔE_OK at least 0.15 for normal, protan, and deutan vision"

Certificates & Bounds

Tools that return guarantees rather than samples: provable ceilings on palette quality, discriminability certified over entire illuminant families, safe blending regions, and feasibility oracles for spectral constraints.

certify_palette_ceiling

Answers how good ANY N-color palette can possibly be: a certified upper bound on the achievable minimum pairwise ΔE_OK (worst case across CVD profiles) via a covering argument, plus a constructed witness palette as the lower bound.

n_classes int 2..32
Palette size to bound
cvd_profiles array of up to 3 CVD profiles, default full protan + deutan
Observer conditions in the worst case
threshold_delta_e_ok number 0.01..0.5, optional
A specific floor to test feasibility against
gamut_steps int 6..12, default 9
Covering grid density
seed int, default 42
Witness construction seed

returns An upper bound and a witness lower bound that together bracket the true optimum for your exact case.

Brackets the optimum rather than computing it exactly; the point is that published feasibility figures are one-observer napkin estimates while this is computed for your configuration.

"What is the best minimum ΔE any 16-class palette could achieve if it must also survive full protan and deutan vision?"

certify_illuminant_robustness

Certifies that a set of surfaces stays mutually discriminable under EVERY illuminant in a convex family you specify, not just at sampled lights. It exploits XYZ being linear in the illuminant, so the reachable set is exactly the convex hull of basis responses.

surfaces array of color inputs, 2..24
Surface spectra or records to certify
basis array of 1..4 illuminant names, default [D65, A]
Corners of the illuminant family; accepts D65/D50/A/E, BB<kelvin>, LED<nm>
threshold_delta_e_ok number 0.001..0.5, default 0.02
Discriminability floor to certify
divisions int 2..12, default 6
Grid density for the Lipschitz-bounded Oklab step

returns A pass/fail certificate over the whole family, with the binding surface pair; reports grid_sufficient false and a recommended division count when the nonlinear correction dominates.

The XYZ stage is exact (no relaxation); only the Oklab step uses a Lipschitz bound, and the tool says so when that bound is too loose to decide.

"Certify these 6 fabric swatches stay at least ΔE 0.02 apart under every mix of D65 and 2700K blackbody light"

certify_blend_safety

Computes the convex core of the sRGB gamut in Oklab: a verified shrink factor such that any linear blend (gradients, midpoints, crossfades) between colors inside it stays in gamut.

boundary_steps int 6..16, default 10
Boundary sampling density for the certificate

returns The certified shrink factor defining the safe interpolation region, with the sampling density stated.

A sampled certificate with stated density, not a closed-form proof.

"Give me the safe Oklab region where I can crossfade any two UI colors without ever leaving sRGB"

solve_spectral_constraints

A feasibility oracle for multi-illuminant color demands: does any physical reflectance show color A under illuminant 1, color B under illuminant 2, and so on, within tolerances? Returns a verified witness spectrum or a conflict-localized infeasibility report.

constraints array of 1..6 objects {illuminant, target color, tolerance_delta_e_ok default 0.01}
The simultaneous appearance demands

returns A verified witness reflectance, or an infeasibility report naming the smallest conflicting constraint subsets.

Generating multi-condition metamers when they exist is prior art; the new part is the decision procedure with conflict localization when they do not.

"Is there a physical surface that looks like this warm gray under D65 but shifts to this green under illuminant A?"

Inverse Design & Adversarial

Designing physical spectra to order (palettes, test stimuli, benchmark confusions), attacking colorimetric systems with realizable lights, and mapping the geometry of metamerism.

design_spectral_palette

Designs N reflectance SPECTRA (not colors) whose mutual separation holds jointly across every illuminant-times-observer condition you list. A palette designed in a color space is only safe under its design illuminant; designing the physical spectra removes that failure mode.

n_classes int 2..16
Number of spectra to design
conditions array of 1..8 {illuminant, cvd}, default D65 + A + D65-deutan
Viewing conditions the separation must hold under
target_min_delta_e_ok number 0.01..0.5, optional
Separation floor to hit; omit to maximize
order int 2..16, default 6
Chebyshev order of the designed spectra
iterations int 100..20000, default 2000
Optimization budget
seed int, default 42
Deterministic seed

returns N physical reflectance spectra with the achieved worst-condition separation; unreachable targets fail with the achieved bound.

"Design 5 physical pigment spectra that stay distinguishable under daylight, incandescent, and deutan vision at once"

design_discrimination_test

Designs a spectrally-realizable color-vision test stimulus: a pair of reflectances a normal trichromat separates easily but the target deficiency cannot. Optimizes the stimulus directly from spectra instead of the trial-and-error used for pseudoisochromatic plates.

target CVD profile
The deficiency the stimulus should be invisible to
illuminant enum D65|D50|A|E, default D65
Viewing illuminant
max_target_delta_e_ok number 0.001..0.1, default 0.02
Maximum separation allowed for the target observer
iterations int 100..20000, default 3000
Optimization budget
seed int, default 42
Deterministic seed

returns A reflectance pair with its normal-vision and deficient-vision separations.

A research stimulus designer, not a validated clinical screening test.

"Design a reflectance pair that a normal observer separates clearly but a full tritan cannot tell apart under D65"

synthesize_adversarial_spectrum

Finds a physically realizable illuminant that collapses a palette's color separation for a human observer, an adversarial light. Prior adversarial color work attacks CNNs in pixel space; this attacks a colorimetric system with a real light source.

palette array of color inputs, 2..16 (spectra required)
The palette to attack
baseline_illuminant enum D65|D50|A|E, default D65
Reference light the palette was evaluated under
observer CVD profile or null, default null
Optionally attack a color-deficient observer instead
iterations int 100..20000, default 2000
Optimization budget
seed int, default 42
Deterministic seed

returns The attack SPD, the separation degradation factor, and which color pair collapsed.

"Find a realizable lamp spectrum that makes my 6 wayfinding colors indistinguishable"

sample_metamers

Samples the metamer set: physically valid reflectances that all match a target color exactly under a given illuminant, using the convex-set framework of Logvinenko and Godau-Funt.

target one color input
The color every metamer must match
illuminant enum D65|D50|A|E, default D65
Matching illuminant
count int 2..64, default 16
Number of boundary samples
seed int, default 42
Deterministic seed

returns The set center, boundary sample spectra, and a per-wavelength envelope; unrealizable targets error with NO_SOLUTION.

"Sample 20 physically valid reflectances that all match this mid-gray exactly under D65"

map_metamer_stratification

Maps how the SHAPE of the metamer set changes as you move through color space: which box constraints are active, how much free extent remains, and where transitions occur. Shows where metamerism is geometrically rich versus where a color nearly pins down its spectrum.

illuminant enum D65|D50|A|E, default D65
Matching illuminant
path neutral_ramp or {points: 2..64 colors}, default neutral_ramp
The path through color space to stratify along
steps int 2..32, default 8
Points sampled along the path
samples int 4..32, default 10
Metamer samples per point
seed int, default 42
Deterministic seed

returns Per-step active constraints and free extent, with detected shape transitions along the path.

A sampled stratification, not exact face-lattice enumeration.

"Map how metamer-set richness changes along the neutral ramp from black to white under illuminant A"

generate_metamer_benchmark

Generates a benchmark of physically realizable metameric confusions: pairs of valid surface reflectances that are identical under one illuminant and diverge under another. Useful for stress-testing color constancy and imaging pipelines.

anchors array of 1..16 color inputs, optional
Specific anchor colors; omitted means auto-chosen
anchor_count int 1..16, default 5
Number of anchors when auto-choosing
match_illuminant enum D65|D50|A|E, default D65
Illuminant under which pairs match
split_illuminant enum D65|D50|A|E, default A
Illuminant under which pairs diverge
items_per_anchor int 1..4, default 2
Confusion items generated per anchor
seed int, default 42
Deterministic seed

returns Benchmark items, each a reflectance pair with its match and split ΔE; unrealizable anchors fail with NO_SOLUTION.

Every item is a realizable surface, no pixel perturbation; it perturbs the surface where prior benchmarks perturb the lamp.

"Build a benchmark of 10 surface pairs that match under D65 but split apart under incandescent A"

Audits & Forensics

Interrogating artifacts you did not make: colormaps that lie about data structure, LUTs that corrupt tones, spectra that were quietly post-processed, images with physically impossible pixels, and radiation spectra with unknown peaks.

audit_colormap_topology

Certifies whether a colormap invents or destroys features in visualized data. A colormap is topologically faithful exactly when its perceived lightness profile is monotone; each interior extremum creates a ridge viewers see that the data lacks.

colormap named preset (viridis, jet, ...) or {stops}, default viridis
The colormap to audit; custom maps as 2..64 RGB stops
field object {values, width, height}, optional
A concrete 2D data field to evaluate the colormap against
persistence_threshold number 0.001..0.5, default 0.02
Minimum feature persistence counted as real

returns Monotonicity violations plus spurious and lost feature counts from persistent homology, per observer including CVD.

"Audit whether jet invents features in this 128x128 temperature field for both normal and deutan viewers"

audit_colormap_corpus

Runs the topological faithfulness audit across a whole corpus of colormaps at once, for normal and CVD observers, and ranks them by worst offender. Existing corpus studies check CVD accessibility; this checks whether the visualization tells the truth about structure.

colormaps array of 1..64 named presets or {name, stops} objects
The colormaps to audit
persistence_threshold number 0.001..0.5, default 0.02
Minimum feature persistence counted as real

returns A ranked audit of the corpus with per-map violation details.

Audits colormap definitions, not decoded figure images; image extraction is out of scope.

"Rank these 15 in-house colormaps by how badly they distort data topology for a deutan viewer"

audit_spectrum_provenance

Measurement forensics for reflectance curves: is this a real instrument measurement or something interpolated, smoothed, or synthesized? Looks for a missing noise floor, interpolation signatures, value quantization, and clamped extrapolation tails.

inputs array of color inputs, 1..100
Spectra to examine

returns Per-spectrum provenance findings with the specific signatures detected.

A triage signal only; thresholds are calibrated on synthetic negatives, not validated against verified instrument data.

"Check whether these vendor-supplied reflectance curves look like real measurements or smoothed synthetics"

audit_color_transform

Behavioral audit of a color transform supplied as a 3D LUT lattice: gray-axis tone reversals, neutral contamination, hue flips beyond 25 degrees, outputs escaping [0,1], and local tears. LUT viewers show you the transform; this tests what a sane transform must never do.

lattice flat number array, n^3 x 3 RGB values in [0,1]
The LUT lattice, red-fastest (.cube order)
lattice_size int 2..33
Lattice edge length n

returns A defect report listing each violation class with the offending lattice locations.

"Audit this 33-point film-emulation LUT for tone reversals and hue flips before we ship it"

audit_image_physicality

Issues a per-pixel physical impossibility certificate: which supplied sRGB pixels cannot be diffuse surface colors under ANY illuminant in a declared family at a given exposure, and by how much each overshoots.

pixels array of 1..4096 sRGB triples in [0,1]
Small pixel grids supplied directly, not decoded image files
basis array of 1..4 illuminant names, default [D65, A]
The illuminant family; accepts D65/D50/A/E, BB<kelvin>, LED<nm>
exposure number 0.1..10, default 1
Assumed exposure scaling

returns Per-pixel possible/impossible verdicts with overshoot magnitudes.

Fluorescent and emissive sources legitimately exceed the bound; the output says not-a-plain-surface, never fake.

"Which pixels in this sampled patch could not be a real matte surface under any daylight-to-incandescent light?"

diff_spectral_datasets

A perceptual and forensic diff between two versions of a spectral dataset. Classifies every changed record as renoised, smoothed, rescaled, or replaced, quantifies the perceptual impact under D65, and emits a CI gate.

before array of 1..500 {id, 38 values}
The earlier dataset version
after array of 1..500 {id, 38 values}
The later dataset version
allow_smoothed boolean, default false
Whether smoothing counts as an acceptable change
max_perceptual_delta number 0.001..0.5, default 0.05
Perceptual change budget for the gate

returns Per-record change classifications, perceptual impact, and a pass/fail CI gate that fails on silent post-processing of claimed measurements.

"Diff last month's dataset snapshot against today's and fail if any measured record was quietly smoothed"

could_be_same_surface

The forensic corollary of the constraint oracle: could two (illuminant, color) observations have come from the SAME physical surface? Answers with a witness reflectance or a physical impossibility finding.

observation_a object {illuminant, target color, tolerance_delta_e_ok default 0.01}
First observation
observation_b object {illuminant, target color, tolerance_delta_e_ok default 0.01}
Second observation

returns Either a witness reflectance consistent with both observations, or a finding that no diffuse surface can satisfy both.

Fluorescent or emissive materials are outside the bound, and the tool states this.

"Could the jacket that photographed navy under fluorescent store light be the same one that looks purple in this daylight photo?"

detect_photopeaks

Detects gamma-ray photopeaks in a pulse-height spectrum using SNIP continuum removal and a significance test; with an energy calibration supplied it returns ranked isotope candidates.

counts number array, 64..65536 channels
The pulse-height histogram
energy_calibration object {offset_kev, gain_kev_per_ch, quadratic}, optional
Channel-to-energy calibration enabling isotope matching
min_significance_sigma number, default 3.0
Detection significance threshold
match_tolerance_kev number up to 50, default 1.5
Energy window for isotope line matching

returns Detected peaks with significances, and ranked isotope candidates when calibrated.

Decision support only, never an authoritative isotope identification.

"Find the significant peaks in this 4096-channel NaI spectrum and suggest which isotopes they could be"

Correctness Infrastructure

Testing machinery for color code itself: metamorphic and differential testing of implementations, certified conformance vectors, and a static type checker for color pipelines.

crosscheck_color_implementations

Metamorphic and differential testing for color implementations. Checks algebraic identities any correct implementation must satisfy (round-trip identity, gamut-map idempotence, adaptation white preservation, ΔE metric axioms, spectral linearity, and more), shrinking any failure to a minimal witness.

cases int 1..2000, default 200
Random test cases per relation
relations array of relation names, optional
Subset of the 9 built-in algebraic relations; omitted runs all
external_results array of numeric triples, optional
Another library's outputs, enabling differential comparison
external_quantity enum oklab_from_srgb | xyz_from_srgb, default oklab_from_srgb
What quantity the external results represent
seed int, default 42
Deterministic case generation

returns Pass/fail per relation with shrunk minimal counterexamples, and per-case diffs when external results are supplied.

"Run all nine metamorphic relations with 1000 cases and diff my Python library's Oklab outputs against yours"

generate_conformance_vectors

Emits certified numeric test vectors for colorimetric transforms with documented formulae and tolerances, or scores a candidate implementation's outputs against them. Fills the gap left by ICC conformance, which validates profile structure rather than computation.

transforms array of transform names, default [srgb_to_xyz, xyz_to_oklab, ciede2000]
Which transforms to emit vectors for (8 available, incl. spd_to_xyz_d65 and cvd_deutan_full)
candidate_results array of numeric arrays, optional
Supply an implementation's outputs to score instead of just emitting vectors

returns Certified input/output vectors with tolerances, or a scored comparison of the candidate against them.

A reference suite where this engine is the oracle; its authority is published formulae and metamorphic self-consistency, not independent ground truth, so a disagreement means one of the two implementations has a defect to explain.

"Emit conformance vectors for sRGB-to-XYZ and CIEDE2000 so I can score our Rust port against them"

typecheck_color_pipeline

A static checker for color pipeline specifications. Tracks encoding, color space, and illuminant symbolically through a list of operations and flags the classic silent-corruption bugs: a matrix applied to gamma-encoded values, a doubled transfer function, resampling in a nonlinear encoding, or missing chromatic adaptation.

initial object {encoding, space, illuminant}, default nonlinear rgb D65
The state entering the pipeline
ops array of 1..64 op objects
Pipeline steps: decode/encode transfer, RGB-XYZ matrices, Oklab/Lab conversions, chromatic_adapt, cvd_simulate, blend, resize, spd_to_xyz

returns A per-step trace of encoding, space, and illuminant with flagged type errors and their locations.

"Typecheck this 12-step imaging pipeline and tell me if we ever blend or resize in a gamma-encoded space"

Honesty rules

The lab's standing discipline is that caveats travel with results, in the results themselves. Ask for a palette under constraints that cannot be met and the tool fails loudly, reporting the bound it actually achieved rather than quietly relaxing what you asked for. Certificates audit their own resolution: when the grid is too coarse to certify anything, the response says so instead of printing a hollow zero. The forensics tool states in its own output that it was calibrated on synthetic negatives, and its scores are decision support, never authoritative identification. A number without its limits is not a result here.