Review report
Fresh two-persona agent review of all seven component guides, after the 2026-06-08 maintenance pass.
Every component guide is reviewed by an agent team — a MET / verification domain expert (technical faithfulness against the official docs) and a persona scientist (human-readability as a real target reader). This report was regenerated after a maintenance pass that cleared the priority backlog; it records the fixes applied, independent spot-checks confirming them, and the small set of documented issues that remain.
The review process
Section titled “The review process”- Generate. 24 pages (7 entrypoints + 16 deep dives + the ecosystem home) were authored from the official User’s Guides against a shared design contract, each with theme-reactive SVG diagrams.
- Review teams. Per component, a MET expert and a persona scientist independently review the pages, verifying claims against the source docs (fetching them where possible) and reading for clarity.
- Iterate. An editor applies the feedback — verifying every factual correction against the source before writing it, and preserving the design contract.
- Fresh re-review. A new expert + persona team re-checks the revised pages, runs independent falsifiable spot-checks, and documents what remains. This report is the output of that fresh pass.
- Verified facts are protected. A short list of source-verified facts (minimum MET version, the line type ROC_AUC lives in, scorecard significance bands, …) is carried forward so a later reviewer does not “correct” something that is already right.
Outcome summary
Section titled “Outcome summary”All seven components pass. 0 of seven are clean (no open issues); across the whole set 42 documented issues remain, almost entirely minor clarity / consistency nits that are acceptable for a curated, overview-first derived guide.
| Component | Verdict (expert · persona) | Open |
|---|---|---|
| MET | pass · minor pass · minor | 7 |
| METplus | pass · minor pass · minor | 7 |
| METcalcpy | pass · minor pass · minor | 4 |
| METplotpy | pass · minor pass · minor | 6 |
| METdataio | pass · minor pass · minor | 6 |
| METviewer | pass · minor pass · minor | 6 |
| METexpress | pass · minor pass · minor | 6 |
“Open” counts issues the fresh review still considers present; each is documented in the component section below with a suggested fix. Spot-checks confirm the maintenance fixes and the verified facts held.
7 open · expert pass·minor · persona pass·minor
Fresh-review verdicts — Domain expert: pass · minor Persona scientist: pass · minor
Maintenance fixes applied (2026-06-08)
Section titled “Maintenance fixes applied (2026-06-08)”- Glossed the line-type acronyms on first use in
point-stat.html— POD, FAR, CSI, HSS (CTS row), Hanssen-Kuipers and Gerrity (MCTS), Brier score and ROC area (PSTD); added a plain-language hint to the SEEPS row. - Gave the
DW_MEANandLS_FITinterpolation rows human-readable labels. - Glossed CRPS (Continuous Ranked Probability Score) in the
index.htmlEnsemble card.
Independent spot-checks
Section titled “Independent spot-checks”| Result | Reviewer | Claim checked | How verified |
|---|---|---|---|
| ✓ confirmed | expert | point-stat.html DW_MEAN row: ‘Weights are the reciprocal of squared distance in grid coordinates, so closer points count more.‘ | MET Point-Stat User’s Guide: ‘The weight given to each forecast point is the reciprocal of the square of the distance (in grid coordinates) from P.’ Inverse-distance-squared confirmed. |
| ✓ confirmed | expert | mode.html: filter normalization ‘π R² H = 1’ and default total-interest threshold 0.7, with unmatched objects shown in royal blue. | MET MODE User’s Guide: ‘They are related by the requirement that the integral of φ over the grid be unity: πR²H = 1’; default total interest threshold 0.7; ‘objects that are colored royal blue are unmatched’. All three match the page. |
| ✓ confirmed | expert | point-stat.html PSTD row lists Brier score and ROC area, and CTS row glosses POD/FAR/CSI/HSS (recent fix held); ECNT/ORANK/RPS are HiRA-only. | MET Point-Stat docs: PSTD Table 11.9 has BRIER and ROC_AUC; CTS Table 11.4 has PODY/FAR/CSI/HSS; HiRA produces ECNT/ORANK/RPS. The CTS-row glosses (probability of detection / false alarm ratio / critical success index / Heidke skill score) are present on point-stat.html line 331. |
| ✓ confirmed | expert | grid-stat.html neighborhood example ‘10 of the 25 forecast grid points … coverage is 10/25 = 0.4’ and DMAP metrics (Baddeley Δ, Hausdorff, Pratt’s FOM, Zhu, G_β) are source-accurate; Figure 1 inset 3×3 = 5/9 geometry. | MET Grid-Stat docs reproduce the 10/25=0.4 example verbatim and Table 13.6 lists Baddeley Δ, Hausdorff, MED, FOM, ZHU, G, G_β. Recomputed SVG inset: window rect x44-176/y44-176 (3×3); 5 event rects all inside → 5/9 consistent with figcaption and desc. |
| ✓ confirmed | persona | Recent fix held: POD/FAR/CSI/HSS are glossed on first use in the point-stat.html CTS row. | point-stat.html line 331: “POD (probability of detection), FAR (false alarm ratio), CSI (critical success index), HSS (Heidke skill score)” all inline-glossed. |
| ✓ confirmed | persona | Recent fixes held: CRPS glossed in index.html Ensemble card; DW_MEAN/LS_FIT carry human labels in the #interp table; “double penalty” defined on index.html. | index.html L248-249 (“CRPS (Continuous Ranked Probability Score — … in the variable’s own units)”); point-stat.html L152/156 (“Distance-weighted mean (DW_MEAN)”, “Least-squares fit (LS_FIT)”); index.html L256-258 (double penalty defined as punished twice, false alarm + miss). |
| ✓ confirmed | persona | Verified fact held: ROC_AUC / ROC area is written in the PSTD line type (not PCT), and the probabilistic line-type grouping is correct. | point-stat.html L341 attributes “ROC area” to the PSTD row; diagram L267 groups PCT/PSTD/PJC/PRC as probabilistic without misplacing ROC into PCT. |
| ✓ confirmed | persona | Diagram geometry: MODE Fig 1 interest link joins F1 to O1 with the 0.92 badge at the midpoint, and Grid-Stat Fig 1 neighborhood inset shows 5 of 9 cells inside the 3x3 window (= 5/9), distinct from the 5x5 worked text example. | Recomputed: MODE link (514,159)->(536,294) starts on F1 lower edge and ends on O1 upper edge, badge center (525,226) = exact midpoint (525,226.5). Grid-Stat: all 5 shaded event rects fall inside window x[44,176] y[44,176]; caption correctly separates 3x3 inset (5/9) from 5x5 text example (10/25=0.4). |
Remaining — documented (minor / nit)
Section titled “Remaining — documented (minor / nit)”| Severity | Category | Reviewer | Page | Issue & suggested fix |
|---|---|---|---|---|
| Minor | consistency | expert | met/grid-stat.html | In the output line-types table the SEEPS row is placed in the ‘Categorical’ family. SEEPS (Stable Equitable Error in Probability Space) is a multi-category precipitation score that uses a climatology to weight dry/light/heavy categories — the official Grid-Stat docs describe it as ‘a multi-category score which uses a climatology to account for local variations in behavior’, not as a standard 2x2 categorical contingency-table line type. point-stat.html correctly presents SEEPS as its own precipitation score, so the two sibling pages disagree on how SEEPS is framed. Fix: Change the SEEPS family cell from ‘Categorical’ to ‘Precipitation’ (or ‘Multi-category / climatology-based’) to match how point-stat.html treats it and the source wording. |
| Minor | clarity | persona | met/point-stat.html | The acronym “ROC” is used in the PSTD line-type row (“…and ROC area (how well the probabilities discriminate events from non-events)”) and again in the PRC row (“Probabilistic ROC points”), but it is never expanded to “Receiver Operating Characteristic” anywhere on the page. By contrast grid-stat.html does spell it out. The function is described in plain words, so meaning is recoverable, but the letters ROC are introduced unglossed. Fix: On first use in the PSTD row, write “ROC (Receiver Operating Characteristic) area” to mirror the treatment in grid-stat.html. |
| Nit | accuracy | expert | met/point-stat.html | The Nearest Neighbor interpolation row says ‘No interpolation (W = 1).’ This conflates the method with the interpolation width. Nearest-neighbor returns the single closest grid value regardless of the configured width, whereas W is a separate neighborhood-size parameter; a user could set width>1 and still pick a non-nearest method. The parenthetical implies nearest-neighbor is width=1. Fix: Reword to e.g. ‘Assigns the value of the single closest grid point — no averaging’ and drop the ‘(W = 1)’ equation, or clarify that with width 1 every method reduces to the nearest grid point. |
| Nit | clarity | expert | met/index.html | The dataflow figure’s <desc> (lines 113-116) says the dashed box surrounds ‘the reformat and statistics tools’, but the dashed METplus band (rect x=262 y=44 … height=178) spans y 44-222, which visually encloses the Reformat & regrid box (y 60-106) and the Statistics tools box (y 138-202) — it does not enclose the Gen-Ens-Prod / ensemble-prep step, which is fine, but the prose ‘reformat and statistics tools’ is a slight under-description of what METplus actually wraps (it wraps essentially all MET tools). Cosmetic only. Fix: Optionally soften the desc to ‘…surrounds the central MET tool boxes to show that METplus wraps and automates these runs’ so it doesn’t over-specify exactly which tool categories are inside the band. |
| Nit | clarity | persona | met/index.html | In the “What MET is” section, “the Unified Forecast System (UFS) and SIMA” expands UFS but leaves SIMA unexpanded right beside it, so the two acronyms are treated inconsistently in the same clause. Fix: Expand on first use, e.g. “…and SIMA (System for Integrated Modeling of the Atmosphere)”, matching the UFS treatment. |
| Nit | clarity | persona | met/index.html | ”ATCF deck format” (TC card) and “ATCF ASCII format” (Inputs section) appear without ever expanding ATCF. A working forecaster will likely recognize it, but it is the one prominent TC-domain acronym left unglossed on the page. Fix: On first use add the expansion, e.g. “ATCF (Automated Tropical Cyclone Forecasting system) deck format”. |
| Nit | clarity | persona | met/index.html | Grid-Diag is described as building “joint and marginal distributions (multivariate PDFs)”. The parenthetical is meant to clarify, but it uses an unexpanded acronym (PDF = probability density function) that could be misread as the document format, so the gloss leans on jargon to explain jargon. Fix: Spell it out once: “multivariate probability density functions (PDFs)”, or drop the parenthetical since “joint and marginal distributions” already conveys the idea. |
METplus
Section titled “METplus”7 open · expert pass·minor · persona pass·minor
Fresh-review verdicts — Domain expert: pass · minor Persona scientist: pass · minor
No source edits this maintenance pass; the fresh review re-confirmed the earlier corrections still hold.
Independent spot-checks
Section titled “Independent spot-checks”| Result | Reviewer | Claim checked | How verified |
|---|---|---|---|
| ✓ confirmed | expert | PairStat is a current METplus wrapper that encapsulates the MET pair_stat tool, consumes forecast/observation pairs already matched in time and space (MPR from Point-Stat or via Python embedding), skips smoothing/regridding/interpolation, and computes continuous, categorical, and probabilistic statistics. | raw.githubusercontent.com/dtcenter/METplus/develop/docs/Users_Guide/wrappers.rst line 6234 (PairStat section, ‘encapsulates the MET pair_stat tool’) and MET develop docs/Users_Guide/pair-stat.rst: ‘data that has already been paired in time and space… no smoothing, regridding, or interpolation methods apply… computes continuous, categorical, and probabilistic verification statistics.’ |
| ✓ confirmed | expert | MakePlots is NOT a current wrapper (must not appear), while GFDLTracker and DataIngest ARE current wrappers. | grep of develop wrappers.rst: GFDLTracker (line 2040) and DataIngest (line 191) have sections; no MakePlots match. The doculizer catalog omits MakePlots and includes GFDLTracker + DataIngest. |
| ✓ confirmed | expert | METplus minimum requirements are MET 12.2.0 or above, Python 3.12.0 or above, python-dateutil 2.8; wrapper extras requests 2.32.5, netCDF4 1.5.4, cartopy 0.20.3, matplotlib 3.5.2. | metplus.readthedocs.io/en/latest/Users_Guide/installation.html via WebFetch: ‘MET version 12.2.0 or above’, ‘Python 3.12.0 or above’, python-dateutil 2.8, and exact package pins requests 2.32.5 / netCDF4 1.5.4 / cartopy 0.20.3 / matplotlib 3.5.2 — all match getting-started.html. |
| ✓ confirmed | expert | Design contract holds: no hard-coded hex colors, no <style> blocks, no inline style= attributes; SVGs use theme CSS vars; FOUC script first in <head>; shared ../assets/doculizer.css + theme-toggle.js; footers cite real sources with ‘derived guide’ note. | grep across all four files found zero hex colors / <style> / style= (only an SVG font-style=“italic” presentation attribute); manual read confirmed inline FOUC <script> is first in <head>, CSS/JS links present, footers cite metplus.readthedocs.io pages with the derived-guide disclaimer. |
| ✓ confirmed | persona | MakePlots is absent as a current wrapper across all four pages (recent fix held). | grep for MakePlots/MakePlot returned no matches in index/wrappers/use-cases/getting-started.html |
| ✓ confirmed | persona | PairStat consumes already-matched MPR pairs from Point-Stat / Python embedding and skips regridding+interpolation (verified fact held). | wrappers.html line 401: ‘pairs that are already matched in time and space (e.g. MPR output from Point-Stat, or supplied via Python embedding)… skipping the regridding and interpolation that Point-Stat performs.’ |
| ✓ confirmed | persona | METplus minimum MET version is stated as 12.2.0 or above (not 12.1.0). | getting-started.html line 92 ‘MET version 12.2.0 or above’ and line 379 ‘Confirm MET 12.2.0+’. |
| ✓ confirmed | persona | ’Python embedding’ and ‘strptime’ are glossed on first use in reading order on the pages that use them. | wrappers.html line 104 glosses Python embedding, line 258 glosses strptime; use-cases.html line 129 re-glosses Python embedding on its own first use. |
| ✓ confirmed | persona | PrepBUFR is spelled consistently and design contract holds (FOUC script first, shared CSS/JS, SVGs theme-reactive via var(), derived-guide footer). | grep: only ‘PrepBUFR’ spelling used; FOUC comment on line 7 + script line 8 first in head; no <style> blocks; no hardcoded hex in SVG fill/stroke; every SVG has role=img + aria-labelledby; derived-guide note in all four footers. |
Remaining — documented (minor / nit)
Section titled “Remaining — documented (minor / nit)”| Severity | Category | Reviewer | Page | Issue & suggested fix |
|---|---|---|---|---|
| Minor | clarity | persona | metplus/wrappers.html | In the PairStat catalog row (line 401), the acronym MPR (‘e.g. MPR output from Point-Stat’) is used without expansion. As a working forecaster I don’t carry MET line-type names in my head; MPR = Matched Pair is MET-internal jargon. The surrounding phrase ‘forecast-observation pairs that are already matched’ carries the meaning so it’s inferable, but the bare acronym is the only unexpanded MET line-type abbreviation on the page. Fix: Expand on first use: ‘e.g. the matched-pair (MPR) line-type output from Point-Stat’ or simply ‘e.g. matched-pair output from Point-Stat’. |
| Nit | accuracy | expert | metplus/use-cases.html | The ‘Start with Example’ tip presents a verbatim quotation — “does not utilize any of the MET tools, but simply demonstrates how the Common Config Variables control a use case run.” — attributed to the docs, but I could not locate this exact string in the current METplus usecases source (the live usecases.rst is a thin toctree; the Example wording lives in generated per-wrapper pages). The substance is correct, but the quoted phrasing is hard to verify against the cited page. Fix: Either confirm the quote against the current generated Example use-case page and cite that page, or soften from a direct quotation to a paraphrase (drop the quotation marks). |
| Nit | accuracy | expert | metplus/use-cases.html | The sample-data tarball naming claim (“named with the X.Y version of the corresponding METplus Coordinated Release and the name of the use case category separated by a dash, e.g. 4.1-data_assimilation or 4.0-met_tool_wrapper”) is presented as a quote from the cited usecases.html, but that prose was not found on the current usecases source page; it appears to originate from a separate sample-data/release page. Claim is plausibly accurate but the citation is imprecise. Fix: Cite the specific page that documents the sample-data tarball naming convention, or mark it as paraphrased if the exact source string has moved between releases. |
| Nit | consistency | expert | metplus/wrappers.html | DataIngest is listed in the catalog table under ‘Reformat & prep’, but the ‘Not every wrapper wraps a MET tool’ callout lumps ‘the database/ingest helpers’ with UserScript/CyclonePlotter/Example as glue/non-MET-tool wrappers. DataIngest is a real wrapper but does not front a MET program; the two groupings read slightly inconsistently to a careful reader. Fix: Make the callout explicit that DataIngest/PyEmbedIngest/METdbLoad are the ‘ingest/database helpers’ it means, so the table placement and the callout agree. |
| Nit | clarity | persona | metplus/wrappers.html | The LEAD_SEQ row (lines 269-272) attaches the ‘hours are assumed when no unit is given’ remark to the ‘values with explicit units (6H, 12H)’ form. Logically the ‘no unit’ caveat belongs to the FIRST form (the plain list 0, 6, 12), since 6H/12H DO carry an explicit unit. The parenthetical reads as slightly self-contradictory next to ‘explicit units’. Fix: Move the unit-default note to the plain-list form: ‘an explicit list of hours (0, 6, 12 — hours assumed when no unit is given), values with explicit units (6H, 12H), or the begin_end_incr(…) shorthand.‘ |
| Nit | consistency | persona | metplus/index.html | index.html lists TCMPRPlotter as a Plotting wrapper (line 283), but the detailed wrapper catalog in wrappers.html omits it (Plotting there is only PlotDataPlane, PlotPointObs, CyclonePlotter). A reader who notices TCMPRPlotter in the overview and clicks through to the wrappers page to learn more won’t find it. Mitigated because both tables are explicitly framed as ‘orientation, not exhaustive,’ and TCMPRPlotter is a real wrapper. Fix: Either add a TCMPRPlotter row to the wrappers.html Plotting group, or drop it from the index overview to keep the two plotting lists aligned. |
| Nit | consistency | persona | metplus/use-cases.html | The sample-data tarball is referred to by two naming conventions: the quoted doc form ‘X.Y-met_tool_wrapper’ (lines 341-344, e.g. 4.0-met_tool_wrapper) and the on-disk prefix ‘sample_data-met_tool_wrapper’ (line 365, ‘the one that starts with sample_data-met_tool_wrapper’). A first-timer downloading data may be unsure exactly what filename to look for. Fix: Reconcile in one place, e.g. note that the published file is ‘sample_data-met_tool_wrapper-X.Y…’ so the X.Y version label and the sample_data- prefix are clearly the same artifact. |
METcalcpy
Section titled “METcalcpy”4 open · expert pass·minor · persona pass·minor
Fresh-review verdicts — Domain expert: pass · minor Persona scientist: pass · minor
Maintenance fixes applied (2026-06-08)
Section titled “Maintenance fixes applied (2026-06-08)”- Removed the unverified word “linearly” from the vertical-interpolation row in
index.html. - Added a source-note hedge flagging that
calc_ctp’s 100/300 hPa offsets, the 950/850 hPa humidity levels, and the Findell/Dirmeyer citations come from source docstrings, not a rendered guide page.
Independent spot-checks
Section titled “Independent spot-checks”| Result | Reviewer | Claim checked | How verified |
|---|---|---|---|
| ✓ confirmed | expert | RECENT FIX HELD: indy_vals are HHMMSS lead encodings, not seconds. Page says ‘030000 = 3 h, 360000 = 36 h — not seconds.‘ | Source config_agg_stat.yaml indy_vals = [‘30000’,‘60000’,…,‘360000’]; 030000 in HHMMSS = 3h00m00s, 360000 = 36h. Encoding and the page’s stated examples match the official aggregation.html. |
| ✓ confirmed | expert | RECENT FIX HELD: a muted source-note hedges calc_ctp/HI layer offsets (100/300 hPa, 950/850 hPa) and the Findell & Eltahir / Dirmeyer citations as docstring-sourced rather than from a rendered guide page. | index.html lines 282-285: ‘Source note: … taken from the functions own docstrings in the METcalcpy source rather than from a rendered User’s Guide page.’ Present and correctly muted. |
| ✓ confirmed | expert | The difficulty-index equation structure A/2 × [ (σ/x̄)/(σ/x̄)_ref + 1 − ½|P≥ − P<| ], the peak A = 1.5 over 28–34 kt, the (σ/x̄)_ref scalar/5-day-regional-max description, and the ‘Figure 6.1 Weighting applied to wind difficulty index’ caption all match the source. | WebFetch of difficulty_index.html: equation, peak A=1.5, scalar 5-day-regional-max reference, and Figure 6.1 caption all reproduced faithfully on the page. |
| ✓ confirmed | expert | RECENT FIX: ‘linearly’ removed from the vertical-interpolation row; current text ‘interpolating fields from pressure to target height levels’ is accurate. | index.html line 191-192 has no ‘linearly’. Note: the source vertical_interpolation.html actually says ‘implemented with linear interpolation’, so the removal merely omits a true detail — current text remains accurate, not a defect. |
| ✓ confirmed | persona | Recent fix held: indy_vals are described as MET HHMMSS lead encodings, not seconds (e.g. 030000 = 3 h, 360000 = 36 h). | aggregation.html line 367: ‘forecast leads in MET’s HHMMSS encoding — e.g. 030000 = 3 h, 360000 = 36 h — not seconds’ |
| ✓ confirmed | persona | Recent fix held: ‘linearly’ removed from the vertical-interpolation capability row in index.html (row now reads ‘interpolating fields from pressure to target height levels’ with no ‘linearly’). Remaining ‘linearly’ usages are correct (difficulty-index A-curve ramp desc; ‘non-linear’ in aggregation pitfall). | grep for ‘linear’: index.html line 189-192 has no ‘linearly’; only difficulty-index.html lines 281-282 and aggregation.html line 86 match, both accurate |
| ✓ confirmed | persona | Recent fix held: a muted source-note hedges the calc_ctp/HI layer offsets (100/300 hPa, 950/850 hPa) and citations as docstring-sourced, not from a rendered guide. | index.html lines 282-285, p.muted: ‘taken from the functions’ own docstrings in the METcalcpy source rather than from a rendered User’s Guide page’ |
| ✓ confirmed | persona | Diagram geometry/math correct: wind-weighting A-curve tick positions (5->126, 28->386, 34->453, 50->634), peak band rect width 67, A-curve path vertices, and straddling-term floor (agree=0.5, even split=1.0) all recompute to match the SVG and prose. | Recomputed: x=70+(kt/55)620 gives 126.4/385.6/453.3/633.6 (SVG uses 126/386/453/634); 1-0.5|1-0|=0.5 and 1-0.5*|0.5-0.5|=1.0 match difficulty-index.html lines 244-247 |
| ✓ confirmed | persona | Design contract held across all three pages: shared ../assets/doculizer.css + ../assets/theme-toggle.js, FOUC inline script first in head, SVGs use CSS vars (var(—accent) etc.) with no hard-coded hex, no <style> blocks, footer cites real source + ‘derived guide’ note. | grep confirmed assets/FOUC/footer/skip-link present in all three; grep for hex/<style> in aggregation.html and difficulty-index.html returned no matches (exit 1) |
Remaining — documented (minor / nit)
Section titled “Remaining — documented (minor / nit)”| Severity | Category | Reviewer | Page | Issue & suggested fix |
|---|---|---|---|---|
| Minor | accuracy | expert | metcalcpy/difficulty-index.html | The wind-speed weighting-factor table gives the 34<x̄≤50 ramp-down as A = 1.5·[1 − (x̄ − 34)/16], but the METcalcpy User’s Guide prints it literally as A = 1.5·[1 − 1.5·((x̄ − 34)/16)] (an extra inner 1.5 factor). The page’s form is the mathematically correct, continuous one (it reaches exactly 0 at 50 kt, whereas the source’s literal formula yields A = −0.75 at 50 kt — a likely typo in the official guide). But the table caption asserts the values are ‘as given in the METcalcpy User’s Guide,’ so the page is silently correcting the source without flagging it. A reader cross-checking against the guide will see a mismatch and not know which to trust. Fix: Keep the corrected continuous formula (it is right) but add a brief muted note that the source text prints an extra 1.5 inside the bracket which makes A go negative at 50 kt, so the page uses the continuous ramp-to-zero form. This matches the page’s existing convention of hedging source-vs-implementation discrepancies (as done for (σ/x̄)_ref and the bracketing). |
| Minor | clarity | persona | metcalcpy/index.html | In the Capability areas table, the vertical-interpolation row says ‘Pressure-to-height conversion for TC-RMW data via vertical_interp.py’. TC-RMW (Tropical Cyclone Radius of Maximum Wind) appears exactly once and is never expanded anywhere on the page. As a forecaster reader this is the one acronym in the table that is not unpacked on first use, breaking the gloss-on-first-use contract. Fix: Expand on first use, e.g. ‘tropical-cyclone radius-of-maximum-wind (TC-RMW) data’ or add a brief parenthetical. |
| Nit | accuracy | expert | metcalcpy/difficulty-index.html | The up-ramp band condition is written 5 ≤ x̄ < 28, but the source states the ramp applies for 5 < x̄ < 28 and separately assigns A = 0 for x̄ ≤ 5 (5 inclusive in the zero region). The boundary at exactly 5 kt is handled by a different branch than the source assigns it to. Numerically harmless (both branches give A = 0 at x̄ = 5), but the inclusivity does not match the guide. Fix: Change the table row condition to 5 < x̄ < 28 and the zero-region row to x̄ ≤ 5 or x̄ ≥ 50 to mirror the source’s exact inequalities. |
| Nit | diagram | persona | metcalcpy/difficulty-index.html | In Figure 1, the ‘All below’ and ‘All above’ clusters draw 5 ensemble dots each while the ‘Straddling’ cluster draws 6 dots (so it can show a clean 3-above/3-below split). A reader comparing the cases for an ‘even split’ may briefly notice the member count differs between panels. Not misleading, since the spread band is identical (42px each) and the split is the intended message. Fix: Optionally use 6 dots in all three panels (or note the member counts are illustrative) so the only visible difference between cases is position relative to the threshold, not count. |
METplotpy
Section titled “METplotpy”6 open · expert pass·minor · persona pass·minor
Fresh-review verdicts — Domain expert: pass · minor Persona scientist: pass · minor
No source edits this maintenance pass; the fresh review re-confirmed the earlier corrections still hold.
Independent spot-checks
Section titled “Independent spot-checks”| Result | Reviewer | Claim checked | How verified |
|---|---|---|---|
| ✓ confirmed | expert | Taylor std-dev arcs are concentric quarter-circles about origin (60,330): arcs M 330,330 A270, M 240,330 A180, M 150,330 A90 each have all endpoints at the stated radius from (60,330); reference point (240,330) lies on the r=180 arc (dx=180, dy=0). | Recomputed from the SVG path data in diagnostic-diagrams.html lines 351-353, 369; all endpoint distances match radii exactly. |
| ✓ confirmed | expert | Performance-diagram CSI iso-lines follow 1/CSI = 1/SR + 1/POD − 1 with x=70+320·SR, y=350−320·POD. Verified at CSI=0.4 right-edge point (390,222): SR=1 → POD=0.4 → y=222; CSI=0.6 (390,158) → POD=0.6 → y=158; CSI=0.2 (230,270) → SR=0.5, POD=0.25 → y=270. | Recomputed against polyline points in diagnostic-diagrams.html lines 121-130; all sampled points satisfy the CSI relation. |
| ✓ confirmed | expert | Wind-rose color bands stack low-to-high speed OUTWARD: legend maps accent=0-2 (low), accent-2=2-4, warn=4-6 (high); W petal warn band uses outermost radius (~150), accent-2 mid (~102), accent innermost (~58), so the strongest-wind band is at the outer tip — matching the caption. | Read wedges (specialty-plots.html lines 415-417) + legend (lines 441-447); radii and color-to-bin mapping consistent with caption. |
| ✓ confirmed | expert | Source-supported line-type/config claims hold: Taylor reads CNT (FSTDEV/OSTDEV/PR_CORR) with taylor_voc and taylor_show_gamma; reliability reads PCT (PSTD_CALIBRATION/PSTD_BASER/PSTD_NI) with add_noskill/reference/skill_line; ROC reads CTC or PCT with roc_pct/roc_ctc and METdataio/METreformat note; wind rose reads MPR line type with dump_points→.points1; performance reads CTS (PODY/FAR). | WebFetch of metplotpy User’s Guide pages: taylor_diagram.html, reliability_diagram.html, roc_diagram.html, wind_rose.html, performance_diagram.html — all quote matching text. |
| ✓ confirmed | persona | RECENT FIX HELD — Taylor std-dev arcs are concentric quarter-circles about the origin (60,330), and the reference point (240,330) lies on the r=180 arc. Recomputed: arc radii are exactly 270, 180, 90 from (60,330) for all three paths (start and end points both match); reference (240,330) is at distance 180 = the middle arc. Also verified internal consistency via law of cosines: dashed model→reference segment (86.4 px) equals the centered-RMSE implied by the model radius (192) and angle (26.6°, corr≈0.894). | Recomputed coords in diagnostic-diagrams.html Taylor SVG (lines 351-375) |
| ✓ confirmed | persona | RECENT FIX HELD — Performance-diagram CSI iso-lines follow 1/CSI = 1/SR + 1/POD − 1. Each labeled curve’s right-edge endpoint (SR=1.0) yields exactly its label: (390,286)→0.20, (390,222)→0.40, (390,158)→0.60, (390,94)→0.80; an interior CSI=0.4 sample point (262,175) recomputes to 0.401. | Recomputed polyline endpoints in performance SVG, diagnostic-diagrams.html lines 121-131 |
| ✓ confirmed | persona | RECENT FIX HELD — Wind-rose color bands stack low-to-high speed OUTWARD, matching the caption and legend. Measured wedge tip radii from center (240,220): accent (0–2 m/s) innermost at r≈58, accent-2 (2–4) at r≈101, warn (4–6) outermost at r≈148. Legend maps accent=0–2, accent-2=2–4, warn=4–6. | Recomputed wedge radii in wind-rose SVG, specialty-plots.html lines 415-447 |
| ✓ confirmed | persona | VERIFIED FACT HELD — ROC reads PCT or CTC (POD vs POFD per threshold), not a PSTD claim; and design contract holds: no <style> blocks, no hard-coded hex in any SVG (all theme vars), FOUC script first in <head>, shared ../assets css+js, derived-guide footer note on all three pages. All cross-page links (../metdataio/reformat.html, ../met/index.html, sibling index pages) resolve to existing files. | grep over metplotpy/*.html and ls of sibling dirs (met, metcalcpy, metplus, metviewer, metdataio) |
Remaining — documented (minor / nit)
Section titled “Remaining — documented (minor / nit)”| Severity | Category | Reviewer | Page | Issue & suggested fix |
|---|---|---|---|---|
| Minor | accuracy | persona | metplotpy/diagnostic-diagrams.html | The reliability “What feeds it” prose (and the cross-reference table) attributes the columns PSTD_CALIBRATION, PSTD_BASER, PSTD_NI to the PCT line type: “Reliability is built from MET’s probability contingency table — the PCT line type … references statistics such as PSTD_CALIBRATION, PSTD_BASER, PSTD_NI.” Those are PSTD line-type columns, not PCT columns. The METplotpy reliability source page’s default config actually lists those PSTD_* columns (list_stat_1), and the project’s own verified-fact note treats PSTD as a distinct line type (e.g. ROC_AUC lives in PSTD, not PCT). A meteorologist looking up where CALIBRATION/BASER live in a .stat file would be pointed at the wrong line type. Fix: Say the reliability plotter consumes PSTD-derived probabilistic statistics (the PCT-family output), and that the named columns PSTD_CALIBRATION / PSTD_BASER / PSTD_NI are PSTD line-type columns. Update both the prose at the reliability “What feeds it” paragraph and the “What feeds each diagram” table row (change the Reliability MET line type cell from PCT to PSTD, or to ‘PCT input → PSTD columns’). |
| Nit | accuracy | expert | metplotpy/index.html | The claim “Most plots are built with plotly; the performance diagram is built with matplotlib” is substantively correct (the performance diagram page exposes matplotlib-specific title-alignment config, corroborating a matplotlib implementation), but the footer cites only the Overview, Installation, and Line Plot pages as sources, none of which state this plotly-vs-matplotlib split. The distinction is asserted as fact without a directly-cited source. Fix: Either soften to a hedge (e.g. “the performance diagram is matplotlib-based”) or add the performance-diagram page to the cited sources, since its matplotlib-only options are the on-page evidence for the claim. |
| Nit | accuracy | expert | metplotpy/diagnostic-diagrams.html | The reliability section defines Resolution as “how much the curve rises across the plot — how far the observed frequency spreads from low to high as the forecast probability climbs.” That is a reasonable lay paraphrase, but resolution in the strict verification sense is the weighted variance of the conditional event frequencies about the climatological base rate, not literally the vertical rise of the reliability curve. Fix: Add a brief qualifier such as “(more precisely, the spread of conditional event frequencies about the base rate)” so the intuitive description is not mistaken for the formal definition. |
| Nit | accessibility | expert | metplotpy/diagnostic-diagrams.html | The reliability-diagram SVG <desc> alt text calls the sample curve “S-shaped,” but the drawn path (M 86,318 C 150,250 200,235 230,210 C 270,178 320,140 374,118) is monotonic and concave, not sigmoidal — it crosses the diagonal once (above at low prob, below at high), with no inflection back. The visible caption avoids this wording; only the alt text overstates it. Fix: Change “S-shaped” in the <desc> to “a sample forecast curve that crosses the diagonal once,” matching the actual geometry and the figcaption. |
| Nit | clarity | persona | metplotpy/index.html | In the MJO callout, OLR is introduced as an acronym only inside another gloss — “OMI (the OLR-based MJO index)” — and is never itself expanded. The page’s stated contract is to gloss jargon on first use; OLR (Outgoing Longwave Radiation) is the one acronym used here purely as a gloss-helper yet left unglossed. Fix: Expand on first use: “OMI (the OLR-based — Outgoing Longwave Radiation — MJO index)”, or add a brief parenthetical the first time OLR appears. |
| Nit | clarity | persona | metplotpy/specialty-plots.html | NetCDF is used without expansion at the Hovmöller “What goes in” paragraph (“The input is a NetCDF file …”). It is near-universal jargon for the target reader, but the page elsewhere is scrupulous about glossing acronyms (MPR, CIRA, S2S, TCMPR), so this is a small inconsistency against its own gloss-on-first-use contract. Fix: Optionally add a one-clause gloss on first use, e.g. “a NetCDF file (the standard self-describing gridded-data format)”. Low priority given how common the term is. |
METdataio
Section titled “METdataio”6 open · expert pass·minor · persona pass·minor
Fresh-review verdicts — Domain expert: pass · minor Persona scientist: pass · minor
Maintenance fixes applied (2026-06-08)
Section titled “Maintenance fixes applied (2026-06-08)”- Relabeled METreformat’s output from “tidy dataframes” to “tidy, long-format tables” and clarified that METreformat writes a text file while only METreadnc yields a pandas/xarray dataframe.
- Removed the unsourced “WriteStatAscii workflow” label.
- Repointed
metdbload.html’s METviewer / METexpress links from external readthedocs to the internal doculizer pages.
Independent spot-checks
Section titled “Independent spot-checks”| Result | Reviewer | Claim checked | How verified |
|---|---|---|---|
| ✓ confirmed | expert | Recent fix held: METreformat output is labeled “tidy, long-format tables” and described as a TEXT FILE, with only METreadnc yielding pandas/xarray; no “WriteStatAscii workflow” label. | index.html lines 80-84 (‘long, human-readable text file’; METreadnc reads netCDF into pandas/xarray) and reformat.html line 416-417 (‘A text file is created in the output directory’). Script referenced as write_stat_ascii.py (module/script), never as a ‘WriteStatAscii workflow’ label. |
| ✓ confirmed | expert | Recent fix held: metdbload.html links METviewer and METexpress internally to ../metviewer/index.html and ../metexpress/index.html, not external readthedocs. | metdbload.html lines 43-44, 248-249, 516, 248; all METviewer/METexpress hrefs are internal ../metviewer/index.html and ../metexpress/index.html. Only external links are to met.readthedocs.io for MET itself, which has no internal page. |
| ✓ confirmed | expert | PCT oy_i/on_i mean observation=YES/NO events whose forecast probability falls between the ith and i+1th threshold; METreadnc exposes ReadNetCDF with read_into_xarray (list of xarray Datasets) and read_into_pandas (pandas DataFrame), deps xarray/netcdf4/pandas/pyyaml. | MET Point-Stat Table 11.8 via WebFetch (OY_i=‘Sum of weights for observation yes when forecast is between the ith and i+1th probability thresholds’); METdataio read_nc.html via WebFetch confirms ReadNetCDF, both methods, infile as string-or-list, and the four dependencies aligned with METcalcpy requirements. |
| ✓ confirmed | expert | Tool attributions in the supported-line-types table are source-correct: ECNT from Point-Stat(HiRA)+Ensemble-Stat, RHIST from Ensemble-Stat only (not Point-Stat), DMAP from Grid-Stat only, VCNT/PCT from Point-Stat+Grid-Stat. | MET Point-Stat output line-type table via WebFetch: Point-Stat produces FHO/CTC/CTS/CNT/MCTS/SL1L2/VL1L2/VCNT/PCT/MPR and ECNT (HiRA only); RHIST and DMAP NOT in Point-Stat output, consistent with reformat.html attributions. |
| ✓ confirmed | persona | RECENT FIX held: METreformat output is labeled tidy/long-format and described as a TEXT FILE, with only METreadnc yielding a pandas/xarray dataframe. | index.html lines 80-84 (METreformat -> ‘long, human-readable text file’; METreadnc -> ‘pandas or xarray dataframe’) and capabilities table line 206 (‘A reformatted text file readable by METplotpy / METcalcpy’) vs lines 209-212 (METreadnc -> xarray Datasets / pandas DataFrame) |
| ✓ confirmed | persona | RECENT FIX held: no ‘WriteStatAscii workflow’ label; metdbload.html links METviewer and METexpress to internal ../metviewer/index.html and ../metexpress/index.html, not external readthedocs. | grep of all three files shows only the script name ‘write_stat_ascii.py’ (index.html L294, reformat.html L145/L415), no ‘WriteStatAscii workflow’; metdbload.html L43-44, L245, L248-249, L515-516 all use ../metviewer/index.html and ../metexpress/index.html |
| ✓ confirmed | persona | VERIFIED FACT held: PCT line type reformats to the ROC diagram and OY_i/ON_i are counts of obs=YES/NO whose forecast probability falls between the ith and i+1th threshold (ROC, not a band-significance encoding). | reformat.html lines 287-301: ‘By threshold values (PCT -> ROC diagram)’ with thresh_i/oy_i/on_i defined as inter-threshold YES/NO counts — correct PCT semantics feeding the ROC plot |
| ✓ confirmed | persona | Design contract held: shared ../assets/doculizer.css + ../assets/theme-toggle.js, FOUC inline <script> first in <head>, SVGs theme-reactive via CSS vars with no hard-coded hex, no <style> blocks, footer cites real sources + derived-guide note. | All three files: inline FOUC script at lines 8-10 before the stylesheet link; grep for hex fill/stroke in SVGs returns nothing; grep for ‘<style’ returns nothing; footers cite the metdataio readthedocs Overview/load_data/reformat_stat/read_nc pages with ‘derived guide, not official documentation’ |
Remaining — documented (minor / nit)
Section titled “Remaining — documented (minor / nit)”| Severity | Category | Reviewer | Page | Issue & suggested fix |
|---|---|---|---|---|
| Minor | clarity | persona | metdataio/metdbload.html | SEEPS is used twice (the ‘SEEPS_MPR’ line-type row and the gloss ‘SEEPS per-pair output’ at line 146, plus in the prose example list at line 129) but the acronym is never expanded. A working forecaster who knows RMSE and ME may well not recognize SEEPS (Stable Equitable Error in Probability Space); it lands as opaque jargon on first and only use. Fix: Spell it out on first mention, e.g. ‘SEEPS (Stable Equitable Error in Probability Space) per-pair output’, or add a one-line gloss in the table caption. |
| Nit | accuracy | expert | metdataio/reformat.html | The PCT threshold-value table defines oy_i/on_i as “Count of observation=YES/NO events whose forecast probability falls between the ith and i+1th threshold.” MET’s authoritative definition (Point-Stat Table 11.8) is “Sum of weights for observation yes/no when forecast is between the ith and i+1th probability thresholds.” For unweighted verification these coincide, but with observation weighting OY_i/ON_i are weighted sums, not raw counts. Fix: Soften to “(weighted) count” or “sum of weights for observation=YES events …” to match the MET definition exactly. |
| Nit | accuracy | expert | metdataio/index.html | The capabilities table row for METreformat lists Reads as “.stat / .tcst (Point-Stat, Grid-Stat, Ensemble-Stat, TC-Pairs).” This conflates the two extensions with all four tools, whereas .tcst is produced only by TC-Pairs and .stat by the other three. The grouping reads as if all four tools emit both extensions. Fix: Clarify, e.g. “.stat (Point-Stat, Grid-Stat, Ensemble-Stat) / .tcst (TC-Pairs)”. |
| Nit | accuracy | expert | metdataio/reformat.html | In the supported-line-types table, ECNT is attributed “From MET tools: Point-Stat, Ensemble-Stat.” Point-Stat only emits ECNT under the HiRA methodology (per MET Point-Stat docs: “ECNT … is only computed for the HiRA methodology”). The bare “Point-Stat” attribution is technically correct but could mislead a reader into thinking standard Point-Stat runs emit ECNT. Fix: Optionally annotate “Point-Stat (HiRA), Ensemble-Stat” to flag that Point-Stat produces ECNT only via HiRA. |
| Nit | clarity | persona | metdataio/index.html | The loader is described as run ‘from the METdbLoad ush directory’ (index.html line 242, and again in metdbload.html line 468 ‘the loader’s ush/ directory’). ‘ush’ is METplus-internal jargon (user shell scripts) and is never glossed; a forecaster reader sees an unexplained directory name with no hint of what it contains or why it is named that. Fix: On first mention add a brief parenthetical, e.g. ‘the ush/ directory (the user-script directory that holds met_db_load.py)’. |
| Nit | consistency | persona | metdataio/reformat.html | The supported-line-types table (lines 234-247) and the index.html pills both list the order …PCT, RHIST…, but the line_type config dd list (line 384) inverts them to …RHIST, PCT… All 14 types are present in every list, so nothing is missing; it is purely an ordering discrepancy within the same page that a careful reader cross-referencing the two lists may notice. Fix: Make the line_type config dd list follow the same PCT-then-RHIST order as the supported-line-types table for intra-page consistency. |
METviewer
Section titled “METviewer”6 open · expert pass·minor · persona pass·minor
Fresh-review verdicts — Domain expert: pass · minor Persona scientist: pass · minor
Maintenance fixes applied (2026-06-08)
Section titled “Maintenance fixes applied (2026-06-08)”- Corrected the scorecard significance bands to 0.95, 0.99, and 0.999 (the 99.9% level) — a prior pass had mistakenly rendered the strongest band as “1.0”.
- Fixed the performance-diagram bias = 2 dashed line geometry so it is the steepest bias line (reaching the top edge at success ratio 0.5), in both
index.htmlandplots.html. - Added the R-deprecation note (Python + METplotpy) to
plots.html, matchingindex.htmlanddatabase.html.
Independent spot-checks
Section titled “Independent spot-checks”| Result | Reviewer | Claim checked | How verified |
|---|---|---|---|
| ✓ confirmed | expert | Performance-diagram bias=2 dashed line is the steepest, with endpoint (345,30) reaching the top edge at success-ratio 0.5 (recomputed: POD=biasSR; POD=1 at SR=0.5 -> x=90+0.5510=345, y=30). bias=1 ends at (600,30), bias=0.5 at (600,135). Geometry is correct and source-faithful. | Recomputed from SVG coords in index.html lines 333-338 and plots.html lines 445-450; plot box x:90..600 (SR 0..1), y:240..30 (POD 0..1). |
| ✓ confirmed | expert | ROC_AUC is attributed to the PSTD line type (not PCT) in plots.html (‘when ROC_AUC is present in the PSTD line type’), and METviewer plots but does not compute it. | https://metplus.readthedocs.io/projects/metviewer/en/latest/Users_Guide/rocplot.html — ‘MET can also write out the PSTD line type which includes the ROC_AUC column’. |
| ✓ confirmed | expert | Scorecard significance bands read 0.95 / 0.99 / 0.999 (the ‘1’ in the source threshold file is the range upper_limit, not a band); scorecard is XML-only with EMC/NCAR algorithm choice; supported line types CTC, SL1L2, SAL1L2, VL1L2, VAL1L2, PCT, GRAD, NBRCNT, ECNT, NBRCTC, RPS match the source exactly. | https://metplus.readthedocs.io/projects/metviewer/en/latest/Users_Guide/scorecard.html — bands ‘0.95, 0.99, and 1’, XML-only ‘no GUI interface’, EMC/NCAR via <stat_flag>, line-type list verbatim. |
| ✓ confirmed | expert | plots.html notes the R rendering path is deprecated in favor of Python (3.12) and METplotpy (present in the architecture note on index.html and the ecosystem callout + plot_spec R-element note on plots.html/database.html); and Taylor (CNT; DLWRF; 7 stations; Bondville ~0.85 corr, ~1.0 std dev) and Spread/Skill (SSVAR_RMSE & SSVAR_Spread; SSVAR; 2m temp; HRRR; EAST; 36 leads) examples match the source. | taylordiag.html and spreadskillplot.html (WebFetch) confirm the example details verbatim; deprecation note appears in index.html lines 188-191 and plots.html lines 662-664. |
| ✓ confirmed | persona | Performance-diagram bias=2 dashed line is the steepest, ending at (345,30): success-ratio 0.5, POD 1.0, reaching the top edge. Recomputed bias=POD/SR for all three endpoints. | plots.html lines 444-450 and index.html 333-338; recomputed: (600,135)->bias 0.5, (600,30)->bias 1.0, (345,30)->SR 0.5/POD 1.0/bias 2.0, screen-slope magnitude 0.824 = steepest |
| ✓ confirmed | persona | ROC_AUC is attributed to the PSTD line type (not PCT). | plots.html line 403: “when ROC_AUC is present in the PSTD line type” |
| ✓ confirmed | persona | Scorecard significance bands read 0.95 / 0.99 / 0.999 (strongest = 99.9%), not 1.0/100%. | plots.html line 615 figcaption and line 624 prose: “0.95, 0.99, and 0.999 (the 99.9% level)” |
| ✓ confirmed | persona | plots.html states the R rendering path is deprecated in favor of Python (3.12) + METplotpy. | plots.html lines 662-664 ecosystem callout; corroborated by index.html architecture callout lines 188-191 and database.html plot-spec note lines 338-342 |
Remaining — documented (minor / nit)
Section titled “Remaining — documented (minor / nit)”| Severity | Category | Reviewer | Page | Issue & suggested fix |
|---|---|---|---|---|
| Minor | accuracy | expert | metviewer/index.html | The plot-families table caption asserts a precise span — “chapters 9–20” — for the plot families in the METviewer User’s Guide. The readthedocs landing/index page does not expose a numbered TOC in rendered form, and chapter numbering is exactly the kind of detail that drifts between METviewer releases. The page is otherwise careful to hedge version-dependent specifics (e.g. the “Read this against the source” callout), so this hard-coded numeric range stands out as an unhedged, hard-to-verify claim. Fix: Soften to “documented across the plot chapters of the METviewer User’s Guide” (drop the explicit 9–20), or add a “numbering may vary by release” caveat consistent with the rest of the page. |
| Minor | accuracy | persona | metviewer/plots.html | In the box-and-whisker prose (line 287), outliers are defined as points “more than 1.5× the IQR from the median.” The standard Tukey convention measures the outlier fence as 1.5×IQR beyond the quartiles (Q1/Q3), not from the median. As written it would place the fence symmetrically about the median, which is non-standard and inconsistent with the whiskers, which line 285 anchors to the box edges (“1.5× the box height”). Fix: Change “outliers more than 1.5× the IQR from the median” to “outliers more than 1.5× the IQR beyond the quartiles (the box edges)” so the outlier fence and the whisker definition share the same anchor. |
| Nit | consistency | expert | metviewer/plots.html | Workflow step 9 instructs the reader to “sanity-check the underlying numbers in the ‘R data’ tab,” using the legacy R-centric tab name, while the very next ecosystem callout (and index.html) correctly notes the R rendering path is deprecated in favor of Python/METplotpy. index.html’s analogous step says generically “the data” tab. Minor terminology friction against the page’s own deprecation note. Fix: Refer to it as “the data tab” (optionally “the data tab — historically labeled ‘R data’”) to match the deprecation framing used elsewhere on the page. |
| Nit | diagram | expert | metviewer/plots.html | In the reliability-diagram SVG the inline source comment says the sample curve “starts above diagonal at low p, dips below at high p,” but the path as drawn (M60,290 … 320,108) sits ON the diagonal at low p (60,290) and below it for higher p — i.e. consistent over-forecasting, never above. The user-visible caption and bullets are correct; only the internal comment misdescribes the geometry. Fix: Update the SVG comment to match what renders (curve sits on/below the diagonal throughout, marking over-forecasting), or nudge the early control points slightly above the diagonal if an above-then-below S-shape was intended. |
| Nit | clarity | persona | metviewer/plots.html | ”whiskers reach to 1.5× the box height” (lines 280, 285, and SVG desc line 230) omits the anchor point. A reader cannot tell whether the 1.5× distance is measured from the box edges or from the center; without “beyond the quartiles” the phrase is ambiguous even though box height does equal the IQR. Fix: Phrase as “whiskers extend up to 1.5× the box height (IQR) beyond the quartiles” to make the measurement origin explicit. |
| Nit | clarity | persona | metviewer/plots.html | CSI appears unexpanded in the cheat-sheet body (line 138, “Performance (CSI)”) and section heading (line 57 nav, line 412 “Performance (CSI) diagrams”) before it is first spelled out as “Critical Success Index” at line 420. A forecaster scanning top-to-bottom meets the bare acronym in the cheat-sheet first. (index.html glosses it correctly on first use at line 266.) Fix: Add the expansion at first body use, e.g. in the cheat-sheet row label “Performance (Critical Success Index, CSI)” or a one-line note under the cheat-sheet, mirroring the POD/POFD/FAR gloss already provided at lines 103–105. |
METexpress
Section titled “METexpress”6 open · expert pass·minor · persona pass·minor
Fresh-review verdicts — Domain expert: pass · minor Persona scientist: pass · minor
Maintenance fixes applied (2026-06-08)
Section titled “Maintenance fixes applied (2026-06-08)”- Glossed QPF (quantitative precipitation forecast) and MSLP (mean sea-level pressure) on first use.
- Softened the “Plot types, by axis” intro so it no longer claims the source documents the per-plot axes.
- Added a source-note hedge to the metadata-admin section — the
MEmetadata_update.py/mats_metadata/mv_load.shspecifics, since confirmed verbatim against the live Metadata page. - Pointed the scorecard note to the sibling METviewer, which does produce scorecards.
Independent spot-checks
Section titled “Independent spot-checks”| Result | Reviewer | Claim checked | How verified |
|---|---|---|---|
| ✓ confirmed | expert | METexpress comprises exactly EIGHT apps with the names and scopes listed (Upper Air, Anomaly Correlation, Surface, Air Quality, Ensemble, Precipitation, Cyclone, Objects), and each app’s plot-type roster matches the source. | WebFetch of metplus.readthedocs.io/projects/metexpress/en/latest/Users_Guide/apps.html — 8 apps, scopes and plot-type lists match index.html/apps.html/interface.html tables exactly (e.g. Ensemble: Time Series, Dieoff, ValidTime, Histogram, Ensemble Histogram, Reliability, ROC, Performance Diagram). |
| ✓ confirmed | expert | Plot caching duration is about 8 hours, and Re-sample uses the Largest Triangle Three Buckets algorithm; plots are rendered with Plotly. | WebFetch of interface.html source: “METexpress will cache requested plots for eight hours”; “Largest Triangle Three Buckets algorithm”; “METexpress plots are produced with the graphing package Plotly.” interface.html lines 376/388 match. |
| ✓ confirmed | expert | RECENT FIX HELD: the “Plot types, by axis” intro no longer claims the source documents the axis assignments; it explicitly hedges that the x/y assignments follow standard verification convention. | apps.html lines 396-398: “(METexpress’s documentation names the plot types; the x/y assignments here follow standard verification convention — e.g. a profile puts the value on x and pressure on y.)” |
| ✓ confirmed | expert | RECENT FIX HELD: the metadata-admin specifics (MEmetadata_update.py, mats_metadata schema, mv_load.sh hook) are present AND hedged by a muted source-note flagging they come from the separate Metadata page, not the cited interface/apps pages. | interface.html lines 411-422: steps name MEmetadata_update.py, mats_metadata, mv_load.sh, followed by muted “Source note” para advising readers to confirm exact script names against their installed version. |
| ✓ confirmed | expert | RECENT FIX HELD: QPF and MSLP are glossed on first use, and the scorecard note steers readers to METviewer for actual scorecards. | index.html line 228 “QPF (quantitative precipitation forecast)”; apps.html line 295 “MSLP (mean sea-level pressure)”; index.html lines 327-330 and interface.html #scorecard both state METexpress docs do not document a scorecard plot type and point to METviewer. |
| ✓ confirmed | persona | QPF is glossed on first use in index.html (“QPF (quantitative precipitation forecast) thresholds”), and MSLP is glossed on first use in apps.html (“MSLP (mean sea-level pressure) error”) before its un-glossed reuse in the table. | index.html line 228 (QPF gloss, first/only QPF occurrence); apps.html line 295 glosses MSLP, line 379 reuses it later in reading order |
| ✓ confirmed | persona | The apps.html “Plot types, by axis” intro no longer claims the source documents the axes; it explicitly hedges that x/y assignments follow standard verification convention, not the source. | apps.html lines 394-398: “METexpress’s documentation names the plot types; the x/y assignments here follow standard verification convention” |
| ✓ confirmed | persona | The metadata-admin specifics (MEmetadata_update.py, mats_metadata schema, mv_load.sh) are hedged by a muted source note, and the scorecard note correctly points readers to METviewer for actual scorecards. | interface.html lines 418-422 (muted source note hedging script names against installed version); index.html lines 327-330 point to sibling METviewer; interface.html scorecard callout (440-446) frames the diagram as conceptual only |
| ✓ confirmed | persona | Design contract holds: no <style> blocks, no hard-coded hex in SVGs (all fills use var()/color-mix), shared ../assets/doculizer.css + theme-toggle.js, FOUC script first in <head>; and the scorecard diagram geometry renders correctly (significance triangles sit within their cells and match better/worse coloring). | grep: 0 <style> blocks, 0 non-href hex matches across all 3 files; FOUC <script> at line 8 precedes stylesheet at line 11. Recomputed interface.html Fig 2: cell centers (290,370,450,530,610 / 92,132,172,212,252) align with column/row labels; marker M290,84 l6,10 l-12,0 = apex-up (better) on accent-2 cell, M610,100 l-6,-10 = apex-down (worse) on warn cell |
Remaining — documented (minor / nit)
Section titled “Remaining — documented (minor / nit)”| Severity | Category | Reviewer | Page | Issue & suggested fix |
|---|---|---|---|---|
| Minor | consistency | expert | metexpress/interface.html | The Aggregation Method option is named “Mean weighted by N” in the Universal-fields table (line 156), but the source documents it as “Mean statistic weighted by N” and index.html (line 270) correctly uses the full “Mean statistic weighted by N”. This is a within-suite inconsistency where interface.html drops the word “statistic”. Fix: Change “Mean weighted by N” to “Mean statistic weighted by N” in the interface.html Aggregation Method row to match both the source and index.html. |
| Minor | consistency | persona | metexpress/index.html | The Aggregation Method option is labeled “Mean statistic weighted by N” in index.html (line 270) but “Mean weighted by N” in interface.html (line 156). A forecaster cross-referencing the overview against the interface deep-dive sees two slightly different names for the same menu choice. Fix: Pick one wording for the Aggregation Method option and use it on both pages (e.g. “Mean statistic weighted by N” everywhere). |
| Nit | accuracy | expert | metexpress/apps.html | The Air Quality app card (line 251-255) lists a “Threshold” plot-type chip, but the official Apps page lists Air Quality’s plot types as Time Series, Dieoff, Threshold, ValidTime, Histogram, Contour — so Threshold IS correct there. However the Upper Air card (lines 208-212) and the source agree on six types with no Threshold; this is consistent. No defect in the chips themselves; flagging only that the Air Quality narrative paragraph (“such as pollutant concentrations”) is an unsourced example gloss rather than verbatim source text. Low impact, clearly framed as illustrative. Fix: Optional: keep as-is, or add “e.g.” framing is already implied; no change strictly required. |
| Nit | clarity | expert | metexpress/index.html | The Objects app row (line 217-219) describes “Skill scores and model–obs pair verification statistics for convective objects” which matches the source verbatim, but the term “convective objects” narrows the source’s general “objects” framing. The source scope says “convective objects,” so this is faithful; the nit is only that a first-time reader may not know object-based verification (MODE) underlies this — no gloss of “object-based verification” appears. Fix: Optionally add a one-clause gloss that “objects” refers to object-based (MODE-style) verification where contiguous features are matched between forecast and observation. |
| Nit | accuracy | persona | metexpress/index.html | Index line 274 states “Curve0 defaults to red” as a concrete fact, whereas interface.html (line 117) more carefully says each curve is “automatically given a label and a default color; both can be changed” without naming a specific color. The specific-red claim is unsourced and could mislead a reader if the default palette differs by app/version. Fix: Soften to “Curve0 gets an auto-assigned default color” to match the interface page, or keep the color only if it is verified across apps. |
| Nit | consistency | persona | metexpress/apps.html | Within the same statistic lists, most acronyms are wrapped in <code> (RMSE, CSI, FAR, etc.) but “ROC AUC” appears as plain text (glossary line 110, Ensemble card line 264, table line 367). The inconsistent typographic treatment of one statistic name reads as an oversight to a careful reader. Fix: Wrap “ROC AUC” (or “ROC_AUC”/“ROC”) in <code> consistently with the neighboring statistic acronyms, or leave all of them unstyled — just be consistent within a list. |
A derived, human-readable re-presentation — not official documentation. Sources: metplus.readthedocs.io