feat(ui): solid mode-displacement arrows + CIF/mCIF export from the 3D card#6
Merged
Merged
Conversation
…D card
Arrows (requirement 1). Two independent problems with the green
distortion-mode arrows on the PDF page:
Too long — the scale was span·0.34 with span the bounding-box body
DIAGONAL, so on GaTa4Se8 (10.36 A cubic) the longest arrow ran ~6 A,
well past the neighbouring site; the pattern read as a vector field
over the cell instead of a displacement of each atom. Now
min(shortestCellEdge·0.26, span·0.12) ~ 1.8 A, about one bond. Tying
it to the cell edge rather than the diagonal also stops the arrows
growing when a supercell is displayed.
Stems too thin — THREE.ArrowHelper draws its shaft with
LineBasicMaterial, which WebGL rasterizes at a single device pixel
however close the camera gets, so the stem was a hairline that
disappeared against the lit spheres. New `arrowBuilder` emits a real
cylinder shaft + cone head in MeshPhongMaterial, lit by the same
lights as the atoms and bonds. Shaft/head sizes are constant across a
set so length alone carries the amplitude and the smallest arrow of a
pattern stays legible; unit geometries are built once per overlay and
scaled per arrow. Head length is capped at a fraction of a short arrow
so a small one keeps a shaft instead of collapsing to a bare cone.
Verified on the GaTa4Se8 demo, mode 1 @ Gamma (Ta1): the <111> arrows
on the 16 Ta copies now read as solid local displacements.
Export (requirement 2). StructureView gains `exports` — a list of
host-supplied {label, title, run} descriptors rendered as download
buttons in its toolbar. Descriptors rather than a flag so the viewer
never learns which flavour it is writing: the label tracks the content,
which is what makes room for the mCIF work ahead (moments today, mode
displacements once the writer carries them). Wired into three hosts:
the PDF card (phase on screen), the Rietveld card (phase the picker
selects, mCIF when the primary phase carries moments) and the magnetic
analysis card (mCIF at the current amplitudes as soon as a group is
previewed, so file and arrows agree).
Fix found while wiring: EVERY CIF export wrote the STARTING structure.
structureToCif reads coordinates and cell straight off the model and
consults the parameters only for their esds, but all three workbenches
passed the pre-refinement `structure` — so exported files carried
starting coordinates annotated with refined uncertainties and refined
R-factors. All three now pass the model with parameters applied, and
the powder path routes bindings by phase (as refinedPhases does) so a
multi-phase session cannot attach one phase's esds to another's
identically-labelled site. cif.test pins the contract both ways.
Full suite green (1126 passed); typecheck clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two UI requests, plus a data-integrity fix found while wiring the second.
1. Distortion-mode arrows (PDF page, irreps)
Two independent problems with the green arrows:
Too long. The scale was
span * 0.34wherespanis the bounding-box body diagonal — on GaTa₄Se₈ (10.36 Å cubic) that is 17.9 Å, so the longest arrow ran ~6 Å, well past the neighbouring site. The pattern read as a vector field over the cell rather than a displacement of each atom. Nowmin(shortestCellEdge · 0.26, span · 0.12)≈ 1.8 Å, about one bond. Tying it to the cell edge rather than the diagonal also stops arrows growing when a supercell is displayed.Stems too thin. The real culprit:
THREE.ArrowHelperdraws its shaft withLineBasicMaterial, which WebGL rasterizes at a single device pixel however close the camera gets — the stem was a hairline that disappeared against the lit spheres. NewarrowBuilderemits a real cylinder shaft + cone head inMeshPhongMaterial, lit by the same lights as the atoms and bonds. Shaft and head sizes are constant across a set, so length alone carries the amplitude and the smallest arrow of a pattern stays legible; unit geometries are built once per overlay and scaled per arrow.Verified in the running app on the GaTa₄Se₈ demo, mode 1 @ Γ (Ta1): the ⟨111⟩ arrows on the 16 Ta copies now read as solid local displacements.
2. CIF export from the 3D model
StructureViewgainsexports— a list of host-supplied{label, title, run}descriptors rendered as download buttons in its toolbar. Descriptors rather than a boolean so the viewer never learns which flavour it is writing and the label tracks the content; that is what leaves room for the mCIF work ahead (moments today, mode displacements once the writer carries them).↓ CIF↓ CIF/↓ mCIF↓ CIF→↓ mCIFonce a group is previewedThe magnetic-analysis card is beyond the two pages originally asked for, but it is the view that actually holds the moments, so it is where mCIF means the most — and its export uses
appliedMagnetic, the very model drawn as arrows, so file and picture agree.Fix: every CIF export wrote the starting structure
Found while tracing the export path.
structureToCifreads coordinates and cell straight off the model and consults the parameters only for their esds — but all three workbenches passed the pre-refinementstructure. Exported files therefore carried starting coordinates annotated with refined uncertainties and refined R-factors.All three now pass the model with parameters applied. The powder path additionally routes bindings by phase (as
refinedPhasesdoes), so a multi-phase session cannot attach one phase's esds to another phase's identically-labelled site.cif.test.tspins the contract in both directions.Verification
tsc -b --noEmitcleanNot touched
The red magnetic moment arrows still use
ArrowHelper, so they share the hairline-stem issue and sit atspan * 0.42. Left alone deliberately — out of scope, and that rendering has a validated look plus test coverage. Routing them through the same builder is a two-line follow-up.🤖 Generated with Claude Code