solprop.recipe.core#

Recipes: a simulation as versioned TOML, read, built, run and saved (SEP 41, S1).

A recipe is read, checked against the parameter metadata, built into a Simulation, run, written back and exported as a plain Python script. It is one-way: objects are built from it and never turned back into tables, so a saved recipe always comes from a recipe or from plain values (Recipe.from_keywords()).

Module Attributes

ROUTES

The routes a recipe of format 1 describes (SEP 41).

Functions

resume_file(path[, mode, node_budget, ...])

Continue a run from its output file alone, rebuilding it from its recipe.

Classes

Recipe(document, *[, text, base, allow_outside])

A simulation written as TOML: read, checked, built, run, saved and exported.

RecipeBuilder(text, base, allow_outside)

Build one scan point's simulation from a recipe; picklable for pool executors.

RecipeIssue(message, parameter, severity[, rule])

One problem Recipe.check() found, placed at the parameter it concerns.

RecipeScan(scan, build, keywords)

A recipe's scan, ready for run_scan().

solprop.recipe.core.ROUTES: Final = ('gnlse', 'capillary', 'waveguide', 'radial', 'free', 'planar')#

The routes a recipe of format 1 describes (SEP 41).

The keyword routes gnlse, capillary and waveguide, and the object routes (OBJECT_ROUTES), whose keywords are tables of grids, medium, responses, beam and settings.

class solprop.recipe.core.Recipe(document, *, text=None, base=None, allow_outside=False)[source]#

Bases: object

A simulation written as TOML: read, checked, built, run, saved and exported.

Construct one with load(), loads(), from_dict(), from_keywords() or example(), not directly.

Parameters:
documentcollections.abc.Mapping

The recipe’s tables, as tomllib.loads() reads them.

textstr or None, optional

The text it was read from, kept so that an unedited recipe saves verbatim.

basepathlib.Path or None, optional

The directory its data files resolve against.

allow_outsidebool, optional

Whether a data file may lie outside base.

Attributes:
routestr

The route the recipe builds.

Examples

>>> from solprop.recipe import Recipe
>>> recipe = Recipe.loads('''
... [recipe]
... format = 1
... route = "gnlse"
...
... [build]
... gamma = 0.11
... length = "1 cm"
... betas = [0, 0, "-0.01183 ps^2/m"]
... wavelength = "835 nm"
... wavelength_limits = ["500 nm", "2 um"]
... trange = "1 ps"
... width = "100 fs"
... peak_power = "9.8 W"
... shape = "sech"
... noise = "none"
... ''')
>>> recipe.route, recipe.get("length")
('gnlse', '1 cm')
>>> recipe.set("length", "2 cm")
>>> recipe.get("length")
'2 cm'
build()[source]#

Build the simulation the recipe describes, without running it.

Pins are solved first (resolve()).

Returns:
solprop.driver.simulation.Simulation

The simulation, with [execution]’s settings applied, carrying this recipe, which its first run records in its output.

check()[source]#

Find what stops the recipe building, or makes it warn (SEP 41, S10).

Every value is decoded against the metadata first, each problem reported at its path. If none is refused, the simulation is built and translated, which is where the refusals that depend on several values are found, stopping before a backend is constructed; the first refusal is reported with its parameter, and every warning of solprop’s with its own. It costs a translation: call it on a pause in typing, not on every keystroke.

Returns:
list of RecipeIssue

The issues, errors first; empty when the recipe builds cleanly.

classmethod example(name)[source]#

Load one of the example recipes solprop ships, each a gallery example’s.

Parameters:
namestr

The example’s name, one of examples().

Returns:
Recipe

The recipe.

Raises:
RecipeError

If no example has that name.

classmethod examples()[source]#

Return the names of the example recipes solprop ships.

Returns:
tuple of str

The names example() takes, sorted.

Examples

>>> from solprop.recipe import Recipe
>>> "rdw" in Recipe.examples()
True
classmethod from_dict(document, *, base=None)[source]#

Build a recipe from its tables.

Parameters:
documentcollections.abc.Mapping

The tables, as TOML would read them.

basepathlib.Path or None, optional

The directory its data files resolve against.

Returns:
Recipe

The recipe.

classmethod from_keywords(route, *, title=None, **keywords)[source]#

Write a route’s keyword call as a recipe, from plain values only.

Parameters:
routestr

The route, one of ROUTES.

titlestr or None, optional

The recipe’s title.

**keywordsobject

The route’s build keywords, as numbers in their SI unit (pressure in bar), strings, booleans, and lists and mappings of these.

Returns:
Recipe

The recipe.

Raises:
RecipeError

If a value is an object or a callable, which a recipe holds only as a table with a type key, or through the Python export.

Examples

>>> from solprop.recipe import Recipe
>>> recipe = Recipe.from_keywords(
...     "capillary", radius=125e-6, length=1.0, gas="He", pressure=1.2,
...     wavelength=800e-9, fwhm=7.5e-15, energy=275e-6,
... )
>>> recipe.get("radius")
0.000125
classmethod from_output(path, *, resolved=False)[source]#

Read back the recipe a run’s output records (SEP 41, S2).

Parameters:
pathstr or pathlib.Path

The HDF5 output of a run, or a scan’s file, which records the authored recipe only.

resolvedbool, optional

Read the resolved recipe, which rebuilds the run as it ran, rather than the authored one, for editing.

Returns:
Recipe

The recipe, holding the data files the output embedded.

Raises:
RecipeError

If the file records no recipe, being a file from a script, or its recipe is of a newer format.

get(path)[source]#

Return a value of the [build] table as the recipe writes it.

Parameters:
pathstr

A parameter path, as "pressure" or "pulses[1].energy".

Returns:
object

The value as written: a number, a quantity string, a list or a table.

keywords(*, grid=None)[source]#

Return the route’s build keywords as the constructor takes them.

Parameters:
gridsolprop.grid.TimeGrid or None, optional

The route’s grid, for a value built on it; None leaves such values out.

Returns:
dict

Keyword arguments for the route’s Simulation.from_*.

classmethod load(path, *, allow_outside=False)[source]#

Read a recipe file.

Parameters:
pathstr or pathlib.Path

The .toml file.

allow_outsidebool, optional

Whether a data file it refers to may lie outside its directory.

Returns:
Recipe

The recipe, whose data files resolve against the file’s directory.

classmethod loads(text, *, base=None, allow_outside=False)[source]#

Read a recipe from TOML text.

Parameters:
textstr

The recipe.

basepathlib.Path or None, optional

The directory its data files resolve against; None allows none.

allow_outsidebool, optional

Whether a data file may lie outside base.

Returns:
Recipe

The recipe, which saves as text until it is edited.

modes(z=None)[source]#

Return the mode set a guided route would build, before the run (S18).

Labels, the effective index, beta to beta3, loss, effective area and nonlinear coefficient over the grid’s band, and the zero-dispersion wavelength; pins are solved first. The cost is the mode solve (solprop.recipe.preview.modes()).

Parameters:
zfloat or None, optional

The position, m; None for the launch position.

Returns:
solprop.recipe.preview.ModeSetPreview

The modes.

Examples

>>> from solprop.recipe import Recipe
>>> preview = Recipe.example("rdw").modes()
>>> [mode.label for mode in preview.modes]
['HE1,1:even', 'HE1,2:even']
pin_roots(path)[source]#

Return every root of one pin’s target, for a front end to choose among.

A pin on a pulse reads the guide as its own pin (if any) settles it.

Parameters:
pathstr

The pinned path, as [pins] writes it.

Returns:
solprop.tools.DesignRoots

The roots over the pin’s search range, or none with the attainable range.

Raises:
RecipeError

If the path is not pinned, or a pin does not read.

preview_input()[source]#

Return the input pulse on the run’s grid, as launched, without noise (S18).

Pins are solved first; the cost is a translation (solprop.recipe.preview.preview_input()).

Returns:
solprop.recipe.preview.InputPreview

The pulse in time and frequency, its energy and its peak power.

Examples

>>> from solprop.recipe import Recipe
>>> preview = Recipe.example("rdw").preview_input()
>>> f"{preview.energy * 1e6:.1f} uJ"
'275.0 uJ'
record(simulation)[source]#

Return the record a run built from this recipe keeps in its output.

Called by run() at the run’s start, with the settings it starts with.

Parameters:
simulationsolprop.driver.simulation.Simulation

The simulation this recipe built.

Returns:
solprop.output.schema.RecipeRecord

The authored and resolved texts, and the data files (solprop.recipe.provenance).

resolve()[source]#

Return the recipe with each pin replaced by its solved value.

The pin on the guide or fill is solved first, on the launch mode at the launch position; the pins on pulses then read the mode it settled (solprop.recipe.pins). A run of a pinned recipe records both texts: the authored one with its pins, and the resolved one.

Returns:
Recipe

A recipe without [pins], its pinned paths set in [build] as numbers in their keywords’ units; a copy of this one when it has no pins.

Raises:
RecipeError

On the pinned path, if a pin does not read, or its target is not met in its search range (naming the attainable range).

Examples

>>> from solprop.recipe import Recipe
>>> recipe = Recipe.example("soliton_self_compression")
>>> document = recipe.to_dict()
>>> del document["build"]["energy"]
>>> document["pins"] = {"energy": {"target": "soliton_order", "order": 4}}
>>> pinned = Recipe.from_dict(document)
>>> f"{pinned.resolve().get('energy') * 1e6:.1f} uJ"
'126.1 uJ'
run(output=None, **run_keywords)[source]#

Build the simulation and run it, with [execution] applied.

Parameters:
outputstr, pathlib.Path, Output or None, optional

Where to write, as run() takes it; None keeps the run in memory.

**run_keywordsobject

Further keywords of run(), such as progress or resume.

Returns:
solprop.output.schema.Output

The run’s output.

save(path)[source]#

Write the recipe to a file.

A recipe read back from a run’s output (from_output()) writes the data files the output embedded beside it, under the generated names they were filed by, and refers to them by those names; a file the output only referred to stays a reference, which check() reports when it is missing.

Parameters:
pathstr or pathlib.Path

The .toml file to write.

scan()[source]#

Return the scan the [scan] table declares, ready for run_scan.

[scan] requires name, which names the durable files and derives the points’ seeds, and may give base_seed; its other keys are parameter paths, each with a list of values or {start, stop, num, spacing}, spacing "linear" (the default) or "log". Values are read in the unit of the keyword each path ends on.

Returns:
RecipeScan

The Scan, a picklable builder that sets each point’s values, passes point.seed and builds, and the keywords run_scan() takes from [execution].

Raises:
RecipeError

If the recipe has no [scan] table, its name is missing, or a path or a value does not read.

Examples

>>> from solprop.recipe import Recipe
>>> recipe = Recipe.example("soliton")
>>> document = recipe.to_dict()
>>> document["scan"] = {"name": "power", "peak_power": ["5 W", "10 W"]}
>>> scan = Recipe.from_dict(document).scan()
>>> scan.scan.shape, scan.scan.variables["peak_power"].tolist()
((2,), [5.0, 10.0])
set(path, value)[source]#

Set a value of the [build] table, checked against the metadata.

Parameters:
pathstr

A parameter path; the keyword it starts with must be the route’s.

valueobject

A number in the keyword’s unit, a quantity string, a boolean, a string, or a list or table of these.

Raises:
RecipeError

If the keyword is not the route’s, or the value does not decode.

property title: str | None[source]#

Return the recipe’s title.

Returns:
str or None

The [recipe] table’s title, or None.

to_dict()[source]#

Return a copy of the recipe’s tables.

Returns:
dict

The five tables that are present, as TOML would read them.

to_python(output=None)[source]#

Return a plain Python script that makes the same run.

The route’s prop_* call when every key is on its surface, otherwise Simulation.from_*, the settings and run: keyword arguments in SI, with a comment per keyword stating the recipe’s value where it was a quantity.

Parameters:
outputstr or None, optional

The file the script’s run writes; None keeps it in memory.

Returns:
str

The script.

to_text()[source]#

Return the recipe’s TOML text.

Returns:
str

The text it was read from while it is unedited, comments included; otherwise canonical TOML, each quantity in its keyword’s display unit.

class solprop.recipe.core.RecipeBuilder(text, base, allow_outside)[source]#

Bases: object

Build one scan point’s simulation from a recipe; picklable for pool executors.

Attributes:
textstr

The recipe, without its [scan] and [execution] tables.

basestr or None

Its directory, for data files.

allow_outsidebool

Whether a data file may lie outside it.

allow_outside: bool#
base: str | None#
text: str#
class solprop.recipe.core.RecipeIssue(message, parameter, severity, rule=None)[source]#

Bases: object

One problem Recipe.check() found, placed at the parameter it concerns.

Attributes:
messagestr

What is wrong, in the words of the refusal or warning.

parameterstr or tuple of str or None

The path of the value at fault, or the paths of a conflict; None when the issue concerns no single value.

severity{‘error’, ‘warning’}

Whether the recipe cannot be built, or builds with a warning.

rulestr or None

The identifier of the combination rule a refusal enforces, where it is one.

Examples

>>> from solprop.recipe import RecipeIssue
>>> RecipeIssue("must be positive", "pressure", "error").severity
'error'
message: str#
parameter: str | tuple[str, ...] | None#
rule: str | None = None#
severity: Literal['error', 'warning']#
class solprop.recipe.core.RecipeScan(scan, build, keywords)[source]#

Bases: object

A recipe’s scan, ready for run_scan().

Attributes:
scansolprop.driver.scan.Scan

The points.

buildcallable

The picklable builder of each point’s simulation.

keywordsdict

The run_scan keywords: fields and field_planes from the recipe’s [execution], which run_scan takes itself, and recipe, which the scan file records.

Examples

run_scan(scan.scan, scan.build, output="scan.h5", **scan.keywords) runs it.

build: RecipeBuilder#
keywords: dict[str, object]#
scan: Scan#
solprop.recipe.core.resume_file(path, mode=True, *, node_budget=None, progress=None, stop=None)[source]#

Continue a run from its output file alone, rebuilding it from its recipe.

The simulation is rebuilt from the resolved recipe the file records (SEP 41, S2) and run into the same file with resume=mode, so the resume gate decides by the hashes of the stored and rebuilt records, as for any resume (ADR-066). A file written from a script records no recipe; its script resumes it.

Resuming a file runs the setup it holds. A file received from someone else does not choose its own limit: the recipe’s node_budget is ignored, and the caller’s applies.

Parameters:
pathstr or pathlib.Path

The output file.

modebool or {‘interpolated’}, optional

As run()’s resume takes it.

node_budgetint or None, optional

The node-buffer budget of a capillary run; None takes solprop’s default.

progressobject, optional

Where progress goes, as run() takes it.

stopobject, optional

The run’s stop flag, any object with an is_set() method.

Returns:
solprop.output.schema.Output

The handler the run continued in.

Raises:
RecipeError

If the file records no recipe, or one of a newer format.