Feat: Electronic minimization convergence plot#299
Merged
Conversation
Add xscale/yscale/y2scale fields (default None = automatic linear scale) to the Graph dataclass and wire them into the plotly axis options. This enables log-scale convergence plots such as the electronic-minimization summary.
Route the selection through select.Tree + index.Selector (as dos/band do)
so that multi-column selections ("E, dE") and compositions ("E + dE") work.
The VASP label "rms(c)" clashes with the selection grammar (parentheses mean
nesting), so it is exposed under the grammar-safe alias "rms_c"; the raw label
is retained for printing.
Without a selection, plot() now produces a convergence overview: the energy changes (|E_final - E|, |dE|, |d eps|) on a logarithmic left axis and the residuals (rms, rms_c) on a logarithmic secondary axis, mirroring the ALGO convergence-summary idea. An explicit selection plots the chosen columns on a logarithmic axis, flowing through the standard selection logic (e.g. "E, rms"). Positive-value marker flagging from the idea is intentionally left out for a later exploration.
VASP reports zero for a column until it is computed - most notably rms(c), which stays zero until density updates begin after the NELMDL delay. read() now treats any convergence entry whose magnitude is below a small threshold as not-yet-computed and reports it as NaN, for every column. The convergence overview therefore no longer plots spurious near-zero points on its log axis. Printing (__str__) still reproduces the raw OSZICAR values verbatim.
A logarithmic axis cannot show negative numbers, but some columns are signed - most notably "ort" (reported as rms(c) for ALGO=All), which can be negative. A directly plotted series is now shown as |value| and labelled "|label|" when any of its values is negative, and plotted/labelled as-is when all are non-negative. The energy distance |E_final - E| remains a magnitude by construction.
The overview hardcoded the residual token as "rms_c", so a run whose 7th column is labelled differently (e.g. "ort" for the fixed ALGO=All output) raised a KeyError. Derive the residual series from the actual labels by excluding the fixed non-residual columns (N, E, dE, deps, ncg) instead.
…tive The convergence overview measured the energy distance as E_final - E, which is negative while the energy sits above its converged value - i.e. for essentially every step of a normal run. Flip the convention to E - E_final so the distance is positive by default, and route it through the same sign-aware _make_series helper as the other columns (shown as |E - E_final| only when the energy overshoots below its final value). The demo energy now decreases monotonically.
Add a Marker(symbol, size) dataclass (exported as graph.Marker) and wire the marker symbol and size through to the plotly trace, so a series can choose how its points are drawn. A bare string stays valid as a shorthand for the symbol, and a small alias map translates friendly names (o, *, x, s, ^, v, d, +) to plotly symbols so the plotly vocabulary does not leak into the public API. Add a show_legend flag so several series can share a single legend entry.
The convergence overview plots magnitudes on a log axis, so the sign of signed columns (dE, d eps, and ort) is not visible. When any value is negative, add an extra markers-only "negative" series that flags those points with a small cross at their magnitude, one overlay per axis sharing a single legend entry.
Three fixes to the sign overlay: - The 'x' alias mapped to plotly's 'x-thin', an open thin symbol that renders invisibly without a line width; map it to the filled 'x' so the points show. - Flag only the atypical (minority) sign of each series instead of every negative point, so a normally-negative dE is no longer marked wholesale. - Relabel the overlay 'unusual sign' to match that meaning. Markers on the two axes still share a single legend entry.
When a graph has a secondary y-axis, the default legend position (x=1.02) sits on top of the y2 axis title on the right. Move the legend further right and widen the right margin so the (potentially long) labels are not clipped.
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.
Improve the electronic-minimization convergence plot
Reworks
electronic_minimizationinto a proper convergence overview and adds theGraphfeatures it needs.Electronic minimization
read/plotnow use the standardselect/indexselection logic, so composing and listing columns works ("E + dE","E, rms"). Therms(c)label is aliased to the grammar-saferms_c.rms(c)/ortbefore the NELMDL delay) are reported asNaNinstead of zero.plot()is a convergence overview: energy changes (E − E_final,dE,d eps) on a log left axis, residuals (rms,rms(c)/ort) on a log secondary axis. Residual columns are derived from the labels, so theALGO=Allortcolumn works.E − E_final(positive while converging). Points whose sign is atypical for their series are flagged with a small "×" ("unusual sign"), so a normally-negativedEisn't marked wholesale.Graph
xscale/yscale/y2scale.Marker(symbol, size)(a bare string is shorthand); a friendly symbol-alias map keeps plotly's vocabulary out of the public API. Addedshow_legendso series can share one legend entry.