Lattice viewer: a .vti exporter in CI and a GLMakie voxel viewer outside it - #25
Lattice viewer: a .vti exporter in CI and a GLMakie voxel viewer outside it#25aurascoper wants to merge 14 commits into
Conversation
export_vti.jl turns a transport snapshot into VTK ImageData: species as UInt8 with 0 for medium and wall, the stored cell_id with its sentinels, lineage, generation, the interior mask, the two CPM fields, and the accumulated dose under the schema's own label (physical Gy, zero until a dose was imported). The nutrient field comes only from a restart file and the OpenMC dose rate only from a transport result, both optional, because the snapshot carries neither. A directory becomes a .pvd keyed by the mcs attribute, a step count and not a time. Spacing is 1.0 per site. Any other spacing is refused unless a declared pitch is passed and labelled as declared, since the pitch is D-PITCH and awaiting measurement. The snapshot's axis and sentinel attributes are carried into the file as field data rather than restated. tests/vti_export_tests.jl reads every array back with ReadVTK and compares it to the snapshot, checks VTK x is Julia axis 1 by a 3x4x5 array valued 100i+10j+k and by the snapshot's own orientation probes, keeps background 0 and wall -1, refuses spacing 0.012 without a declaration, and refuses a duplicate mcs in a series. String field data is read back by hand because ReadVTK reads numeric arrays only. WriteVTK and ReadVTK are ordinary deps: CI instantiates the project and runs tests/runtests.jl directly, so a test extra would not be installed there. The fixture's basis_gate_ack is added to the census. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UR6L4KXRqhcHQkDdq5kbX7
…d that reaches it viewer/visualize_lattice.jl reads a transport snapshot and draws one cube per occupied site with GLMakie's voxels recipe: 0 is air where the file's own background and wall sentinels say so, ids 1..7 index the serial script's palette, the legend carries the species labels, and the title carries the MCS and nothing else. It never re-runs the simulation. A still or a short orbit can be written; nothing rendered is committed. viewer/ is its own Julia project with GLMakie pinned by a committed Manifest (un-ignored for this directory only), so the main environment pulls no OpenGL dependency. The viewer is not run in CI, and that is stated as uncovered surface in the note, not hidden behind a skip. Planting the retracted word in the viewer's title left every guard green: the figure-vocabulary guard reads preprint/figures sidecars, and the ceiling guard scans three other terms. tests/manuscript_claims_tests.jl now scans every .jl under viewer/ and the .vti exporter for it, with a synthetic control, so an image made here cannot carry the word an image in the manuscript may not. This replaces feat/visualize-3d (50228b8), whose script re-ran the simulation in-process, drew with CairoMakie meshscatter, and titled every frame with that word; its palette and frame loop are what survive. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UR6L4KXRqhcHQkDdq5kbX7
…3d read from source Part A records what that branch was, read locally: one commit on an April base, an in-process CairoMakie meshscatter GIF, no checkpoint read, no test, and a frame title carrying the retracted word. The note says the new tools replace it and what was salvaged. The snapshot schema the tools read is tabulated from export_checkpoint.jl and docs/exchange_schema.md, with the two things it does not carry and the scope of each absence. The GLMakie table keeps the documentation claims with their URLs and adds what running the viewer here established, with the pinned versions. The exporter section states the arrays, the unit strings, the spacing rule, the [deps] reasoning, the 44 assertions and the three planted controls with their red and green counts. CI coverage and its one gap are stated as coverage, and the guard that closed the gap is named. Copydesk discipline check on the note reads zero em dashes in prose (the three counted are the --restart and --dose flags) and four inline colons, all inside quoted unit strings in table cells. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UR6L4KXRqhcHQkDdq5kbX7
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cb872c8521
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…s its qualifier The first scan reached only viewer/, the directory the planted word landed in, which is the defect relocated. It now walks every .jl, .R and .py under the root minus .git and virtualenvs against a declared allowlist of the five files that carry the word in comments or as a vocabulary, with a synthetic control and a control that plants the word under a directory that did not exist when the scan was written, through the same walker. A bench/plant.jl planted by hand on committed state failed it by name. GUARD-SCOPE-01 records the gap in the ledger and AGENTS.md rule 1 records the lesson. A dose-rate array from a transport result is now labelled from that file's own target_calibration and source_rate_photons_per_s attributes, so a synthetic source rate reads "synthetic source rate, not a physical target" beside the number in ParaView; a file without those attributes is refused and nothing is written. Seven assertions cover the two labels, the refusal and the mesh check. The note's API tables now say which doc pages were consulted and that they were not reconciled against the pinned versions except where a test exercises the call; the pyvista version is stated and the ParaView recipe is marked unsourced. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UR6L4KXRqhcHQkDdq5kbX7
…branch line says what is true today Each GLMakie row now carries what the 2026-09-07 run on the pinned GLMakie 0.13.14 / Makie 0.24.14 established, with the call verbatim, and which clauses no run touched. The WriteVTK paragraph says per call what the 51 assertions exercise at the pinned 1.22.0 and 0.2.6, and that compression is the one path no test takes. feat/visualize-3d is to be deleted after #25 merges; its commit is reachable at the tag archive/visualize-3d, pushed and read back today. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UR6L4KXRqhcHQkDdq5kbX7
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UR6L4KXRqhcHQkDdq5kbX7
One assertion checks that the round-trip file carries no compressor and raw appended encoding, which is what export_vti writes by default and the only form it offers. Flipping the default to compressed turns the round trip red at that line and the two string reads after it; restoring it returns 52 of 52. The note says the same in place of a sentence that read as if compression were a shipped path no test took. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UR6L4KXRqhcHQkDdq5kbX7
export_transport_series advances one simulation in windows of k and writes snap_mcsNNNNNN.h5 after each, plus the final MCS when it is not a multiple, so a series comes from one trajectory rather than one run per snapshot. The CLI takes --every K with a directory as the output. Six assertions cover the file names and their mcs attributes, the .pvd built from them, and the refusals of every = 0 and every above n_mcs; the CLI was run once to 30 MCS every 10 and the .pvd carries 10, 20 and 30. Rendered exports (*.vti, *.pvd) are ignored by git. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UR6L4KXRqhcHQkDdq5kbX7
… it reported Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UR6L4KXRqhcHQkDdq5kbX7
…iewer, and two refusals The retracted-word scan read one term where the vocabulary has four; it now reads RETRACTED_IN_FIGURES out of the python guard at test time and scans the root for each, with per-term declared allowlists and a fresh-root control that plants a term other than the first through the production walker. A hand plant of the second term in a new directory failed by name on committed state. The viewer's renderer-free half (the grid from the file's own sentinels, the palette, the CLI contract) moves to viewer/lattice_grid.jl and runs in CI from the main environment. The GL half is checked statically: the file parses and every free name resolves in Base, HDF5, that file, a local binding, or the declared GLMakie names; a planted undefined call is reported by the same walker. export_vti refuses a restart whose mcs is not the snapshot's, and a dose file that declares any axis order but xyz or declares none. Fixtures now declare the axis order results.py always writes. viewer/paraview_species.py is the pvpython script that rendered the species view through ParaView 6.2.0, so the note's recipe is a run. 80 assertions in the exporter file, 122 in the manuscript guard, full suite green. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UR6L4KXRqhcHQkDdq5kbX7
Canonical 42-parcel coupled run with inert accepted-copy logging, sampled identity analysis, replay, RNG and window equivalence, and negative controls. Tree identical to producer commit 8cbb8eee1c224298341a0b93a19ab5e078929b14; the original producer history is preserved in the evidence archive.
Add the categorical parcel-label figure and measured trajectory results. Build TeX outside the checkout and retain an archive of exact inputs and outputs, preserving the live-source claims census. The 101-snapshot production export, independent postflight, 28,685 Julia checks, 46 claim/figure checks, and staged PDF inspection passed. Figure 1 is unchanged. Tree identical to validated local commit 2969141e59c84bdb09e3a1cdbb26ddba534f76f9.
The callback addition moved the unchanged diffusion-stability statement from line 1453 to 1469, making calibration-unit fail its source citation guard. Update the Markdown and TeX citation together, regenerate the guide PDF through render_guide.py, and retain the source hash emitted by that successful render. Validation: reproduced the original failure; all five guide citation and artifact checks now pass. The eight-page PDF retains identical extracted wording apart from the citation and whitespace, and the changed page was visually inspected. Rendered with Tectonic 0.17.0 using a local TeX Live directory bundle because the default remote bundle returned HTTP 403. No model code, numerical results, manuscript figure, or CI configuration changes.
|
@codex review Please review PR #25 at head commit Please identify the commit actually reviewed in the review result. PR #25 remains on hold; do not merge. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6cd270f7f2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| manifest = verified_manifest(run) | ||
| base = render(run, manifest) | ||
| stage_and_build(run, manifest, base, install=args.install) |
There was a problem hiding this comment.
Refuse completed builds before rerendering
At the reviewed head 6cd270f7f262d6e2d51aa09c2a7bec9b92653958, rerunning the renderer on a successfully built run passes verified_manifest because manuscript_built is accepted, then render overwrites the verified Figure 5 files before stage_and_build notices the existing manuscript directory and raises. Since generated PDF bytes can change between renders, this can leave the run's figures inconsistent with its unchanged manifest and receipt; check for the completed manuscript output before calling render.
Useful? React with 👍 / 👎.
| if abspath(PROGRAM_FILE) == @__FILE__ | ||
| o = viewer_options(ARGS) | ||
| out = show_lattice(o.snapshot; record_to = o.record_to, still = o.still, frames = o.frames) | ||
| out isa String ? println("wrote $out") : (println("close the window to exit"); wait(GLMakie.Screen())) |
There was a problem hiding this comment.
Wait on the screen that displays the figure
In interactive mode, show_lattice calls display(fig) but returns the figure, after which this line constructs a separate GLMakie.Screen() and waits on that unrelated screen. Consequently the process can either exit without keeping the displayed window alive or remain attached to another screen after the visible lattice window is closed; retain the screen returned by displaying the figure and wait on that instance.
Useful? React with 👍 / 👎.
Drive a declared source-diffusion-decay field from the immutable 101-frame seed-42 parcel trajectory. Keep acceptance and the original evidence unchanged. Add numerical controls, ParaView exports, a browser event/label explorer, native viewer reader, and a separately scoped signal figure and manuscript section. Validated with the full Julia suite, 428 calibration tests (5 expected skips), 101-frame HDF5/VTI read-back, browser replay, and a staged 40-page manuscript build. Native GLMakie window execution remains a target-host check. PR #25 remains unmerged. The published tree matches local 3126146def37cc4a2fdaa448acc7b09260fa890c; local producer history is retained with the evidence.
Stacked on #23 (
fix/figure-artifacts-and-v11); merges after it. Independent of #24, which is stacked on the same base.Three commits, each pushed after the one below it was green.
export_vti.jlandtests/vti_export_tests.jl. A transport snapshot becomes VTK ImageData for ParaView, a directory of snapshots a.pvdkeyed by themcsattribute. Lattice units only, so spacing is 1.0 per site, and any other spacing is refused unless a declared pitch is passed and labelled as declared. Species is UInt8 with 0 for medium and wall by the file's own sentinel attributes; every other array is carried as stored, the accumulated dose under the schema's own label. Nutrient (restart file) and the OpenMC dose rate (transport result, Gy/s) are optional inputs because the snapshot carries neither. WriteVTK and ReadVTK are ordinary deps because CI runstests/runtests.jldirectly, so a test extra would not install. 44 assertions; three planted controls (transposed array, refusal removed, one label corrupted) each red then green on committed state.viewer/visualize_lattice.jlon GLMakievoxels, in its own project with a committed Manifest (GLMakie 0.13.14, Makie 0.24.14) so the main environment pulls no OpenGL dependency. Reads a snapshot; never re-runs the simulation; title carries the MCS and nothing else. Not run in CI, stated as uncovered surface. Planting the retracted word in its title left every suite green (the figure-vocabulary guard readspreprint/figures/*.txt; the ceiling walk scans other terms), sotests/manuscript_claims_tests.jlnow scansviewer/*.jlandexport_vti.jlfor it with a synthetic control; the same plant fails at the planted line.docs/visualization/lattice_viewer.md. Part A is read from source.feat/visualize-3dis one commit (50228b8) of an in-process CairoMakie GIF script with the retracted word in its frame titles; these tools replace it, keeping its palette. Retiring that remote branch is not done here.Nothing rendered is committed. Any image from either tool intended for the manuscript is registered with the figure-staleness guard first.
🤖 Generated with Claude Code
https://claude.ai/code/session_01UR6L4KXRqhcHQkDdq5kbX7