solprop.recipe.registry#
From recipe values to the objects a route takes: the registry and the decoder.
A recipe names an object by a type key, which must be an entry of the fixed
REGISTRY (SEP 41 section 5.1): a named factory, a constructor, class
method or module function, with the units of its keywords declared and any build
context it receives declared too. Format 1 defines one context, the route’s time
grid, so absorber = {type = "absorber"} builds
solprop.boundaries.absorber(grid); on the free-space routes it is the grid
keyword itself, and the absorber is a keyword of the settings table.
A recipe never imports a module or evaluates code: a type outside the registry is
refused, and the Python export is the way out.
decode() turns one value of a recipe into the Python value a keyword takes:
quantities into numbers in the keyword’s unit, {re, im} into a complex number,
{file, sha256} into an array read from a checked file, a table with a type into
an object, and "none" into None where the keyword has that spelling.
Module Attributes
What a factory may be given besides its keywords: format 1 defines the time grid. |
|
A keyword's unit: one unit string, a rule by element index, or none. |
|
The types a recipe may name, keyed by the |
Functions
|
Build the object a table with a |
|
Give a decoded list the container its parameter's annotation asks for. |
|
Turn one recipe value into the Python value a keyword takes. |
|
Turn the value of one build keyword into what the constructor takes. |
|
Return the unit of the form a keyword's value takes. |
Classes
|
What decoding a recipe may read besides the recipe's own values. |
|
A registered type: what a |
- class solprop.recipe.registry.BuildContext(base=None, allow_outside=False, grid=None, embedded=<factory>, mode_fill=False)[source]#
Bases:
objectWhat decoding a recipe may read besides the recipe’s own values.
- Attributes:
- basepathlib.Path or None
The recipe’s directory, against which data files resolve;
Nonefor a recipe from text, which then may hold no data file.- allow_outsidebool
Whether a data file may lie outside base.
- gridsolprop.grid.TimeGrid or None
The route’s time grid, for a factory that declares it as its context;
Noneuntil the route has built one.- embeddedcollections.abc.Mapping
Data files held in memory by the name the recipe refers to them by, as a run’s output embeds them (SEP 41, S2); read before the directory.
- mode_fillbool
Whether a supplied mode may name its own fill (
Factory.fill): on the planar route, whose slab channels carry the run’s fill. The guided routes rebind every supplied mode to their own fill, so there it may not.
Examples
>>> from solprop.recipe.registry import BuildContext >>> BuildContext().grid is None True
- solprop.recipe.registry.Context#
What a factory may be given besides its keywords: format 1 defines the time grid.
alias of
Literal[‘grid’]
- class solprop.recipe.registry.Factory(name, target, units=<factory>, context=(), data_file=None, omitted=(), fill=())[source]#
Bases:
objectA registered type: what a
typenames, and how its keywords are read.- Attributes:
- namestr
The
typea recipe writes, as"GaussianPulse"or"EnvelopeGrid.from_limits".- targetcallable
The constructor, class method or function it calls.
- unitscollections.abc.Mapping
The unit of each keyword that has one (
UnitSpec); a keyword not listed is read as it stands.- contexttuple of str
What it receives besides its keywords, passed first and positionally.
- data_filestr or None
The keyword a
{file, sha256}reference fills with the file’s text, for a loader such asload_spectrum;Noneotherwise.- omittedtuple of str
Keywords of the target that a recipe may not give, so that they are not part of the format:
RungeKutta’stableau, and a mode’s own fill, which the route replaces with its own.- filltuple of str
A mode’s own fill keywords, which a recipe gives only where the context allows a mode its fill (
BuildContext.mode_fill): the slab channels of the planar route, whose fill is the run’s.
Examples
>>> from solprop.recipe.registry import REGISTRY >>> REGISTRY["GaussianPulse"].units["fwhm"] 's'
- solprop.recipe.registry.REGISTRY: Final[Mapping[str, Factory]] = {'BoundaryCheck': Factory(name='BoundaryCheck', target=<class 'solprop.monitor.BoundaryCheck'>, units={}, context=(), data_file=None, omitted=(), fill=()), 'CoherentWall': Factory(name='CoherentWall', target=<class 'solprop.modes.capillary.CoherentWall'>, units={}, context=(), data_file=None, omitted=(), fill=()), 'Constant': Factory(name='Constant', target=<class 'solprop.profiles.Constant'>, units={'span': 'm'}, context=(), data_file=None, omitted=(), fill=()), 'EnvelopeGrid.from_limits': Factory(name='EnvelopeGrid.from_limits', target=<bound method EnvelopeGrid.from_limits of <class 'solprop.grid.EnvelopeGrid'>>, units={'length': 'm', 'reference_wavelength': 'm', 'wavelength_limits': 'm', 'trange': 's', 'dt': 's'}, context=(), data_file=None, omitted=(), fill=()), 'EnvelopePlasmaResponse': Factory(name='EnvelopePlasmaResponse', target=<class 'solprop.nonlinear.envelope_plasma.EnvelopePlasmaResponse'>, units={}, context=(), data_file=None, omitted=(), fill=()), 'FieldGrid.from_limits': Factory(name='FieldGrid.from_limits', target=<bound method FieldGrid.from_limits of <class 'solprop.grid.FieldGrid'>>, units={'length': 'm', 'reference_wavelength': 'm', 'wavelength_limits': 'm', 'trange': 's', 'dt': 's'}, context=(), data_file=None, omitted=(), fill=()), 'FixedSchedule': Factory(name='FixedSchedule', target=<class 'solprop.stepper.schedule.FixedSchedule'>, units={'steps': 'm', 'z_start': 'm'}, context=(), data_file=None, omitted=(), fill=()), 'FixedSchedule.uniform': Factory(name='FixedSchedule.uniform', target=<bound method FixedSchedule.uniform of <class 'solprop.stepper.schedule.FixedSchedule'>>, units={'z_start': 'm', 'z_end': 'm', 'dz': 'm', 'save_planes': 'm', 'hard_kinks': 'm'}, context=(), data_file=None, omitted=(), fill=()), 'FreeGrid': Factory(name='FreeGrid', target=<class 'solprop.grid.FreeGrid'>, units={'radius_x': 'm', 'radius_y': 'm'}, context=(), data_file=None, omitted=(), fill=()), 'GaussianPulse': Factory(name='GaussianPulse', target=<class 'solprop.pulses.GaussianPulse'>, units={'wavelength': 'm', 'energy': 'J', 'peak_power': 'W', 'phase': <function phase_unit>, 't0': 's', 'fwhm': 's', 'width': 's'}, context=(), data_file=None, omitted=(), fill=()), 'KerrResponse': Factory(name='KerrResponse', target=<class 'solprop.nonlinear.responses.KerrResponse'>, units={}, context=(), data_file=None, omitted=(), fill=()), 'LineGrid': Factory(name='LineGrid', target=<class 'solprop.grid.LineGrid'>, units={'radius_x': 'm'}, context=(), data_file=None, omitted=(), fill=()), 'Linear': Factory(name='Linear', target=<class 'solprop.profiles.Linear'>, units={'length': 'm'}, context=(), data_file=None, omitted=(), fill=()), 'LowStorageRungeKutta': Factory(name='LowStorageRungeKutta', target=<class 'solprop.stepper.low_storage.LowStorageRungeKutta'>, units={}, context=(), data_file=None, omitted=(), fill=()), 'MarcatiliMode': Factory(name='MarcatiliMode', target=<class 'solprop.modes.capillary.MarcatiliMode'>, units={'radius': 'm', 'phi': 'rad'}, context=(), data_file=None, omitted=('gas', 'pressure', 'temperature', 'susceptibility', 'mixture'), fill=()), 'MaterialSelection': Factory(name='MaterialSelection', target=<class 'solprop.physdata.selection.MaterialSelection'>, units={'carrier_wavelength': 'm'}, context=(), data_file=None, omitted=(), fill=()), 'Mixture.air': Factory(name='Mixture.air', target=<bound method Mixture.air of <class 'solprop.physdata.mixtures.Mixture'>>, units={'pressure': 'bar', 'temperature': 'K', 'floor': 'bar', 'length': 'm', 'radius': 'm'}, context=(), data_file=None, omitted=(), fill=()), 'Mixture.fill': Factory(name='Mixture.fill', target=<bound method Mixture.fill of <class 'solprop.physdata.mixtures.Mixture'>>, units={'pressure': 'bar', 'temperature': 'K', 'floor': 'bar', 'length': 'm', 'radius': 'm'}, context=(), data_file=None, omitted=(), fill=()), 'Mixture.partial_pressures': Factory(name='Mixture.partial_pressures', target=<bound method Mixture.partial_pressures of <class 'solprop.physdata.mixtures.Mixture'>>, units={'temperature': 'K'}, context=(), data_file=None, omitted=(), fill=()), 'ModeCollection.slab': Factory(name='ModeCollection.slab', target=<bound method ModeCollection.slab of <class 'solprop.modes.collection.ModeCollection'>>, units={'half_gap': 'm', 'pressure': 'bar', 'temperature': 'K'}, context=(), data_file=None, omitted=('susceptibility', 'mixture'), fill=('gas', 'pressure', 'temperature')), 'Multistep': Factory(name='Multistep', target=<class 'solprop.stepper.multistep.Multistep'>, units={}, context=(), data_file=None, omitted=(), fill=()), 'OptmatRate': Factory(name='OptmatRate', target=<class 'solprop.nonlinear.optmat_rates.OptmatRate'>, units={'wavelength': 'm', 'negligible_rate': 's^-1', 'maximum': 's^-1'}, context=(), data_file=None, omitted=(), fill=()), 'PIController': Factory(name='PIController', target=<class 'solprop.stepper.controller.PIController'>, units={}, context=(), data_file=None, omitted=('weights', 'lag', 'estimator_order'), fill=()), 'PiecewiseLinear': Factory(name='PiecewiseLinear', target=<class 'solprop.profiles.PiecewiseLinear'>, units={'positions': 'm'}, context=(), data_file=None, omitted=(), fill=()), 'PlanarGrid': Factory(name='PlanarGrid', target=<class 'solprop.modes.slab.PlanarGrid'>, units={'radius_y': 'm'}, context=(), data_file=None, omitted=(), fill=()), 'PlanarPulse': Factory(name='PlanarPulse', target=<class 'solprop.pulses.PlanarPulse'>, units={'waist': 'm', 'propz': 'm', 'displacement': 'm', 'tilt': 'rad', 'waist_x': 'm', 'offset_x': 'm'}, context=(), data_file=None, omitted=(), fill=()), 'PlasmaResponse': Factory(name='PlasmaResponse', target=<class 'solprop.nonlinear.responses.PlasmaResponse'>, units={}, context=(), data_file=None, omitted=(), fill=()), 'PressureGradient.from_stages': Factory(name='PressureGradient.from_stages', target=<bound method PressureGradient.from_stages of <class 'solprop.profiles.PressureGradient'>>, units={'length': 'm', 'start_bar': 'bar', 'end_bar': 'bar', 'floor': 'bar', 'radius': 'm', 'positions': 'm', 'pressures': 'bar'}, context=(), data_file=None, omitted=(), fill=()), 'PressureGradient.two_point': Factory(name='PressureGradient.two_point', target=<bound method PressureGradient.two_point of <class 'solprop.profiles.PressureGradient'>>, units={'length': 'm', 'start_bar': 'bar', 'end_bar': 'bar', 'floor': 'bar', 'radius': 'm', 'positions': 'm', 'pressures': 'bar'}, context=(), data_file=None, omitted=(), fill=()), 'RadialGrid': Factory(name='RadialGrid', target=<class 'solprop.grid.RadialGrid'>, units={'radius': 'm'}, context=(), data_file=None, omitted=(), fill=()), 'RectMode': Factory(name='RectMode', target=<class 'solprop.modes.rectangular.RectMode'>, units={'half_width_x': 'm', 'half_width_y': 'm'}, context=(), data_file=None, omitted=('gas', 'pressure', 'temperature', 'susceptibility', 'mixture'), fill=()), 'RungeKutta': Factory(name='RungeKutta', target=<class 'solprop.stepper.runge_kutta.RungeKutta'>, units={}, context=(), data_file=None, omitted=('tableau',), fill=()), 'SechPulse': Factory(name='SechPulse', target=<class 'solprop.pulses.SechPulse'>, units={'wavelength': 'm', 'energy': 'J', 'peak_power': 'W', 'phase': <function phase_unit>, 't0': 's', 'fwhm': 's', 'width': 's'}, context=(), data_file=None, omitted=(), fill=()), 'SimulationSettings': Factory(name='SimulationSettings', target=<class 'solprop.driver.simulation.SimulationSettings'>, units={'save_planes': 'm', 'dz_max': 'm', 'dz_init': 'm', 'dz_min': 'm', 'evanescent_rate': 'm^-1'}, context=(), data_file=None, omitted=('fields', 'field_planes', 'resume_history', 'auto_init', 'density', 'prefactor_index', 'quadrature', 'components', 'adiabatic_accuracy', 'tdse_execution', '_default_integrator', '_route', '_default_controller'), fill=()), 'SlabMode': Factory(name='SlabMode', target=<class 'solprop.modes.slab.SlabMode'>, units={'half_gap': 'm', 'pressure': 'bar', 'temperature': 'K'}, context=(), data_file=None, omitted=('susceptibility', 'mixture'), fill=('gas', 'pressure', 'temperature')), 'SpatialAbsorber': Factory(name='SpatialAbsorber', target=<class 'solprop.spatial_absorber.SpatialAbsorber'>, units={'kappa': 'rad/m', 'angle': 'rad', 'discard_above': 'rad/m'}, context=(), data_file=None, omitted=(), fill=()), 'SpatialMedium': Factory(name='SpatialMedium', target=<class 'solprop.spatial.SpatialMedium'>, units={'pressure': 'bar', 'temperature': 'K'}, context=(), data_file=None, omitted=('susceptibility',), fill=()), 'SpatialPulse': Factory(name='SpatialPulse', target=<class 'solprop.pulses.SpatialPulse'>, units={'waist': 'm', 'propz': 'm', 'displacement': 'm', 'tilt': 'rad'}, context=(), data_file=None, omitted=(), fill=()), 'StatsSpec': Factory(name='StatsSpec', target=<class 'solprop.stats.StatsSpec'>, units={}, context=(), data_file=None, omitted=(), fill=()), 'TubeLattice': Factory(name='TubeLattice', target=<class 'solprop.modes.antiresonant.TubeLattice'>, units={'wall_thickness': 'm', 'tube_radius': 'm'}, context=(), data_file=None, omitted=(), fill=()), 'absorber': Factory(name='absorber', target=<function absorber>, units={'boundary_length': 'm', 'walkoff': 's'}, context=('grid',), data_file=None, omitted=(), fill=()), 'default_spec': Factory(name='default_spec', target=<function default_spec>, units={}, context=(), data_file=None, omitted=(), fill=()), 'gamma3': Factory(name='gamma3', target=<function gamma3>, units={'wavelength': 'm'}, context=(), data_file=None, omitted=(), fill=()), 'load_spectrum': Factory(name='load_spectrum', target=<function load_spectrum>, units={'energy': 'J'}, context=(), data_file='path', omitted=(), fill=())}#
The types a recipe may name, keyed by the
typeit writes (SEP 41 section 5.1).The documented user-facing types of the
gnlse,capillary,waveguide,radial,freeandplanarroutes. Every keyword of an entry is part of recipe format 1, so the registry starts small: adding an entry later is additive, removing one is not.RungeKuttatakes notableauin a recipe, whose default is the only one the interfaces document. The supplied modes (MarcatiliMode,RectMode,SlabModeandModeCollection.slab) take their geometry, cladding and loss and not their fill, which the route sets; on the planar route a slab mode’s fill is the run’s, so there it names one (Factory.fill). A guide built from a provider has no table form: its knots and node rule are derived from the run’s grid and the provider’s own method.The free-space routes register their grids (
RadialGrid,FreeGrid,LineGrid,PlanarGrid), the medium (SpatialMedium, without a supplied susceptibility), the responses the free-space guide uses (KerrResponse, withgamma3for optmat’s coefficient of a gas,EnvelopePlasmaResponse,PlasmaResponseandOptmatRate), the beams (SpatialPulse,PlanarPulse), their settings (SimulationSettingswithout the execution settings, which are[execution]’s, nor the fields a route’s builder sets;PIControllerwithout its per-bin weights, history lag and estimator order;default_spec) and the transverse boundary (SpatialAbsorber).
- solprop.recipe.registry.UnitSpec = str | collections.abc.Callable[[int], solprop.recipe.quantity.Unit] | None#
A keyword’s unit: one unit string, a rule by element index, or none.
- solprop.recipe.registry.build_object(table, context, path)[source]#
Build the object a table with a
typekey names.- Parameters:
- tablecollections.abc.Mapping
The table:
type, the factory’s keywords and, for a loader,fileandsha256.- contextBuildContext
The recipe’s directory and the route’s grid.
- pathstr
The table’s path.
- Returns:
- object
What the factory returns.
- Raises:
- RecipeError
If the type is not registered, a keyword is not the factory’s, or the factory needs a grid that is not yet built.
Examples
>>> from solprop.recipe.registry import BuildContext, build_object >>> pulse = build_object( ... {"type": "GaussianPulse", "wavelength": "800 nm", "fwhm": "30 fs", ... "energy": "1 mJ"}, ... BuildContext(), ... "pulses[0]", ... ) >>> pulse.fwhm 3e-14
- solprop.recipe.registry.coerce(target, name, value)[source]#
Give a decoded list the container its parameter’s annotation asks for.
TOML has lists only; a parameter typed as a tuple takes a tuple and one typed as an array takes an array, so a value reaches the constructor as a script passes it.
- Parameters:
- targetcallable
The constructor or factory.
- namestr
The parameter.
- valueobject
The decoded value.
- Returns:
- object
value, as a tuple or a float array where the annotation asks for one.
Examples
>>> from solprop.grid import EnvelopeGrid >>> from solprop.recipe.registry import coerce >>> coerce(EnvelopeGrid.from_limits, "wavelength_limits", [4e-7, 2e-6]) (4e-07, 2e-06)
- solprop.recipe.registry.decode(value, unit, context, path)[source]#
Turn one recipe value into the Python value a keyword takes.
- Parameters:
- valueobject
The value as TOML read it.
- unitstr, callable or None
The keyword’s unit (
UnitSpec).- contextBuildContext
The recipe’s directory and the route’s grid.
- pathstr
The value’s parameter path, for errors.
- Returns:
- object
A number in the keyword’s unit, a complex number, an array, an object, a list of these, or the value as it stands.
Examples
>>> from solprop.recipe.registry import BuildContext, decode >>> decode("800 nm", "m", BuildContext(), "wavelength") 8e-07 >>> decode({"re": 1.45, "im": 0.0}, None, BuildContext(), "cladding") (1.45+0j)
- solprop.recipe.registry.decode_keyword(entry, value, context)[source]#
Turn the value of one build keyword into what the constructor takes.
- Parameters:
- entryParameter
The keyword’s metadata.
- valueobject
The value as TOML read it.
- contextBuildContext
The recipe’s directory and the route’s grid.
- Returns:
- object
The decoded value;
Nonefor"none"where the keyword has the spelling.
- Raises:
- RecipeError
If the keyword’s forms cannot hold the value in a recipe.
Examples
>>> from solprop.recipe.registry import BuildContext, decode_keyword >>> from solprop.recipe.metadata import parameters >>> table = parameters("capillary") >>> decode_keyword(table["pressure"], ["0 bar", "1.2 bar"], BuildContext()) [0.0, 1.2] >>> decode_keyword(table["noise"], "none", BuildContext()) is None True