primat.plotting — plotting helpers¶
primat.plotting¶
Shared plotting conventions for nuclide abundance curves, so that every front
end (the notebooks/ figures and the Streamlit GUI) draws the same nuclide
with the same colour and line style.
Convention¶
Colour encodes the chemical element (the proton number Z): every isotope of hydrogen is one colour, every isotope of helium another, and so on. This is what the eye groups first, so it carries the most salient coordinate.
Line style encodes the isotope within an element: the lightest isotope is solid, the next is dashed, then dash-dot, dotted, and progressively finer custom dash patterns. Isotopes are ranked by mass number A, so the ordering is reproducible across plots that show different subsets of the network.
The free neutron
nis not a chemical element; it is drawn in black, solid, as a neutral reference curve.
The single public entry point is nuclide_styles(), which takes the list of
nuclide names (as used throughout primat, e.g. ["n", "p", "H2", "He4",
"Li7", ...]) and returns, for each name, a (color, linestyle, label)
triple ready to pass to matplotlib’s plot(..., color=, linestyle=,
label=).
Example
>>> from primat.plotting import nuclide_styles
>>> styles = nuclide_styles(["n", "p", "H2", "H3", "He3", "He4"])
>>> color, ls, label = styles["He4"]
>>> # color is the helium colour; ls distinguishes He4 from He3; label = '$^{4}$He'
- primat.plotting.parse_nuclide(name)[source]¶
Split a primat nuclide name into
(element_symbol, mass_number A).Handles the two non-standard names used as bookkeeping aliases in the network: the free neutron
"n"->("n", 1)(treated specially by the colour map) and the free proton"p"->("H", 1)(hydrogen-1). Every other name is of the form<element><A>(e.g."He4","Be7") and is split with a regex into its leading letters (the element symbol) and trailing digits (the mass number).- Parameters:
name (str) – Nuclide name as used in
abundance_names/run.Akeys.- Returns:
(str, int) – Element symbol and mass number. For the neutron the symbol is the sentinel
"n"(not a real element), with A = 1.- Return type:
Examples
>>> parse_nuclide("He4") ('He', 4) >>> parse_nuclide("p") ('H', 1) >>> parse_nuclide("n") ('n', 1)
- primat.plotting.abundance_evolution_curves(evolution, A, names, t_grid)[source]¶
Compute per-nuclide
A_i Y_i(t)curves ready to plot, backend-agnostic.The single piece of curve-preparation logic shared by every front end that draws an abundance-evolution figure (the Streamlit GUI’s
primat.gui.panels.render_evolution_panel()and thenotebooks/figures): build each nuclide’sY(t)interpolator from a plainprimat.evolution.EvolutionResult(viaprimat.evolution.Y_interpolator(), so it works on the result of eitherprimat.backend.run_bbn()backend, never requiring a live PythonPRIMATinstance), evaluate it ont_grid, weight by the mass numberA, and drop non-positive points (a log-y plot cannot show them). Colour/linestyle/label come fromnuclide_styles().- Parameters:
evolution (primat.evolution.EvolutionResult) – E.g.
run_bbn(params, ...)["evolution"](requiresoutput_time_evolution=True).A (dict) – Nuclide name -> mass number (e.g.
{name: NZ[0] + NZ[1] for name, NZ in cfg.Nuclides.items()}, the same mappingprimat.gui.run_view. GuiRun/primat.main.PRIMATexpose as.A).names (sequence of str) – Nuclide names to compute a curve for (e.g. a subset of
evolution.Y.keys()).t_grid (np.ndarray) – Cosmic time [s] grid to evaluate each
Y(t)interpolator on.
- Returns:
dict –
{name: (t_masked, y_masked, color, linestyle, label)}–t_masked/y_maskedaret_grid/A[name] * Y(t_grid)restricted to where the abundance is strictly positive.- Return type:
dict[str, tuple[‘NDArray[np.float64]’, ‘NDArray[np.float64]’, str, object, str]]
Example
>>> import numpy as np >>> from primat.backend import run_bbn >>> result = run_bbn({"network": "small", "output_time_evolution": True}) >>> A = {"n": 1, "p": 1, "H2": 2, "H3": 3, "He3": 3, "He4": 4, "Li7": 7, "Be7": 7} >>> t = np.logspace(0, 5, 500) >>> curves = abundance_evolution_curves(result["evolution"], A, result["evolution"].Y, t)
- primat.plotting.nuclide_styles(names)[source]¶
Map each nuclide name to a
(color, linestyle, label)triple.Colour is fixed per chemical element (
ELEMENT_COLORS); line style distinguishes isotopes of the same element, assigned by ascending mass number A so the lightest isotope present is solid, the next dashed, etc. (cycling throughLINESTYLES). The free neutron is black/solid.Because the isotope ranking is computed within each element from the names actually passed in, the same nuclide can in principle receive a different line style in two plots that show different isotope subsets – but the colour (the dominant visual cue) is always identical, and in practice the notebooks/GUI pass the full network’s nuclide list, so the styles are stable too.
- Parameters:
names (sequence of str) – Nuclide names (e.g.
run.abundance_names).- Returns:
dict –
{name: (color, linestyle, label)}for every input name.- Return type:
Example
>>> styles = nuclide_styles(["n", "p", "H2", "He3", "He4"]) >>> styles["p"][0] == styles["H2"][0] # same hydrogen colour True >>> styles["p"][1] != styles["H2"][1] # different isotope line styles True