Record and Save One Run
Separate chosen configuration, measured results, and artifact paths, then convert their small NumPy values into a JSON record that can be read back.
A numerical result is hard to inspect later when its settings and artifacts have been separated from it. A useful run record keeps three roles distinct:
- configuration records choices made before the run;
- measurement records values produced by the run;
- artifact points to a file created from those values.
Chapter 9 used frozen dataclasses to make configuration and result roles visible. We can reuse that pattern for one noisy measurement run.
Give Each Role a Record
The configuration contains the seed, number of observations, and noise range:
The result contains discrete observation identifiers, the noisy readings, and a small numerical summary:
The artifact record contains a path rather than the image itself:
The roles answer different questions. Changing a seed changes configuration.
The generated noisy readings are measurements. A saved plot is an artifact
derived from those measurements. Putting the figure path inside RunConfig
would mix a product of the run with the choices that define it.
Q1. Separate configuration, measurement, and artifact
Which assignment keeps the three roles distinct?
Select one choice, then check.
HintFollow when each value exists
Configuration exists before generation. Measurements and artifacts do not exist until the run has produced or saved something.
SolutionKeep the three roles explicit
The seed, count, and bounds are configuration. The generated values and their summary are measurements. The figure path identifies an artifact.
Run the Bounded-Noise Experiment
Begin with the calibrated table from the previous chapters:
The run uses only the requested number of observations and generates one noise value for each selected reading:
This run keeps every observation in order, so its identifiers are 0, 1,
and 2. If a run samples records first, its measurement record should instead
save the selected indexes from that sampling step.
The generated table has shape (3, 2). Its noise bounds can be checked from
the result:
These assertions check the run contract. The record will preserve their evidence, but saving a record does not replace the checks.
Convert NumPy Values Before Writing JSON
asdict turns a dataclass into a dictionary of its fields:
The configuration fields are already ordinary Python integers and floats.
The result still contains NumPy arrays and NumPy scalar values, while the
artifact contains a Path. Python's JSON encoder does not automatically know
how those objects should be represented.
Convert each boundary deliberately:
.tolist() converts the two-dimensional NumPy array into nested Python lists
and converts its entries to nearby built-in Python scalar types. The explicit
int(...), float(...), and str(...) calls make the other JSON boundaries
visible. The record remains small: it keeps the settings, three observations,
their summary, and one artifact path rather than an unrelated dump of program
state.
Q2. Choose JSON-compatible conversions
Which conversions preserve the values in ordinary JSON-compatible forms?
Select one choice, then check.
HintPreserve structure, change boundary types
Keep arrays as nested lists, scalar numbers as Python numbers, and paths as strings.
SolutionConvert arrays, scalars, and paths explicitly
Use .tolist() for arrays, int(...) and float(...) for NumPy scalars,
and str(...) for a path. The resulting dictionary retains its field names
and nested structure.
Write the Record and Read It Back
Write one JSON document, then read that same path:
allow_nan=False rejects non-finite floating-point values instead of writing
non-standard JSON spellings. The read-back check confirms that the intended
fields reached the file:
In Browser Python, this file lives in the page session's temporary browser-side file system. Download it if it must outlive the session. In a local program, the relative path belongs to the current working directory.
Q3. Save and inspect a compact run record
Complete the conversions, write the JSON document, and read it back. The round-trip should preserve the configuration, measurement shape, summary, and figure path.
Editable Python
Ready to run.
HintConvert at the JSON boundary
Use asdict(config), noisy.tolist(), float(value), and
str(figure_path). Write with json.dump(record, handle, indent=2) and read
with json.load(handle).
SolutionWrite ordinary Python values and read them back
Keep choices, produced measurements, summaries, and artifact paths in named roles. Use dataclasses for the in-program records, then convert NumPy arrays, NumPy scalars, and paths explicitly at the JSON boundary. Reading the saved document back confirms that the evidence needed for reconstruction is present.
References
- Python documentation:
dataclasses.asdict— converting dataclass fields to dictionaries. - Python documentation:
json— writing and reading JSON documents. - NumPy documentation:
ndarray.tolist— converting arrays and their entries to nested built-in Python values.