Python API¶
noodlelab.verify¶
Verifiable calculations in plain Python: units, uncertainty, requirements, checks and an audit trail, for people and for AI agents writing code.
This is noodlelab’s science without the editor. Everything here works in any
script, notebook or test after pip install noodlelab:
import noodlelab.verify as nv
with nv.record("pendulum") as rec: # writes runs/<...>/provenance.json
L = rec.input("L", "1.000 ± 0.002 m", source="tape measure, lab book p. 12")
g = rec.input("g", "9.81 ± 0.02 m/s^2", source="local gravity survey")
T = rec.result("period", nv.const.tau * (L / g) ** 0.5) # (2.006 ± 0.003) s
rec.require("PER-001 period <= 2.1 s [Analysis] # The swing shall take at most 2.1 s")
rec.verify("PER-001", T) # ✓ margin +0.094 s
assert rec.passed
The rules it helps you keep (and audit() checks afterwards):
Every number has a unit. Values are Pint quantities; mixing dimensions raises instead of silently giving nonsense. Dimensionless results say so (
unit="1"). Constants are named, never retyped:nv.const.c,rec.constant("g0")(seenoodlelab.constants), with their unit, their source and, for measured ones such asG, their CODATA uncertainty.Every measured input has an uncertainty and a source. Uncertainty is propagated by the GUM’s law (first order, with correlations kept), and
budget()says which input contributes most.monte_carlo()checks the linear result where the model is not linear (JCGM 101).Requirements are written down before they are checked, as text a person can read (
COM-001 link_margin >= 3 dB [Analysis]), and each check reports its margin, not just pass or fail. An uncertain result whose margin is no larger than its expanded uncertainty U = 2u is inconclusive, and does not pass: the design may meet the requirement, but the calculation cannot show it.Every run leaves a record: inputs, results, requirements, checks, the code (its hash and git commit), the files read and written (SHA-256) and the environment (Python, platform, package versions), so someone else can see exactly what was computed and repeat it.
noodlelab verify script.py runs a script, audits every record it wrote and
exits non-zero when a check fails or is inconclusive, for CI and for agents checking their own
work. Graphs from the editor are verified the same way (noodlelab verify
analysis.graph.json).
- class noodlelab.verify.Check(passed: 'bool', message: 'str' = '', requirement: 'str' = '', statement: 'str' = '', method: 'str' = '', required: 'str' = '', achieved: 'str' = '', margin: 'float | None' = None, unit: 'str' = '', margin_pct: 'float | None' = None, uncertainty: 'float | None' = None, inconclusive: 'bool' = False)[source]¶
- Parameters:
passed (bool)
message (str)
requirement (str)
statement (str)
method (str)
required (str)
achieved (str)
margin (float | None)
unit (str)
margin_pct (float | None)
uncertainty (float | None)
inconclusive (bool)
- passed: bool¶
- message: str = ''¶
- requirement: str = ''¶
- statement: str = ''¶
- method: str = ''¶
- required: str = ''¶
- achieved: str = ''¶
- margin: float | None = None¶
- unit: str = ''¶
- margin_pct: float | None = None¶
- uncertainty: float | None = None¶
- inconclusive: bool = False¶
- property status: str¶
"passed","failed"or"inconclusive".
- class noodlelab.verify.Finding(code, level, message, where='')[source]¶
Something
audit()found in a record.- Parameters:
code (str)
level (Literal['error', 'warning', 'info'])
message (str)
where (str)
- code: str¶
- level: Literal['error', 'warning', 'info']¶
- message: str¶
- where: str = ''¶
- class noodlelab.verify.MonteCarlo(mean, std, low, high, p, trials, unit, gum, agrees, message)[source]¶
A Monte Carlo evaluation (JCGM 101) of a model, next to its GUM result.
- Parameters:
mean (float)
std (float)
low (float)
high (float)
p (float)
trials (int)
unit (str)
gum (Any)
agrees (bool)
message (str)
- mean: float¶
- std: float¶
- low: float¶
- high: float¶
- p: float¶
- trials: int¶
- unit: str¶
- gum: Any¶
- agrees: bool¶
- message: str¶
- property inconclusive: bool¶
Too few trials to tell (the message says how many would).
- class noodlelab.verify.Quantity(value, unit=None)[source]¶
A Pint quantity as a type hint:
Quantity["m/s"]for a speed,Quantityfor any quantity.Quantity(9.81, "m/s^2")makes one, andisinstance(x, Quantity)is true for every Pint quantity.- Parameters:
value (Any)
unit (str | None)
- Return type:
Any
- class noodlelab.verify.Record(name, *, out=None, write=True, _caller=None)[source]¶
The audit trail of one calculation. See
record().- Parameters:
name (str)
out (str | Path | None)
write (bool)
_caller (str | None)
- status: str¶
- error: str | None¶
- inputs: dict[str, dict[str, Any]]¶
- results: dict[str, dict[str, Any]]¶
- calls: list[dict[str, Any]]¶
- files: dict[str, list[dict[str, Any]]]¶
- notes: list[str]¶
- path: Path | None¶
- close()[source]¶
Finish the record and write it (done on leaving the
withblock).- Return type:
Path | None
- input(name, value, *, unit='', source='', note='')[source]¶
A value the calculation starts from:
"9.81 ± 0.02 m/s^2", ameasure`d or :func:`q()value, or a plain number withunit. Name itssource(instrument, dataset, paper, datasheet): the audit asks for one. Measured inputs are labellednamein uncertainty budgets. Returns the value to compute with.- Parameters:
name (str)
value (Any)
unit (str)
source (str)
note (str)
- Return type:
Any
- constant(name, *, label='')[source]¶
A named constant as an input (
rec.constant("g0")), recorded underlabel(default: its name) with its source, so the audit needs no more. Returns the value to compute with.- Parameters:
name (str)
label (str)
- Return type:
Any
- result(name, value, *, unit='', exact=False, note='')[source]¶
A result of the calculation, recorded with its unit, uncertainty and budget. Converted to
unitwhen given.exact=Truesays it has no uncertainty on purpose (a count, a definition), which the audit then accepts. Returns the value.- Parameters:
name (str)
value (Any)
unit (str)
exact (bool)
note (str)
- Return type:
Any
- require(spec)[source]¶
Write down requirements (text, one per line, or parsed ones) before checking them; each should be verified before the record closes.
- Parameters:
spec (str | Requirement | RequirementSet)
- Return type:
- verify(req, value)[source]¶
Check a result against a requirement: its id (given with
require()), aRequirement, or a line of text.- Parameters:
req (str | Requirement)
value (Any)
- Return type:
- expect(condition, message)[source]¶
A check that is not a requirement: a sanity bound, a conservation law, agreement with a reference.
conditionis truthy when it holds.- Parameters:
condition (Any)
message (str)
- Return type:
- close_to(name, value, reference, *, rtol=0.0, atol=0.0, k=2.0)[source]¶
Check
valueagrees withreference(a textbook value, another method, an earlier result): withinrtol/atolwhen given, else within k times their combined standard uncertainty (En ≤ 1 at k = 2).Quantities are compared in the reference’s unit, so 20 degC and 293.15 K agree. With a temperature in degC or degF,
atolis a difference (0.5 Kor0.5 delta_degC;0.5 degCis read as one too) andrtolis relative to the absolute temperature.- Parameters:
name (str)
value (Any)
reference (Any)
rtol (float)
atol (Any)
- Return type:
- read(path)[source]¶
Note a file the calculation reads (its SHA-256 goes in the record).
- Parameters:
path (str | Path)
- Return type:
Path
- output(name)[source]¶
A path in this record’s folder to write an output to (a plot, a table); its SHA-256 is recorded when the record closes.
- Parameters:
name (str)
- Return type:
Path
- wrote(path)[source]¶
Note a file the calculation wrote outside the record’s folder.
- Parameters:
path (str | Path)
- Return type:
Path
- note(text)[source]¶
A remark for the reader: an assumption, a simplification, a caveat.
- Parameters:
text (str)
- Return type:
None
- property passed: bool¶
Every check passed, every requirement written down was verified, and the block did not raise.
- property unverified: list[str]¶
Requirements written down but never checked.
- class noodlelab.verify.Requirement(id: 'str', quantity: 'str', op: 'Op', limit: 'float', unit: 'str' = '', upper: 'float | None' = None, tolerance: 'float' = 0.0, text: 'str' = '', method: 'str' = 'Analysis', priority: 'str' = '', parent: 'str' = '')[source]¶
- Parameters:
id (str)
quantity (str)
op (Literal['>=', '<=', '>', '<', '==', 'between'])
limit (float)
unit (str)
upper (float | None)
tolerance (float)
text (str)
method (str)
priority (str)
parent (str)
- id: str¶
- quantity: str¶
- op: Literal['>=', '<=', '>', '<', '==', 'between']¶
- limit: float¶
- unit: str = ''¶
- upper: float | None = None¶
- tolerance: float = 0.0¶
- text: str = ''¶
- method: str = 'Analysis'¶
- priority: str = ''¶
- parent: str = ''¶
- property required: str¶
“≥ 3 dB”, “-20 to 60 °C”.
- Type:
The requirement as a short phrase
- property value: Any¶
a quantity when it has a unit (the lower limit of a range).
- Type:
The limit as a value for the graph
- magnitude(value)[source]¶
valueas plain numbers in this requirement’s unit.- Parameters:
value (Any)
- Return type:
Any
- meets(margin)[source]¶
Whether a margin from
margins()meets the requirement: a value exactly at the limit meets>=(margin 0) but not>. Element-wise on arrays.- Parameters:
margin (Any)
- Return type:
Any
- margins(value)[source]¶
How far inside the limits each value is, in the requirement’s unit (negative: outside; zero: at the limit, see
meets()). Works element-wise on arrays and columns.- Parameters:
value (Any)
- Return type:
Any
- verify(value)[source]¶
Compare a result with the requirement. An array passes when every element does; its margin is the smallest (the worst case).
An uncertain value is judged with its expanded uncertainty U = 2u (k = 2, about 95 %): it fails when its nominal value misses, passes when the nominal value is inside the limit by more than U, and is otherwise inconclusive (not passed): the design may meet the requirement, but the calculation cannot show it. An exact value is judged on its value alone, as it always was.
- Parameters:
value (Any)
- Return type:
- class noodlelab.verify.RequirementSet(items=())[source]¶
Requirements by id, in the order they were given.
- Parameters:
items (tuple[Requirement, ...])
- items: tuple[Requirement, ...] = ()¶
- property ids: list[str]¶
- merged(other)[source]¶
- Parameters:
other (RequirementSet)
- Return type:
- class noodlelab.verify.Uncertain(value, uncertainty, unit='', name='')[source]¶
A value with a standard uncertainty, as a type hint:
Uncertainfor any,Uncertain["m"]for a length.Uncertain(9.81, 0.02, "m/s^2")makes one.- Parameters:
value (Any)
uncertainty (float)
unit (str)
name (str)
- Return type:
Any
- class noodlelab.verify.Verifications(checks=())[source]¶
Checks of requirements, collected into a compliance matrix (one entry per requirement: verifying it again replaces the earlier entry).
- Parameters:
checks (tuple[Check, ...])
- property passed: bool¶
- noodlelab.verify.audit(rec)[source]¶
Check a record against the rules of a verifiable calculation (see
RULES): failed or missing checks, results without units or uncertainty, inputs without a source, code that was not committed or has changed since. Takes aRecord, its data, or its file.
- noodlelab.verify.budget(value)[source]¶
[(input, contribution, share of variance), ...], largest first: which named inputs the uncertainty ofvaluecomes from.- Parameters:
value (Any)
- Return type:
list[tuple[str, float, float]]
- noodlelab.verify.constant(name)[source]¶
A named constant with its unit:
constant("c"),constant("g0"). Measured ones (G,m_e…) carry their CODATA uncertainty. The same asnv.const.c; add your own withdefine_constant().- Parameters:
name (str)
- Return type:
Any
- noodlelab.verify.current()[source]¶
The record being written (inside
with record(...)), or None.- Return type:
Record | None
- noodlelab.verify.define_constant(name, value, unit='', *, uncertainty=0.0, title='', source='', symbol='', override=False)¶
Add a constant for every graph and script in this process:
define("g_local", 9.8123, "m/s^2", uncertainty=0.0005, source="survey 2024") define("rho_water", "998.2 kg/m^3", title="density of water at 20 °C")
Replacing a built-in constant warns, unless
override=Truesays it is meant.pi,tauandecannot be replaced.- Parameters:
name (str)
value (Any)
unit (str)
uncertainty (float)
title (str)
source (str)
symbol (str)
override (bool)
- Return type:
- noodlelab.verify.finished()[source]¶
Every record finished in this process, oldest first.
- Return type:
list[Record]
- noodlelab.verify.fmt(value, k=1.0)[source]¶
A value for people:
(2.006 ± 0.003) s(GUM rounding),3 dB,0.5.k: coverage factor for an expanded uncertainty.- Parameters:
value (Any)
k (float)
- Return type:
str
- noodlelab.verify.load(path)[source]¶
A record from its
provenance.json(or the folder holding it).- Parameters:
path (str | Path)
- Return type:
dict[str, Any]
- noodlelab.verify.load_constants(path)¶
define()every constant in aconstants.tomlfile. Raises ConstantsError listing every problem, since a script should stop on them.- Parameters:
path (str | Path)
- Return type:
dict[str, Constant]
- noodlelab.verify.measure(value, u=None, unit='', *, name='', distribution='normal', dof=None)[source]¶
A measured value with its standard uncertainty:
measure("9.81 ± 0.02 m/s^2"),measure("9.81(2) m/s^2")measure(9.81, 0.02, "m/s^2")measure(q("9.81 m/s^2"), 0.02)
namelabels it inbudget().distribution(anddoffor Student’s t) is whatmonte_carlo()samples;uis always the GUM standard uncertainty (for a rectangular distribution of half-width a, give a/√3; for the mean of n readings with spread s, s/√n withdof= n - 1, which is the scale of the t distribution sampled, JCGM 101 6.4.9). An unknown distribution, or t withoutdof, is refused. Inside amonte_carlo()model this returns one draw instead.- Parameters:
value (Any)
u (float | None)
unit (str)
name (str)
distribution (Literal['normal', 'rectangular', 'triangular', 't'])
dof (float | None)
- Return type:
Any
- noodlelab.verify.monte_carlo(model, trials=20000, *, seed=1, p=0.95)[source]¶
Evaluate
model(a function of no arguments that makes its uncertain inputs withmeasure()and returns a number or quantity) by Monte Carlo, and compare with linear GUM propagation (JCGM 101 8). Use it when the model is not linear in its inputs:agreessays whether the GUM uncertainty can be trusted. The inputs must be made inside the model.- Parameters:
model (Callable[[], Any])
trials (int)
seed (int)
p (float)
- Return type:
- noodlelab.verify.nominal(value)[source]¶
The value without its uncertainty.
- Parameters:
value (Any)
- Return type:
Any
- noodlelab.verify.q(value, unit='')[source]¶
A quantity:
q("9.81 m/s^2"),q(9.81, "m/s^2"),q("3 dB"). Text with an uncertainty ("9.81 ± 0.02 m/s^2") gives an uncertain one.- Parameters:
value (Any)
unit (str)
- Return type:
Any
- noodlelab.verify.record(name, *, out=None, write=True)[source]¶
Start a record of a calculation:
with nv.record("link budget") as rec: ....On leaving the block the record is written to
<out>/<time>-<name>-<id>/provenance.json(outdefaults torunsnext to the script, or$NOODLELAB_RECORDS).write=Falsekeeps it in memory only (tests).- Parameters:
name (str)
out (str | Path | None)
write (bool)
- Return type:
- noodlelab.verify.requirement(line)[source]¶
One requirement from a line of text (see
requirements()).- Parameters:
line (str)
- Return type:
- noodlelab.verify.requirements(text)[source]¶
Requirements from text, one per line:
COM-001 link_margin >= 3 dB [Analysis] # The link shall close with 3 dB to spare PWR-001 dc_power <= 40 W [Inspection] TMP-001 temperature between -20 and 60 degC
or from records (rows of a CSV/YAML spec: id, quantity, op, limit, unit…).
- Parameters:
text (str | Iterable[dict[str, Any]])
- Return type:
- noodlelab.verify.std_dev(value)[source]¶
The standard uncertainty (0 for an exact value), in the value’s unit.
- Parameters:
value (Any)
- Return type:
Any
- noodlelab.verify.traced(fn=None, *, name=None)[source]¶
Record every call of a function in the active record: its arguments, result (with units and uncertainty), duration and a hash of its source. Outside a record the function runs as usual, at no cost:
@nv.traced def drag(rho, v, cd, area): return 0.5 * rho * v**2 * cd * area
- Parameters:
fn (F | None)
name (str | None)
- Return type:
Any
- noodlelab.verify.verify(req, value)[source]¶
Check
valueagainst a requirement (aRequirementor its line of text). TheChecksays whether it passed, what was achieved and the margin in the requirement’s unit (negative: outside the limit). An array passes when every element does; its margin is the worst case.- Parameters:
req (Requirement | str)
value (Any)
- Return type:
noodlelab.constants¶
Named constants for calculations in Python, with their units and, where they were measured, their CODATA uncertainty:
from noodlelab.constants import c, g0, k_B, pi
E = m * c**2 # a Pint quantity, in kg·m²/s²
W = m * g0 # standard gravity, 9.80665 m/s², exact
F = G * M * m / r**2 # G is uncertain: 6.67430(15)e-11 m³/(kg·s²)
pi, tau and e are the math module’s plain floats. Exact
constants (c, h, k_B, g0…) are quantities, and measured ones
(G, m_e, alpha…) are uncertain values named after the constant,
so noodlelab.verify.budget() can list them. The full table, with sources,
is in noodlelab.core.constants, and noodlelab constants prints it.
Constants you add with define() (or load() from a
constants.toml) can be imported the same way once they are defined.
- class noodlelab.constants.Constant(name: 'str', value: 'float', unit: 'str' = '', uncertainty: 'float' = 0.0, symbol: 'str' = '', title: 'str' = '', source: 'str' = '', group: 'str' = '', origin: 'Origin' = 'built-in', override: 'bool' = False)[source]¶
- Parameters:
name (str)
value (float)
unit (str)
uncertainty (float)
symbol (str)
title (str)
source (str)
group (str)
origin (Literal['built-in', 'registered', 'workspace', 'graph'])
override (bool)
- name: str¶
- value: float¶
- unit: str = ''¶
- uncertainty: float = 0.0¶
- symbol: str = ''¶
- title: str = ''¶
- source: str = ''¶
- group: str = ''¶
- origin: Literal['built-in', 'registered', 'workspace', 'graph'] = 'built-in'¶
- override: bool = False¶
- property exact: bool¶
- value_of()[source]¶
The constant to compute with. A plain float for exact numbers, and a quantity for exact values with a unit. A measured value is uncertain, named after the constant. It is the same value every time, so results computed from
Gtwice stay correlated. Inside a Monte Carlo trial it is a fresh draw instead.- Return type:
Any
- key()[source]¶
What a cache key needs: the definition, not the description.
- Return type:
dict[str, Any]
- exception noodlelab.constants.ConstantsError[source]¶
A constant that cannot be defined (a bad name, value or unit).
- noodlelab.constants.define(name, value, unit='', *, uncertainty=0.0, title='', source='', symbol='', override=False)[source]¶
Add a constant for every graph and script in this process:
define("g_local", 9.8123, "m/s^2", uncertainty=0.0005, source="survey 2024") define("rho_water", "998.2 kg/m^3", title="density of water at 20 °C")
Replacing a built-in constant warns, unless
override=Truesays it is meant.pi,tauandecannot be replaced.- Parameters:
name (str)
value (Any)
unit (str)
uncertainty (float)
title (str)
source (str)
symbol (str)
override (bool)
- Return type:
- noodlelab.constants.load(path)[source]¶
define()every constant in aconstants.tomlfile. Raises ConstantsError listing every problem, since a script should stop on them.- Parameters:
path (str | Path)
- Return type:
dict[str, Constant]
Writing node packs¶
noodlelab: verifiable science for people and AI agents.
For calculations in plain Python (units, uncertainty, requirements, checks and
a provenance record of every run), use noodlelab.verify:
import noodlelab.verify as nv
with nv.record("pendulum") as rec:
L = rec.input("L", "1.000 ± 0.002 m", source="tape measure")
...
The public API for node-pack authors lives here:
from noodlelab import Param, Probe, ProbeContext, RunContext, node, register_type
- class noodlelab.FileRef(value='')[source]¶
A reference to a file in the workspace, on the server, or on a mount.
It is a
str(so it serialises, hashes and prints as the reference), with methods that work the same for every backend.- Parameters:
value (str | PurePath)
- Return type:
- property target: Target¶
- property mount: str | None¶
- property is_local: bool¶
- property name: str¶
- property suffix: str¶
- with_suffix(suffix)[source]¶
The file next to this one with another extension, on the same storage:
dem.asc→dem.prj, for sidecar files.- Parameters:
suffix (str)
- Return type:
- open(mode='rb', **kwargs)[source]¶
Open for reading (
"rb","r") or, on writable storage, writing.- Parameters:
mode (str)
kwargs (Any)
- Return type:
IO[Any]
- class noodlelab.Param(label=None, description='', widget=None, min=None, max=None, step=None, precision=None, choices=None, accept=None, directory=False, exists=True, options_from=None, empty=None, type=None, multiline=False)[source]¶
Extra metadata for a parameter, used via
Annotated[type, Param(...)].- Parameters:
label (str | None)
description (str)
widget (Literal['number', 'slider', 'combo', 'text', 'toggle', 'none'] | None)
min (float | None)
max (float | None)
step (float | None)
precision (int | None)
choices (Sequence[Any] | None)
accept (Sequence[str] | None)
directory (bool)
exists (bool)
options_from (str | None)
empty (str | None)
type (Any)
multiline (bool)
- label: str | None = None¶
- description: str = ''¶
- widget: Literal['number', 'slider', 'combo', 'text', 'toggle', 'none'] | None = None¶
- min: float | None = None¶
- max: float | None = None¶
- step: float | None = None¶
- precision: int | None = None¶
- choices: Sequence[Any] | None = None¶
- accept: Sequence[str] | None = None¶
- directory: bool = False¶
- exists: bool = True¶
- options_from: str | None = None¶
- empty: str | None = None¶
- type: Any = None¶
- multiline: bool = False¶
- class noodlelab.Preview(*, kind, summary, text=None, image=None, table=None, url=None)[source]¶
- Parameters:
kind (Literal['value', 'text', 'image', 'table', 'file', 'math'])
summary (str)
text (str | None)
image (str | None)
table (TablePreview | None)
url (str | None)
- kind: Literal['value', 'text', 'image', 'table', 'file', 'math']¶
- summary: str¶
- text: str | None¶
- image: str | None¶
- table: TablePreview | None¶
- url: str | None¶
- model_config = {}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class noodlelab.Probe(preview=None, meta=None, output_meta=None, summary=None, sample=None, output_samples=None)[source]¶
What a probe returns (or yields).
preview: any value, rendered with the registered previewers (a DataFrame becomes a table, a Figure an image), or a readyPreviewsuch as one fromimage_preview().meta: small JSON describing the node’s outputs, readable downstream withProbeContext.meta(); it applies to every output unlessoutput_metagives one per output name.summaryoverrides the preview’s one-line summary.sample(oroutput_samplesper output): a small value of the output’s type that downstream nodes are evaluated on while editing (seesample). When left out, a preview value of the output’s type is used, so returningdf.head(20)is enough.- Parameters:
preview (Any)
meta (dict[str, Any] | None)
output_meta (dict[str, dict[str, Any]] | None)
summary (str | None)
sample (Any)
output_samples (dict[str, Any] | None)
- preview: Any = None¶
- meta: dict[str, Any] | None = None¶
- output_meta: dict[str, dict[str, Any]] | None = None¶
- summary: str | None = None¶
- sample: Any = None¶
- output_samples: dict[str, Any] | None = None¶
- class noodlelab.ProbeContext(node_id, root, timeout, _upstream=<factory>, _linked=<factory>, _cancel=<factory>, _started=<factory>, watched=<factory>, logs=<factory>)[source]¶
Passed to probes and options functions that ask for it (by annotation or by naming a parameter
ctx).- Parameters:
node_id (str)
root (Path)
timeout (float)
_upstream (dict[str, dict[str, Any] | None])
_linked (set[str])
_cancel (Event)
_started (float)
watched (dict[str, tuple[Callable[[], Any], Any]])
logs (list[str])
- node_id: str¶
- root: Path¶
- timeout: float¶
- watched: dict[str, tuple[Callable[[], Any], Any]]¶
- logs: list[str]¶
- meta(input)[source]¶
Meta of the output linked into
input, or None (not linked, or the upstream node has no probe).- Parameters:
input (str)
- Return type:
dict[str, Any] | None
- watch(path)[source]¶
Mark a file the probe depends on: the cached result is dropped when it changes (modification time, size, or ETag for remote files). Accepts a Path (resolved against the workspace) or a FileRef; returns it.
- Parameters:
path (str | PurePath)
- Return type:
Any
- property cancelled: bool¶
True once the node’s values changed and a newer probe started. Long probes should check this between steps (or call
check_cancelled()).
- property remaining: float¶
Seconds left in the time budget (may be negative).
- class noodlelab.Problem(severity, message)[source]¶
- Parameters:
severity (Literal['error', 'warning'])
message (str)
- severity: Literal['error', 'warning']¶
Alias for field number 0
- message: str¶
Alias for field number 1
- class noodlelab.RunContext(run_id: 'str', node_id: 'str', workdir: 'Path', scratch: 'Path | None' = None, _emit: 'Callable[[str, dict[str, Any]], None]' = <function RunContext.<lambda> at 0x7f90a51e2840>, _provenance: 'Any' = None, _about_in: 'dict[str, Any]' = <factory>, _declared: 'dict[str, Any]' = <factory>, _samples: 'Any' = None)[source]¶
- Parameters:
run_id (str)
node_id (str)
workdir (Path)
scratch (Path | None)
_emit (Callable[[str, dict[str, Any]], None])
_provenance (Any)
_about_in (dict[str, Any])
_declared (dict[str, Any])
_samples (Any)
- run_id: str¶
- node_id: str¶
- workdir: Path¶
- scratch: Path | None = None¶
- monte_carlo_samples()[source]¶
The trials the executor ran for a Monte Carlo node (a
Samples), or None.- Return type:
Any
- describe(output='result', **fields)[source]¶
Say what an output is:
title,description,sources,licences,citationsorflags(lists of text). It travels downstream with the value (seenoodlelab.core.about).- Parameters:
output (str)
fields (Any)
- Return type:
None
- input_about(name)[source]¶
What is known about input
name: anAbout, or None.- Parameters:
name (str)
- Return type:
Any
- log(message)[source]¶
Send a log line to the editor (shown in the node inspector).
- Parameters:
message (str)
- Return type:
None
- progress(fraction, message='')[source]¶
Report progress between 0 and 1; drawn as a bar on the node.
- Parameters:
fraction (float)
message (str)
- Return type:
None
- path(name)[source]¶
A path inside this run’s output directory (parent dirs are created).
- Parameters:
name (str)
- Return type:
Path
- temp(name)[source]¶
A path in the run’s scratch folder, for large temporary files.
- Parameters:
name (str)
- Return type:
Path
- run_info()[source]¶
What is known about this run so far, as plain JSON: its id, start time and user, the environment (noodlelab, Python, platform, key library versions), and every node that finished before this one, with its settings and fingerprinted input files (see
noodlelab.core.provenance). Outside the editor andnoodlelab run(e.g. in an exported script) only the environment is known.- Return type:
dict[str, Any]
- noodlelab.as_file(value)[source]¶
A FileRef from a string or path (for node code also called from scripts).
- noodlelab.define_constant(name, value, unit='', *, uncertainty=0.0, title='', source='', symbol='', override=False)¶
Add a constant for every graph and script in this process:
define("g_local", 9.8123, "m/s^2", uncertainty=0.0005, source="survey 2024") define("rho_water", "998.2 kg/m^3", title="density of water at 20 °C")
Replacing a built-in constant warns, unless
override=Truesays it is meant.pi,tauandecannot be replaced.- Parameters:
name (str)
value (Any)
unit (str)
uncertainty (float)
title (str)
source (str)
symbol (str)
override (bool)
- Return type:
- noodlelab.downsample(array, max_side=256)[source]¶
Every n-th pixel so that neither of the first two axes exceeds
max_side. Cheap and shape-preserving; for a real overview read less data instead (e.g. rasterio’sout_shape).- Parameters:
array (Any)
max_side (int)
- Return type:
Any
- noodlelab.error(message)[source]¶
Return from a
.checkfunction to report an error (blocks running).- Parameters:
message (str)
- Return type:
- noodlelab.image_preview(array, *, max_side=256, summary=None)[source]¶
A PNG thumbnail from a NumPy array, with no imaging dependencies.
Accepts
(H, W)grayscale,(H, W, 3|4)RGB(A), and band-first(3|4, H, W)as rasterio returns it. Non-uint8 data is stretched between the 2nd and 98th percentiles; NaN and inf become black.- Parameters:
array (Any)
max_side (int)
summary (str | None)
- Return type:
- noodlelab.node(func: F) F[source]¶
- noodlelab.node(*, id: str | None = None, title: str | None = None, category: str = 'Utility', description: str | None = None, color: str | None = None, outputs: Sequence[str] | None = None, version: int = 1, cacheable: bool = True, checkpoint: bool = True, fold: bool = False, sample: bool | None = None, converter: bool | Literal['implicit'] = False, cost: float = 1.0, vectorized: bool = False, views: Sequence[Literal['processing', 'report']] | None = None) Callable[[F], F]
Mark a function as a node. Usable bare (
@node) or with options.version: bump it to invalidate cached results by hand (editing the function’s source already does this automatically).cacheable: set False when the output can change for the same inputs (unseeded randomness, clocks, hardware, files the node finds by itself). Files named byPath/FileRefinputs need no flag: their size and modification time are part of the cache key.checkpoint: set False to keep results in memory only, e.g. for huge intermediates that are quick to recompute.fold: the node is cheap and pure (a constant such as “File Path” or “Number”), so it is also evaluated while the graph is edited and downstream checks and probes receive its value as if it were typed in.sample: set False to never run the node on samples while editing (expensive work, side effects, statistics a sample would misstate). By default cacheable nodes without a RunContext preview on samples, except nodes that read files (give those a probe); True includes them anyway.converter: True makes the node a way to turn its first input’s type into its output’s type; the editor inserts it when such a link is drawn."implicit"(lossless, no settings) applies it on links, without a node.costranks converter chains (lower is preferred).vectorized: the function also works on many Monte Carlo trials at once: given arrays with one element per trial where it takes a number, it returns one element per trial, element by element (noifon a value), without side effects, and raises where it would raise for some trial alone. A Monte Carlo evaluation whose nodes are all vectorized runs its trials in batches; otherwise, or if a batch disagrees with trials run one at a time, trial by trial.views: the canvases whose add-node menus offer the node, “processing” and/or “report”; by default Report nodes are offered on the Reporting tab, Text nodes on both and all others on the Processing tab. Any node can be placed on either tab (the editor can be set to offer them all).The returned function gets decorators for edit-time helpers:
.check(live health checks),.probe(a quick preview and metadata, e.g. the first rows of a file),.options(input)(dynamic dropdown choices),.uses_constants(the named constants it reads, for its cache key) and, for converters,.accepts(which values the conversion fits).- Parameters:
func (Any)
options (Any)
- Return type:
Any
- noodlelab.register_codec(py_type, name, *, save, load, suffix='.bin')[source]¶
Store values of a type (or a qualified class name, for optional dependencies) in checkpoints with
save/loadinstead of pickle. Thenameis written into every checkpoint, so keep it stable.- Parameters:
py_type (type | str)
name (str)
save (Callable[[Any, IO[bytes]], dict[str, Any] | None])
load (Callable[[IO[bytes], dict[str, Any]], Any])
suffix (str)
- Return type:
Codec
- noodlelab.register_fields(py_type, *, names, type, get)[source]¶
Describe the fields of a type (or a qualified class name) for split outputs.
names(ref, meta): the field names, usually from the output’s meta (metamay be None).type(ref, name, meta): a field’s type hint, also asked without meta when a saved link is checked; returnAnywhen it cannot be known then.get(value, name): read a field of a real value.- Parameters:
py_type (type | str)
names (Callable[[TypeRef, dict[str, Any] | None], list[str]])
type (Callable[[TypeRef, str, dict[str, Any] | None], Any])
get (Callable[[Any, str], Any])
- Return type:
None
- noodlelab.register_meta(py_type)[source]¶
Register a function describing values of a type (or a qualified class name, for optional dependencies) as a small JSON dict.
- Parameters:
py_type (type | str)
- Return type:
Callable[[Callable[[Any], dict[str, Any] | None]], Callable[[Any], dict[str, Any] | None]]
- noodlelab.register_sampler(py_type)[source]¶
Register
fn(value, size) -> smaller value of the same typefor a type (or a qualified class name).sizeis roughly the number of rows or elements along each axis to keep.- Parameters:
py_type (type | str)
- Return type:
Callable[[Callable[[Any, int], Any]], Callable[[Any, int], Any]]
- noodlelab.register_type(py_type, name, color=None, description='')[source]¶
Map a Python type (or its qualified name) to a socket type.
- Parameters:
py_type (type | str)
name (str)
color (str | None)
description (str)
- Return type:
str
- noodlelab.register_unit(newtype, unit)[source]¶
Give a
NewTypea unit: its sockets then connect to every type of the same dimension, converted on the link. Returns the NewType.- Parameters:
newtype (Any)
unit (str)
- Return type:
Any
- noodlelab.table_preview(columns, rows, *, total_rows=None, summary=None)[source]¶
A table preview without pandas, e.g. from
csv.readeror a database cursor.- Parameters:
columns (list[Any])
rows (list[list[Any]])
total_rows (int | None)
summary (str | None)
- Return type: