Skip to content

Expose per-peak metrics errors via CLI (CSV/histograms) - #9

Draft
PrinceWalnut wants to merge 7 commits into
neutrons:mainfrom
PrinceWalnut:metrics_improvements
Draft

Expose per-peak metrics errors via CLI (CSV/histograms)#9
PrinceWalnut wants to merge 7 commits into
neutrons:mainfrom
PrinceWalnut:metrics_improvements

Conversation

@PrinceWalnut

Copy link
Copy Markdown

Summary

  • compute_metrics gains a return_per_peak option that attaches the raw per-peak run_index/h/k/l/d_err/ang_err arrays to its result, instead of only aggregated median/mean/max stats.
  • Adds write_per_peak_csv and a new subhkl.viz.metrics_plots module (plot_error_histograms, plot_per_run_histograms) so those distributions can be written to CSV or plotted as histograms (optionally faceted per run/frame via --per-run).
  • Wires this up on the subhkl metrics CLI command as --csv/--csv-path and --plot/--plot-path. The bare flags default to metrics.csv/metrics.png; the -path variants override the filename. (A single --csv <path> option was tried first but doesn't reliably support "flag with no value" against the typer/click versions pinned in uv.lock, hence the split.)

Test plan

  • subhkl metrics indexer.h5 --csv --plot writes metrics.csv/metrics.png
  • subhkl metrics indexer.h5 --csv-path errors.csv --plot-path errors.png writes the custom-named files
  • subhkl metrics indexer.h5 --per-run --plot additionally writes metrics_per_run.png with one histogram row per frame
  • Existing subhkl metrics invocations without these flags behave unchanged

🤖 Generated with Claude Code

https://claude.ai/code/session_01UsgjQGXqZVZBYqxoXvPTwk

PrinceWalnut and others added 6 commits July 21, 2026 13:43
Adds return_per_peak option to compute_metrics plus a CSV writer and
histogram plotting helpers, so the raw error distributions can be
inspected instead of only the aggregated median/mean/max stats. Wired
up as --csv and --plot options on the `subhkl metrics` CLI command.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UsgjQGXqZVZBYqxoXvPTwk
Splits each into a bool flag plus a --csv-path/--plot-path override.
Click's is_flag=False/flag_value optional-argument trick was tested
against the exact typer==0.21.1/click==8.3.1 pinned in uv.lock and
errors with "Option '--csv' requires an argument", so a single
--csv <path> option can't support "no path" reliably on this stack.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UsgjQGXqZVZBYqxoXvPTwk
compute_metrics conflated the two: for Predictor "banks" output, the
value used as "run_index" throughout was actually the composite
frame+panel slot key, so --per-run grouped by panel rather than by
true rotation frame whenever a frame had multiple detector panels.

extract_xyz_from_file now returns panel_index (physical bank) and
frame_index (true frame) alongside the existing slot index used
internally for goniometer/angles and goniometer/R lookups (left
untouched since those arrays are stored per-slot). frame_index is read
from peaks/run_index directly for Indexer/Integrator-format files, and
reconstructed for Predictor output by grouping slots that share an
identical goniometer/angles row (those rows are tiled per-panel from a
single frame's angles at write time, confirmed via source trace).

--per-run now groups by true frame; the per-peak CSV gains a
panel_index column alongside frame_index; the per-run histogram plot
(renamed plot_per_frame_histograms) facets by true frame instead of
panel/slot. Verified against synthetic HDF5 fixtures reproducing the
frame/panel tiling pattern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UsgjQGXqZVZBYqxoXvPTwk
plot_error_histograms/plot_per_frame_histograms gain a bins parameter
(default 50/30, matching the previously hardcoded values), threaded
through run_metrics as plot_bins and exposed on the CLI as --bins.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UsgjQGXqZVZBYqxoXvPTwk
run_index() unconditionally overwrote the true per-peak frame id
(peaks/run_index, correctly written upstream by Peaks.write_hdf5) with
the composite frame+panel slot id (peaks/image_index) whenever the
latter was present in the loaded input data - which is essentially
always for Finder output. This corrupted frame_index downstream (e.g.
in subhkl metrics --per-run) to span n_frames * n_panels instead of
n_frames, and fed the same corrupted value into FindUB.load_from_dict,
which then wrote it right back into the indexed output file.

Only fall back to image_index when run_index is genuinely absent.
Files already indexed with the old behavior need to be re-indexed to
pick up correct peaks/run_index values.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UsgjQGXqZVZBYqxoXvPTwk
compute_metrics now unpacks (xyz, slot_index, panel_index, frame_index)
from extract_xyz_from_file, but this test's mock still returned the old
2-tuple. The resulting unpack ValueError was silently caught and masked
by run_metrics' "METRICS: 9.99 ..." exception sentinel, so the test was
comparing against a fake fallback value instead of the real median
angular error.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UsgjQGXqZVZBYqxoXvPTwk
@jglaser

jglaser commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

@kbega Does this already have the functionality you want in #11

@kbega

kbega commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

I am not aware of PR #9 implementation, and so far I know it does not work and badly affects reproducibility. PR #11 is for error analysis and a separate implementation. Thanks, @jglaser and @vivek-booshan

@jglaser

jglaser commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

@kbega Can you please explain what do you mean by "does not work"?

@PrinceWalnut
PrinceWalnut marked this pull request as draft July 30, 2026 23:15
@jglaser
jglaser requested a review from SmithRWORNL August 11, 2026 14:18
Fixed linting issues.
@jglaser

jglaser commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Thanks!

@SmithRWORNL @kbega can you please check for redundancy with #38

@SmithRWORNL

Copy link
Copy Markdown
Contributor

@jglaser

My non-expert eye couldn't identify any code that looked like it was doing the same thing in both branches.

The comparison, for reference:
https://github.com/PrinceWalnut/subhkl/compare/metrics_improvements..kbega:neu-subhkl:indexer-error-analysis

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants