Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Docs usability: measurement-role snippet clarity, one-line result plots, responsive figures (#86)
* fix: responsive figure sizing — full-width on mobile, 92% plots on desktop (plan 16 T4)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: snippet clarity wave — recording/excitation convention (plan 16 T1)
Apply the recording/excitation naming convention from the P16 audit across
the calibration, intensity, block-processing, time-weighting, levels,
weighting and room-acoustics guides (docs/ + EN guides + ES guides).
- calibration: ref_signal->calibrator_recording, signal->recording (J1 cascade)
- intensity: probe-recording synth + swap-in disclosure on p1/p2
- block-processing / time-weighting: audio_blocks provenance comments
- levels / time-weighting / weighting: signal->recording, provenance upgraded to convention
- room-acoustics: play/record framing on sweep/recorded; synthetic-IR stand-in note
EN docs/guides kept code-identical; ES mirrored with UNE wording.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: one-line canonical plots on result objects (plan 16 T2)
Add a thin plot(ax=None, **kwargs) method to each result dataclass that
renders the essence of its guide's canonical figure in one line, following
the sklearn/statsmodels/librosa pattern. matplotlib stays a soft dependency:
importing phonometry and computing works without it; .plot() raises a clear
ImportError with install guidance. Rendering lives in a new lazy _plotting
module; dataclass methods are thin delegates.
Covers ZwickerLoudness, STIResult, WeightedRatingResult/ImpactRatingResult,
RoomAcousticsResult, SoundPowerResult/ReverberationSoundPowerResult/
SoundPowerIntensityResult, IntensityResult and a new frozen DecayCurve
(returned by decay_curve, tuple-unpackable for backward compat). Rating
results gain band_centers/measured/shifted_reference fields for the figure.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: plot kwargs forwarding, deterministic invalid-band test, octave-impact annotation
- _plot_rating now accepts **kwargs and forwards to the measured curve, so
result.plot(linewidth=2) no longer raises TypeError; parametrized test
covers every public .plot() forwarding a benign kwarg to its primary artist.
- Replace skip-if-all-valid room-acoustics invalid-band test with a directly
constructed RoomAcousticsResult (500 Hz band flagged invalid); assert exactly
the flagged bars are hatched and greyed.
- plot_impact_rating keeps the shifted-reference curve normatively honest
(ref - shift) and marks/annotates the 500 Hz read value with the ISO 717-2
Clause 4.3.2 -5 dB octave rule instead of distorting the curve.
- Move _bar_width next to its only consumer, plot_intensity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: .plot() one-liners and figure-code collapsibles (plan 16 T3)
Add one-line res.plot() mentions to every guide section whose result type
gained .plot() in T2, and figure-code collapsibles (both the one-liner and
the manual matplotlib path) under the five .plot()-backed data figures.
Document .plot() availability and the DecayCurve return type in the API
reference and CHANGELOG. EN docs + EN/ES site; llms-full.txt regenerated.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: collapsibles for STI-vs-T60 and open-plan figures
Controller follow-up to plan 16 T3: the two figures are reproducible with
public API only. STI-vs-T60 sweeps sti_from_impulse_response over synthetic
exponential IRs at a 10-point T60 grid; the open-plan collapsible rebuilds
the D2,S regression and rD/rP crossings from the OpenPlanResult fields.
EN docs + EN/ES site; executed on Agg; llms-full.txt regenerated.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: final-review polish — result-field docs, comment hygiene, naming
Document band_centers/measured/shifted_reference on WeightedRatingResult
and ImpactRatingResult (CHANGELOG + EN/ES API tables), strip internal plan
tags from theme-images.css and test_result_plots.py, note that [plot] also
powers result .plot() methods, tighten the plot_zwicker_loudness docstring
to say the two-panel layout only occurs when ax is None, sentence-case the
intensity provenance comments, and rename the shadowed impact rating var to
res_imp on the room-acoustics pages.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 86 review round 1 — log-axis bars, style kwargs overrides, snippet physics and notation
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
docs: restructure into docs/, slim PyPI-safe README, bilingual Starlight site with theme-aware figures (#61)
* docs: split README content into docs/ topic pages
11 topic pages under docs/ (guides + reference), including the new
levels/spectrogram documentation and a Why PyOctaveBand page distilled
from the issue #38 IEC 61672-1 compliance analysis.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: add auto-generated figures for levels/spectrogram/zero-phase docs
Four new generate_* functions (spectrogram example, LN levels over the
Fast envelope, zero-phase group-delay comparison, A-weighting HF accuracy),
a 'make graphs' target, and a CONTRIBUTING section formalizing that every
docs image must come from generate_graphs.py.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: slim README to hook + quick start with absolute links (PyPI-safe)
The README is the PyPI landing page and PyPI does not resolve relative
links, so every link (docs pages, website, CONTRIBUTING, LICENSE) is now
absolute. The Documentation section sits right after installation with a
per-page table. Full content lives in docs/ and on the website.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): scaffold Astro/Starlight with en/es i18n, KaTeX, and English content
Starlight site under site/ with base /PyOctaveBand for GitHub Pages,
locale-aware sidebar, KaTeX math rendering, and the 11 English pages
ported from docs/ (links rewritten to site routes, GitHub alerts
converted to Starlight asides).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: generate all figures in light and dark themes
generate_graphs.py now renders every figure twice (light + _dark suffix)
via a theme switch (dark_background style, foreground color swap).
- docs/ (GitHub): <picture> with prefers-color-scheme sources.
- site/ (Starlight): dual img.light-only/.dark-only following the theme
toggle via [data-theme] CSS.
- README keeps plain light images (PyPI sanitizes <picture>).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): add complete Spanish translation
Full natural translation of all 12 pages (landing, getting started,
7 guides, 3 reference pages) with theme-aware images and es/ routes.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* ci: deploy Starlight docs site to GitHub Pages
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* ci: bump actions to latest, dependabot cooldown 0, refresh all dependencies
- Workflows: checkout v7; docs.yml to setup-node v6, pnpm/action-setup v6,
upload-pages-artifact v5, deploy-pages v5 (pnpm stays 11.x).
- Dependabot: cooldown 0 days on all ecosystems, stop ignoring pip
minor/patch updates (grouped), add npm ecosystem for site/.
- Python deps to latest: scipy 1.18, matplotlib 3.11, numba 0.66,
mypy 2.1, ruff 0.15.20, pytest 9.1. numpy capped <2.5 in the dev/CI
environment because numba 0.66 requires it (users without the [perf]
extra are unaffected).
- Site deps to latest: astro 7.0.6, starlight 0.41.3, katex 0.17, sharp 0.35.
- Repo configured via API: homepage -> docs site URL, GitHub Pages enabled
with build_type=workflow (no manual post-merge step needed anymore).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: address review feedback (dependabot schema, snippets, workflow hardening)
- dependabot: remove cooldown blocks (default-days minimum is 1; no
cooldown IS the zero-delay behavior).
- docs.yml: scope pages/id-token permissions to the deploy job only and
set persist-credentials: false on checkout (third-party install scripts
run in the build job).
- Snippets: add missing numpy import, define the bank in the zero-phase
example, linspace endpoint=False (docs + site EN/ES + README).
- tsconfig: exclude node_modules and .astro explicitly.
- A-weighting +2.00 constant kept: verified numerically that
20*log10(RA(1000)) = -1.99986, so +2.00 yields 0.0001 dB at 1 kHz;
the suggested +2.06 would introduce a +0.06 dB offset.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
docs: content enrichment (4 new figures, diagrams, equations) + full SEO/GEO layer (#66)
* docs: add group-delay, IEC toneburst, block-continuity and class-mask figures
Four new auto-generated figures (light+dark) wired into the filter-banks,
time-weighting, why-pyoctaveband and block-processing pages (docs/ EN +
site EN/ES), including a new 'Verifying the IEC 61260-1 class' section
documenting verify_filter_class with the acceptance-mask overlay.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: remove unreferenced legacy filter_fraction_* images
Leftovers from the pre-restructure README naming; nothing references
them (docs, site, scripts). Light/dark figure parity is now exact 26/26.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): GEO layer - robots.txt AI opt-in, llms.txt generation, mermaid
- robots.txt: universal allow + Content-Signal + explicit opt-in for 14 AI
crawlers + sitemap pointer.
- scripts/gen_llms.py generates llms.txt (structured project context with
AI-assistant install notes) and llms-full.txt (all docs pages inline);
committed at root, republished to the site via prebuild copy and
regenerated in the docs workflow for freshness. New 'make llms' target.
- astro-mermaid (+ mermaid) with autoTheme for the new calibration and
multirate diagrams; starlight-links-validator and lastUpdated enabled.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): SEO/GEO layer complete - JSON-LD, per-page heads, quality gates
- Site-wide JSON-LD @graph (Person with canonical jmrp.io identity incl.
ORCID, WebSite, SoftwareApplication with single-sourced version and
feature list, SoftwareSourceCode) + og/twitter/author/theme metas,
rel=me links, PGP key, manifest, Bing verification (Google property
already verified).
- Head.astro: per-page TechArticle (+speakable) and locale-aware
BreadcrumbList linked into the @graph, canonical URLs, twitter tags.
Footer.astro maintainer block. favicon.svg + PWA manifest.
- Quality gates: sitemap lastmod stamping (git dates, postbuild), EN/ES
i18n parity check, html-validate and pa11y (WCAG2AA) wired into the
docs workflow with fetch-depth: 0.
- Accessibility sweep: descriptive EN/ES alt text on all 147 figure
references; site uses style width (valid HTML), GitHub docs keep the
width attribute.
- Splash landing now shows the mobile menu button (route middleware
enables the sidebar; CSS hides the pane on desktop to keep the hero).
- og-image: designed 1200x630 card (gpt-image-2 via inference.sh, adapted
and committed); matplotlib generator kept as documented fallback.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: fix extraneous f-prefix and duplicate canonical link
Starlight already emits the canonical URL; Head.astro no longer adds a
second one.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): WCAG2AA - convert deprecated table align attributes to CSS
pa11y flagged 158 deprecated align attributes from markdown table
alignment; the rehypeTableAlign plugin (ported from the reference site)
rewrites them to text-align styles. 10/10 audited URLs now pass WCAG2AA.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: address review feedback (robustness, Table 4 consistency, llms links)
- version regex accepts single/double quotes; rehypeTableAlign appends to
existing styles; routeData guards undefined starlightRoute; Footer lang
detection handles /es without trailing slash; pa11y script kills by PID
(job control unavailable in some CI shells).
- why-pyoctaveband: the toneburst table is Table 4 in IEC 61672-1:2013
(Table 3 is the weightings) - fixed the stale issue-#38 wording, and
softened 'peaking exactly' to 'within 0.1 dB' (EN/ES).
- gen_llms.py absolutizes docs-relative links so llms-full.txt resolves
as a flat artifact.
- Intentionally NOT changed: docs/ keeps the width attribute on images
(GitHub strips style attributes); the site uses style widths.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf