solprop.output.capability#

What a stored basis admits: the accessor whitelist of the run record.

A saved run is read through one protocol, and for every route but one a run’s mode axis means the same thing: an orthogonal one- or two-component basis whose coordinate powers add up to the physical power. A general modal guide resolves three Cartesian components at its own quadrature nodes, and its coordinate quantities are not that: energy and peak_power are defined for it only because its metric happens to be the identity, and peak_intensity is not defined for it at all. Rather than redefine the old names on a basis they do not describe, the record names the capability that produced the file and refuses, by name, every accessor that capability does not admit.

This module is the gate; the sets it reads are in solprop.stats, beside the catalogue of names they select from, so that a translation module can record the list a file publishes without importing an output one.

The gate is applied at four doors: at solprop.stats.StatsSpec admission, where the driver knows the problem; in each CPU backend’s stats, for a caller who builds one and asks it directly; in the accessors of solprop.processing.modal; and in the legacy processing accessors of solprop.processing.time and solprop.processing.fields and the plots drawn from them, which see only the stored record (reading_refusal()). A modal run of any other route carries no general identity, and is read as the ordinary modal run it is: the general names are refused for it, because the certified metric and the stored E/H reference they promise are exactly what such a file does not have.

The fourth door also refuses a spatial file’s columns read as modes. The legacy readers were written for a mode axis of true-power amplitudes in sqrt(W). A radial or Cartesian column is a field sample in V m or V/m and a planar column a slab amplitude per y frequency, so |a|^2 summed over them is neither a power nor an energy: COLUMN_READINGS names those readers and the spatial functional that measures the quantity instead. A run’s statistics are not readers and are not narrowed: the spatial route’s stats/energy is the physical energy and is admitted as before.

The manual page is docs/guide/results/statistics.md.

Module Attributes

BasisCapability

Which kind of basis a run's mode axis is, and so which accessors it admits.

CAPABILITIES

Every declared basis capability, in the order the manual lists them.

ACCESSOR_WHITELIST

Which statistics and accessors each capability admits.

COLUMN_READINGS

The readers that take each column of a file's mode axis for a modal amplitude.

Functions

capability_of(metadata)

Return the capability a stored record declares.

declared_capability(*, general_modal, spatial)

Return the capability a translated problem declares.

reading_refusal(metadata, name, *[, recorded])

Return why a reader of a stored record refuses it, or None.

refusal_for(capability, names, *[, withheld])

Return why the first inadmissible accessor is inadmissible, or None.

withheld_accessors(*, general_modal, ...)

Return the names a problem withholds beyond its basis's whitelist.

withheld_from(metadata)

Return the names a stored record withholds beyond its basis's whitelist.

solprop.output.capability.ACCESSOR_WHITELIST: Mapping[Literal['modal', 'general_modal', 'spatial'], frozenset[str] | None] = {'general_modal': frozenset({'analytic_flux', 'channel_labels', 'coordinate_intensity', 'electric_field', 'fwhm_t', 'fwhm_t_outer', 'instantaneous_flux', 'magnetic_field', 'omega0', 'physical_energy', 'plane_nodes', 'reconstructed_flux', 'spectral_flux', 'zdw'}), 'modal': None, 'spatial': None}#

Which statistics and accessors each capability admits.

None means “every name this run has always had, and no general one”.

An orthogonal modal run and a spatial run keep every statistic they have always had – this table never narrows an existing route’s statistics – and refuse the ten names of _GENERAL_ONLY, which need a certified flux metric and a stored E/H reference they do not carry. A general modal run admits exactly its own list, plus the basis-independent step diagnostics section 6 allows.

The table is read at every door, so it speaks of statistic names, and on a spatial run those are the physical flux the run recorded. What it does not cover is the processing readers that take each column of a file’s mode axis for a modal amplitude: on a spatial file those are refused at the processing door by COLUMN_READINGS, not here, because energy the statistic is admitted where energy the reader of the stored columns is not.

solprop.output.capability.BasisCapability#

Which kind of basis a run’s mode axis is, and so which accessors it admits.

alias of Literal[‘modal’, ‘general_modal’, ‘spatial’]

solprop.output.capability.CAPABILITIES: tuple[Literal['modal', 'general_modal', 'spatial'], ...] = ('modal', 'general_modal', 'spatial')#

Every declared basis capability, in the order the manual lists them.

solprop.output.capability.COLUMN_READINGS: Mapping[str, str] = mappingproxy({'energy': 'use solprop.spatial.spatial_energy{slab}', 'peak_power': 'use the largest value of solprop.spatial.spatial_power', 'get_power': 'use solprop.spatial.spatial_power', 'get_spectral_density': '{spectrum}', 'fwhm_t': 'use solprop.processing.fwhm of solprop.spatial.spatial_power', 'fwhm_f': '{spectrum}', 'time_bandwidth': 'use solprop.processing.fwhm of solprop.spatial.spatial_power for the duration; for the bandwidth, {spectrum}', 'arrival_time': 'use solprop.processing.moment of solprop.spatial.spatial_power', 'field_autocorrelation': 'use solprop.spatial.spatial_energy for its value at zero delay', 'intensity_autocorrelation': 'use solprop.spatial.spatial_power', 'coherence_time': 'it is the width of the transform of a spectrum: {spectrum}', 'prop_2d': 'use solprop.spatial.spatial_power at each saved plane for the temporal map; for the spectral map, {spectrum}', 'time_1d': "use solprop.spatial.spatial_power for the power; get_field reads a column's field, in the file's own units", 'spec_1d': '{spectrum}', 'plot_energy': "use the run's stats/energy, which is the beam's energy at each plane"})#

The readers that take each column of a file’s mode axis for a modal amplitude.

Each of the processing and plotting readers named here forms |a|^2 of a column in the square root of watts and sums it over polarisation and, on request, over columns. This is the one list of what a spatial file refuses. The value of each entry is what to use instead, a functional of solprop.spatial on a saved plane and its SpatialFlux; {spectrum} and {slab} stand for the route’s own spectral functional and slab-mode energy, which reading_refusal() fills in, so that the advice names only what works on the file’s route. On a modal or general modal file these readers are what they always were.

solprop.output.capability.capability_of(metadata)[source]#

Return the capability a stored record declares.

A record whose modal identity declares the general modal basis is a general modal run; a radial or Cartesian run is spatial; everything else – including a record that carries no modal identity at all, and a capillary carrying a coherent wall block, whose identity declares the same orthogonal HE_1m basis it always had – is the ordinary modal basis. It is keyed on modal["basis"] rather than on the identity being present at all because a second route (a capillary with a coherent wall) carries an identity of its own, and a coupled flow through a basis does not change the basis; a general modal record declares "general_modal" there, so nothing already stored reads differently.

Parameters:
metadatasolprop.output.schema.RunMetadata

The record read back from a handler.

Returns:
str

One of CAPABILITIES.

Examples

>>> from solprop.output.capability import capability_of
>>> from solprop.output.schema import _example_metadata
>>> capability_of(_example_metadata())
'modal'
solprop.output.capability.declared_capability(*, general_modal, spatial)[source]#

Return the capability a translated problem declares.

The problem-side companion of capability_of(), for the two places that hold a problem rather than a record: the run loop’s statistics admission and the reference backend’s own stats.

Parameters:
general_modalbool

Whether transform.modal_tables is set, which is what makes a run a general modal one.

spatialbool

Whether transform.geometry is set, which is what makes it a radial or Cartesian beam.

Returns:
str

One of CAPABILITIES.

Examples

>>> from solprop.output.capability import declared_capability
>>> declared_capability(general_modal=True, spatial=False)
'general_modal'
>>> declared_capability(general_modal=False, spatial=False)
'modal'
solprop.output.capability.reading_refusal(metadata, name, *, recorded=())[source]#

Return why a reader of a stored record refuses it, or None.

The processing door of the gate, for the readers that see only the stored record: on a spatial record a reader of COLUMN_READINGS is refused, because it would read each transverse column as a modal amplitude in sqrt(W); otherwise a name ACCESSOR_WHITELIST speaks of is asked of refusal_for(), with the names the record withholds. A reader of no such name – a trace, a density, a plot – is admitted on every modal basis, as it always was.

Parameters:
metadatasolprop.output.schema.RunMetadata

The stored record.

namestr

The reader or accessor asked for, which the refusal names.

recordedcollections.abc.Sequence, optional

The statistics the file holds. A spatial refusal points to those of them that measure the beam, and to none the run did not record.

Returns:
str or None

The refusal, or None when the record admits name.

Examples

>>> from dataclasses import replace
>>> from solprop.output.capability import reading_refusal
>>> from solprop.output.schema import _example_metadata
>>> reading_refusal(_example_metadata(), "get_power") is None
True
>>> radial = replace(
...     _example_metadata(),
...     simulation_kind="radial",
...     spatial={"geometry": "radial", "flux_model": "scalar-axial-admittance"},
... )
>>> reading_refusal(radial, "get_power", recorded=["energy"])[:44]
'get_power measures modal amplitudes and this'
solprop.output.capability.refusal_for(capability, names, *, withheld=())[source]#

Return why the first inadmissible accessor is inadmissible, or None.

The one text both doors use, so that a name refused at admission and the same name refused in processing say the same thing. The message names the basis and the replacement, and never redefines the old name.

Each name is refused for its own reason. A legacy power name is refused because a general basis’s coordinate quantities are not additive; a gas or spatial name is refused because this guide has no gas fill and no transverse geometry, which is not a statement about the basis at all; and a basis-independent step diagnostic is admitted here whatever the basis, so that whoever owns its real reason is the one that refuses it.

Parameters:
capability{‘modal’, ‘general_modal’, ‘spatial’}

What the run’s basis is, from capability_of() or declared_capability().

namescollections.abc.Sequence

The accessor or statistic names asked for, in the order they were asked.

withheldcollections.abc.Sequence, optional

Names the basis admits in general but this run does not publish: a declared basis of a split block executes through a coupled flow whose channels beat, so a per-channel propagation constant is the block’s mean and zdw from it is a number that propagates nothing. The route withholds the name from its record and every door refuses it by name.

Returns:
str or None

The refusal, or None when every name is admitted.

Examples

>>> from solprop.output.capability import refusal_for
>>> refusal_for("general_modal", ["peak_power"])[:34]
'peak_power is unavailable for this'
>>> refusal_for("modal", ["energy"]) is None
True
>>> refusal_for("general_modal", ["quadrature_error"]) is None
True
>>> refusal_for("general_modal", ["zdw"], withheld=("zdw",))[:30]
'zdw is unavailable for this ru'
solprop.output.capability.withheld_accessors(*, general_modal, coupled_flow)[source]#

Return the names a problem withholds beyond its basis’s whitelist.

A general modal problem carrying linear.coupled_flow executes a declared basis of a split block, whose per-channel propagation constant is the block’s mean, so it withholds solprop.stats.WITHHELD_WITH_A_FLOW; every other problem withholds nothing. The two execution doors pass this to refusal_for(), and the route leaves the same names out of the record’s published list so that the file doors agree (withheld_from()).

Parameters:
general_modalbool

Whether transform.modal_tables is set.

coupled_flowbool

Whether linear.coupled_flow is set.

Returns:
tuple of str

The withheld names, sorted; empty for every problem without a split block.

Examples

>>> from solprop.output.capability import withheld_accessors
>>> withheld_accessors(general_modal=True, coupled_flow=True)
('zdw',)
>>> withheld_accessors(general_modal=False, coupled_flow=True)
()
solprop.output.capability.withheld_from(metadata)[source]#

Return the names a stored record withholds beyond its basis’s whitelist.

The file doors’ half of withheld_accessors(): a general modal record whose published accessors list leaves out a name of solprop.stats.WITHHELD_WITH_A_FLOW was written by a split-block route, and the name is refused from the file exactly as it was from the run. A record of any other basis, or one with no published list, withholds nothing.

Parameters:
metadatasolprop.output.schema.RunMetadata

The stored record.

Returns:
tuple of str

The withheld names, sorted.