solprop.recipe.quantity#

Quantities in a recipe: numbers with units, read and written back exactly.

A recipe value is either a bare number, taken in the keyword’s own unit, or a quantity string such as "125 um", "1.2 bar" or "2e14 W/cm^2", converted to that unit. The keyword’s unit is the one its docstring states, so pressures stay in bar (docs/dev/conventions.md) and a bare 1.2 for a pressure means 1.2 bar.

The unit grammar. A unit is a product of factors, with at most one solidus: a numerator of factors joined by * or · (or the single factor 1), then optionally / and one factor or a parenthesised product, as the SI brochure writes it (W/cm^2, fs^2/mm, J/(m*s)). a/b/c and a/b*c are refused as ambiguous. A factor is an optional SI prefix (q to Q; u, µ and μ all read as micro), a symbol and an optional integer exponent ^n or ^-n. The symbols are m, s, g, Hz, J, W, Pa, bar, K, rad and deg. Temperature is in kelvin only: there is no Celsius or Fahrenheit. A whitespace between the number and the unit is optional ("800nm" is read).

Angles are a dimension. Plane angle is tracked as a fifth base dimension beside length, time, mass and temperature, so an angular frequency in rad/s is never confused with a frequency in Hz (a factor of 2π). A consequence is that rad is written only where the keyword’s unit is an angle.

Exact conversion. The number is read as a decimal, multiplied by the ratio of the two units’ factors exactly in decimal, and rounded once to the nearest binary64 value, so "800 nm" gives the double of the literal 800e-9 that a script writes. Every unit but deg is a decimal multiple of an SI unit, so the ratio only shifts the decimal exponent. deg multiplies by π/180, which has no finite decimal; it is carried to 70 significant digits, so the one rounding to binary64 gives the double nearest the exact angle unless the exact value lies within 10⁻⁷⁰ (relative) of a tie, which no recipe value does. deg therefore stands alone: it takes no prefix, no exponent and no other factor.

Writing back. format_quantity() writes a double in a display unit with the fewest digits that read back to the same double. For a decimal display unit this is the shortest round-tripping representation of the double (Python’s repr()) with its decimal point shifted, which is always exact; for deg it is the fewest of up to 17 significant digits that read back, which always suffice.

Module Attributes

ElementUnits

The units of an array keyword whose elements differ, as a function of the index.

Functions

beta_unit(order)

Return the unit of element order of a betas list.

format_quantity(value, unit, display)

Write a value in unit as a quantity string in the display unit.

parse_quantity(value, unit, *[, path])

Read a recipe value given as a number or a quantity string, in unit.

phase_unit(order)

Return the unit of element order of a phases list.

Classes

Dimension([length, time, mass, temperature, ...])

A physical dimension as integer exponents of five base dimensions.

Unit(text)

The unit a keyword, or an element of one, is given in.

class solprop.recipe.quantity.Dimension(length=0, time=0, mass=0, temperature=0, angle=0)[source]#

Bases: object

A physical dimension as integer exponents of five base dimensions.

Attributes:
lengthint

Exponent of length (m).

timeint

Exponent of time (s).

massint

Exponent of mass (kg).

temperatureint

Exponent of thermodynamic temperature (K).

angleint

Exponent of plane angle (rad), kept apart so that rad/s and Hz differ.

Examples

>>> pressure = Dimension(length=-1, time=-2, mass=1)
>>> str(pressure)
'pressure (kg m^-1 s^-2)'
>>> str(Dimension(length=1) * Dimension(length=1))
'area (m^2)'
angle: int = 0#
length: int = 0#
mass: int = 0#
temperature: int = 0#
time: int = 0#
type solprop.recipe.quantity.ElementUnits = Callable[[int], Unit]#

The units of an array keyword whose elements differ, as a function of the index.

class solprop.recipe.quantity.Unit(text)[source]#

Bases: object

The unit a keyword, or an element of one, is given in.

A bare number for the keyword is taken in this unit, and every quantity string is converted to it. It is a decimal multiple of an SI unit, usually the coherent one ("m", "s^2/m") but "bar" for a pressure.

Attributes:
textstr

The unit in the grammar of the module docstring, in ASCII, or "1" for a dimensionless keyword. Two units are equal when their texts are.

Raises:
RecipeError

If text cannot be read, or is deg (a keyword’s unit is rad).

Examples

>>> Unit("bar").dimension
Dimension(length=-1, time=-2, mass=1, temperature=0, angle=0)
>>> str(Unit("s^2/m").dimension)
'm^-1 s^2'
property dimension: Dimension[source]#

The unit’s dimension.

Returns:
Dimension

The exponents of the five base dimensions.

text: str#
solprop.recipe.quantity.beta_unit(order)[source]#

Return the unit of element order of a betas list.

The propagation constant’s Taylor coefficients β_n = ∂ⁿβ/∂ωⁿ are in sⁿ/m.

Parameters:
orderint

The Taylor order n, at least 0.

Returns:
Unit

1/m for order 0, s/m for order 1 and s^n/m after.

Raises:
RecipeError

If order is negative.

Examples

>>> [beta_unit(n).text for n in range(4)]
['1/m', 's/m', 's^2/m', 's^3/m']
solprop.recipe.quantity.format_quantity(value, unit, display)[source]#

Write a value in unit as a quantity string in the display unit.

The number has the fewest significant digits that read back, through parse_quantity(), to exactly value, the sign of a zero included.

Parameters:
valuefloat

The value in unit; finite.

unitUnit

The keyword’s unit.

displaystr

The unit to write in, of the same dimension, in ASCII by convention ("um").

Returns:
str

A quantity string such as "125 um".

Raises:
RecipeError

If value is not finite, or display cannot be read or is of another dimension.

Examples

>>> format_quantity(125e-6, Unit("m"), "um")
'125 um'
>>> format_quantity(7.5e-15, Unit("s"), "fs")
'7.5 fs'
>>> format_quantity(1.2, Unit("bar"), "kPa")
'120 kPa'
solprop.recipe.quantity.parse_quantity(value, unit, *, path=None)[source]#

Read a recipe value given as a number or a quantity string, in unit.

Parameters:
valueobject

An int or float, taken in unit, or a string of a decimal number and a unit ("125 um", "2e14 W/cm^2"), whose dimension must be the unit’s. A string with no unit is read only for a dimensionless unit.

unitUnit

The keyword’s unit.

pathstr or None, optional

The parameter path, for the error message.

Returns:
float

The value in unit: the double nearest the exact decimal value.

Raises:
RecipeError

If value is a boolean, not finite, not a number or quantity string, or of another dimension, if its unit cannot be read or has two readings, or if the value overflows or underflows a double.

Examples

>>> parse_quantity("800 nm", Unit("m")) == 800e-9
True
>>> parse_quantity("120 kPa", Unit("bar"))
1.2
>>> parse_quantity(1.2, Unit("bar"))
1.2
>>> parse_quantity("2e14 W/cm^2", Unit("W/m^2"))
2e+18
solprop.recipe.quantity.phase_unit(order)[source]#

Return the unit of element order of a phases list.

The spectral phase is the Taylor series Σ φ_n (ω - ω₀)ⁿ / n!, so φ_0 is an angle and φ_n for n ≥ 1 is in sⁿ (the radian of the phase is not carried into the higher orders, as is usual for dispersion coefficients).

Parameters:
orderint

The Taylor order n, at least 0.

Returns:
Unit

rad for order 0, s for order 1 and s^n after.

Raises:
RecipeError

If order is negative.

Examples

>>> [phase_unit(n).text for n in range(4)]
['rad', 's', 's^2', 's^3']