skill
analytical-figures-skill
Claude Code skill: publication-grade figures + gated analysis for analytical chemistry (FTIR/ATR, PXRD, calibration, chemometrics, CIF/crystal, cocrystal ID)
Set up
Skills are installed by placing their folder where your agent loads skills.
The download comes from github.com/TheDop/analytical-figures-skill itself, not from our server, so what you get is exactly what its author published.
Install instructions come from the README
README
synced Oct 22, 2026analytical-figures
Ask Claude Code for a calibration curve from your .spc files
and get a journal-ready figure with LOD/LOQ, confidence and prediction bands and a residual panel,
plus one self-contained Python script that reproduces it. Ask for a calculated PXRD pattern from
a CIF, a cocrystal-vs-physical-mixture call or PLS diagnostics with leakage-safe cross-validation
and get the same: a figure that passed its checks, and the code that made it.
analytical-figures is a Claude Code skill for analytical chemistry and spectroscopy: FTIR/ATR
and PXRD spectra, calibration with figures of merit (LOD/LOQ, recovery, ICH Q2), multivariate
calibration (PLS/PCR/PCA), crystal structures from CIFs (validation table, calculated PXRD,
deterministic 3D views) and cocrystal identification.
It is not a plotting tutorial. It does two things a plotting library does not:
- It gates the numbers before they reach a figure. Ingest checks, identical processing across a batch, named error statistics (SD vs SEM vs CI, with n), leakage-safe cross-validation, mandatory residual panels, no extrapolation past the calibrated range, and a static critic that flags a figure-of-merit hand-typed onto a figure instead of interpolated from the code.
- It hands over a script, not a PNG. The deliverable is one self-contained Python file
(
bundle.pyamalgamates the modules an analysis uses) with a provenance header, so every figure is reproducible, editable and attachable to a report.
Hover a tile for what it is and where the data came from; click for full size. Every tile is produced by docs/build_gallery.py from public data and public CIFs — nothing is drawn by hand and nothing is synthetic. Interactive version with placards: https://thedop.github.io/analytical-figures-skill/
From a prompt to a figure
Three prompts, run in this repository with the skill loaded. Left: the prompt and the gates that fired on the way. Right: what came back. Every run hands over one self-contained script that regenerates its figure, and the caption is interpolated from the computed values, never typed.
Install
As a plugin, from inside Claude Code (two commands; the repo is its own marketplace):
/plugin marketplace add TheDop/analytical-figures-skill
/plugin install analytical-figures@analytical-figures-marketplace
Or clone into a Claude Code skills directory, user-level or per project:
git clone https://github.com/TheDop/analytical-figures-skill ~/.claude/skills/analytical-figures # available in every project
git clone https://github.com/TheDop/analytical-figures-skill .claude/skills/analytical-figures # this project only
Either way, install the Python side once:
python -m pip install -r requirements.txt # from the cloned/installed skill directory
numpy and matplotlib are required; scipy is strongly recommended. Everything else is
per-family and imported lazily, so an FTIR job never pulls it: requirements.txt adds
scikit-learn (chemometrics) and rdkit (the cocrystal predictor); the crystal family needs
python -m pip install gemmi Dans-Diffraction (plus pymatgen for the PXRD cross-check and
pyvista for the VTK renders), which the skill asks for by name the first time a CIF job runs.
Claude Code loads the skill at session start. Then ask for what you need: a replicate overlay
with %RSD, a calibration curve with LOD/LOQ, a calculated PXRD pattern from a CIF, a
cocrystal-vs-mixture call.
What is inside
| Path | Role |
|---|---|
SKILL.md | The operating instructions Claude reads: workflow, hard principles, the single-CONFIG rule. |
scripts/ | The maintained modules: config, style, verify, spectra, calibration, chemometrics, charts, doe, report, crystal_engine, crystal_pxrd, crystal_view, pxrd_realism, cocrystal, sources. |
references/ | Decision docs: figure_selection.md (what to plot, and why), cocrystal_id.md (which evidence identifies a cocrystal), databases.md (where to source each external fact), plus per-family conventions. |
templates/analysis_template.py | Copy this to start an analysis; bundle.py turns it into a standalone deliverable. |
cli.py | QC shortcuts: .spc replicates to band area/%RSD, a conc/signal CSV to slope, R², LOD/LOQ. |
assets/styles/ | Journal .mplstyle presets (Nature, ACS, IEEE, general). |
tests/, skill_validation/ | The test gate and the numeric-parity suites, below. |
ROADMAP.md, VISION.md | Backlog and build log; longer-range ideas. |
The modules are plain Python, so the skill also works without Claude: run from the skill root
and from scripts import spectra, calibration as the template does.
Validation
python -m pytest tests/ is one green gate for the whole skill (81 tests). It checks module
imports, the SKILL.md structure, the bundle.py round-trip, p-value correction against
statsmodels, the style presets and the CLI, and it bridges in three numeric-parity suites:
| Suite | Checks | Validated against |
|---|---|---|
skill_validation/chemometrics/ | 100 | closed-form fixtures, scikit-learn, published R mdatools critical limits, the biospectools EMSC gold |
skill_validation/cocrystal/ | 26 | closed-form Rwp, scipy.optimize.nnls, the Cruz-Cabeza ΔpKa zones |
skill_validation/pxrd/ | 23 | March–Dollase, Cu Kα₁/Kα₂ doublet, Caglioti, pseudo-Voigt |
| skill_validation/ftir_integration/ | 14 | closed-form Gaussian areas and scipy.integrate.quad under sloping baselines, noise and band overlap; plus the integrator run against the published pectin-DM (Wang 2023) and BMC 2021 calibrations |
| skill_validation/crystal/ | 9 CIFs | a CIF edge-case set (disorder groups, special positions, Z′ = 9, chiral, multi-block, synthetic broken inputs): the engine's table, an independent gemmi-only second opinion, ADP U_eq, the Dans reflection list vs pymatgen. Needs gemmi + Dans_Diffraction; pytest skips it otherwise |
The 24 pectin spectra (CC BY 4.0) are vendored. Data that cannot be redistributed is fetched on
demand instead: the biospectools EMSC gold and the R pls gasoline set
(skill_validation/chemometrics/datasets/fetch.py) and the CCDC CIFs. Every check that needs
one of them skips cleanly when it is absent.
Known limitations
- The crystal family is written for small-molecule cells. Bond, geometry and H-bond searches use a KD-tree on a cached supercell, but the first calculated pattern per structure still parses the CIF and computes structure factors (seconds for a few hundred atoms); later calls reuse the cache.
- The realistic PXRD profile evaluates each reflection within ±40 FWHM of its centre (
window_fwhm); the discarded Lorentzian tail is below counting quantisation on lab patterns, andwindow_fwhm=Nonerestores the exact full-grid sum. audit_layoutis a set of heuristics (tick overlap, clipping, letters, unit cues). It catches the common faults; reading the saved PNG is still part of the workflow, not a formality.
Provenance and licence
Built during an MSc analytical-chemistry project: quantifying an API in a binary excipient mixture by ATR-FTIR, then identifying cocrystals by FTIR and PXRD. The worked examples in the docs (aspirin in lactose, theophylline cocrystals) come from that work.
MIT licence (see LICENSE). The figure-selection scaffolding and the panel-label alignment
trick are adapted from scipilot-figure-skill
(MIT, Haojae); details in THIRD_PARTY_NOTICES.md.