pyretis.testing package¶
This package defines common methods which are used for testing.
Package structure¶
Modules¶
- simulation_comparison.py (
pyretis.testing.simulation_comparison) Common methods for comparing results.
- helpers.py (
pyretis.testing.helpers) Common methods for tests.
List of submodules¶
pyretis.testing.example_compare module¶
Shared result-comparison for the example run.sh scripts.
The example test folders under examples/tests/ used to each ship a
bespoke compare.py that re-implemented the same three checks against
the committed results/ reference. That logic lives here now, so a
folder’s run.sh calls python -m pyretis.testing.example_compare
<config.toml> (via its -C/-cc flag) instead of carrying its own
copy.
The checks run for a given config are selected from its simulation
task:
golden – every committed per-ensemble reference file (
pathensemble.txtalways;order.txt/energy.txtwhen the folder commits them) is compared against the run’s matching file with the file-type-appropriate primitive (compare_ensemble_files_golden()). Always run; a folder selects which files to check simply by which it commits underresults/.--energy-skip/--path-skip/--rel-toltune this for a folder whose reference legitimately differs in a named term (e.g. GROMACS’s restart-dependent long-range dispersion correction) or needs a looser tolerance (e.g. a build-sensitive external engine).archive – the per-trial trajectory archive (
<ensemble>/paths/<pn>/plus the per-ensemble long-term<ensemble>/archive/<pn>/) is byte-compared (tolerating--energy-skipthe same way as the golden check;compare_archive_check()). Opt-in (not part of the per-task default): the two-run restart/load/two-engine equivalence checks that need it request it explicitly via--checks.paths – every accepted path is validated (start/middle/end interface labels, length, crossings;
check_accepted_paths()). Run for the path-sampling tasks.relaxed-paths – like paths, but the
middle/crossing invariants are relaxed for sparse-loaded (ld-move) initial paths (check_accepted_paths_relaxed()).zero_leftis read from the config automatically, so a[0^-]path may legitimately end'L'under that geometry without being flagged.swaps – accepted
s+/s-swap moves are checked for order-parameter continuity with their parent path (check_retis_swaps()). Opt-in (not a per-task default): the unified infinite-swapping scheduler folds swaps into weighted bookkeeping rather than emitting discretes+/s-moves, so a caller requests this only where discrete swaps exist, and the check fails if it examines none.
--run-dir/--ref-dir need not point at a committed results/
golden – pointing --ref-dir at a second, independently-run directory
of the same config turns the golden/archive checks into a two-run
equivalence check (e.g. a restart or two-engine comparison that has no
committed reference of its own).
A few folders instead check that a restarted (stopped-and-resumed) run
reproduces the uninterrupted one, with no committed golden. Their
run.sh selects a dedicated subcommand: restart-whole (the restart
already holds the whole history; compare_restart_whole()),
restart-concat (part 1 + part 2 must equal the full run;
compare_restart_concat()) and restart-md (the same, with a
trajectory compared by per-snapshot MSE; compare_restart_md()).
Exit status is the number of failing checks (0 == success), so it drops
straight into a run.sh && chain.
- pyretis.testing.example_compare._ALL_CHECKS = ('golden', 'paths', 'relaxed-paths', 'swaps', 'structural', 'reports', 'archive')¶
The check names a folder may request (see
compare_run()).
- pyretis.testing.example_compare._GOLDEN_COMPARATORS = {'energy.txt': <function compare_energy_data>, 'order.txt': <function compare_numerical_data>, 'pathensemble.txt': <function compare_path_ensemble_data>, 'traj.txt': <function compare_simulation_files>}¶
Map a committed per-ensemble golden file to the primitive that compares it. The comparison a folder wants is inferred from which of these files it actually commits under
results/– seecompare_ensemble_files_golden(). Insertion order fixes the report order (path ensemble first, then the numerical trajectories).
- pyretis.testing.example_compare._MISSING = <object object>¶
Unique sentinel used as the
zip_longestfill value when pairing two iterators of trajectory blocks/snapshots, so a length mismatch on either side is detected (a real snapshot is never this object).
- pyretis.testing.example_compare._PATH_SAMPLING_TASKS = frozenset({'explore', 'pptis', 'repptis', 'retis', 'tis'})¶
Tasks that sample paths (so the accepted-path validity check applies).
- pyretis.testing.example_compare._STRUCTURAL_PROFILES = {'explore': {'has_zero_minus': False, 'min_length': 3, 'require_finite_lockstep': True, 'require_maxo_ge_mino': True}, 'pptis': {'has_zero_minus': True, 'min_length': 2, 'require_finite_lockstep': False, 'require_maxo_ge_mino': False}, 'repptis': {'has_zero_minus': True, 'min_length': 2, 'require_finite_lockstep': False, 'require_maxo_ge_mino': False}}¶
Structural-check profiles for the golden-less path-sampling folders, keyed by task.
exploreproducesN - 1positive ensembles and no[0^-];repptis/pptiskeep[0^-]. The accepted-length threshold and the extra order-parameter checks also differ.
- pyretis.testing.example_compare._TRAJ_READER_SPECS = {<class 'pyretis.inout.formats.path.PathIntFile'>: {'nested': True, 'snapshot_diff': <function _snapshot_diff_pathint>}, <class 'pyretis.inout.formats.snapshot.SnapshotFile'>: {'nested': False, 'snapshot_diff': <function _snapshot_diff_snapshot>}}¶
Per-reader trajectory-MSE behaviour.
PathIntFileyields path blocks (nested; each block carries adatalist of snapshots) and is used for the whole-file restart;SnapshotFileyields snapshots directly (flat) and is used for the concatenated restart. The matching per-snapshot diff function reflects the file format’s snapshot keys.
- pyretis.testing.example_compare._archive_subdir_name(base_dir, ens_dir)¶
Return the ensemble’s operational-archive subdirectory name.
Prefers the current default (
ARCHIVE_SUBDIR,accepted) and falls back to the legacypaths/trajsnames so a new run can still be compared against a reference recorded before the renames.Nonewhen the ensemble has no archive.
- pyretis.testing.example_compare._assess_mse(error, what, tol)¶
Log and grade one averaged error term against a tolerance.
- Parameters:
error (float) – The mean per-snapshot error term.
what (str) – A label for the term (e.g.
positions) used in the log message.tol (float) – The tolerance the error must stay below.
- Returns:
int – 0 when
abs(error) < tol, else 1.
- pyretis.testing.example_compare._chained_restart_snaps(part_files, reader)¶
Chain the restart parts’ snapshots, dropping each overlap frame.
- Parameters:
part_files (list of str) – The restart parts, in order.
reader (callable) – The trajectory reader class (
SnapshotFile).
- Returns:
iterator – The chained snapshots, with every part after the first missing its leading frame (which repeats the previous part’s last frame).
- pyretis.testing.example_compare._check_swaps_one(run_dir, paths, accepted, ens, kind)¶
Check the accepted swaps of a single ensemble against its neighbour.
A swap move that is present but whose parent path cannot be found, or whose order-parameter continuity fails, makes the status non-zero. The second returned value is the number of accepted swap moves examined.
- pyretis.testing.example_compare._configure_console_logging()¶
Route this module’s log records to the console.
Every check reports what it compared and, on a mismatch, why (which ensemble, which file, which line) through
logger– but the module only attaches alogging.NullHandlerat import time (so importing it as a library stays silent by default), so run as a script a failed comparison exits non-zero while printing nothing: an opaque, silent failure that defeats the whole point of a detailed mismatch message. Attach a single stdoutlogging.StreamHandleratINFOso the CLI entry point (main()) is loud about what it checked and why it failed. Idempotent: a second call does not stack a duplicate handler.
- pyretis.testing.example_compare._cycle_index(traj)¶
Extract the cycle index from an order.txt block comment.
- pyretis.testing.example_compare._default_checks(task)¶
Return the checks a task runs when a folder does not name its own.
- Parameters:
task (str) – The (lower-cased) simulation task.
- Returns:
list of str – The default check names:
goldenalways andpathsfor the path-sampling tasks. Swap validation must be requested explicitly because unified infinite swapping does not emit discrete swap moves.
- pyretis.testing.example_compare._generated_report_path(run_dir, name)¶
Resolve a committed report name to the run’s generated report file.
Reports are written under
<run_dir>/report/and may carry a_cycles-NNNsuffix (the cycle count at write time). Given the plain reference name, return the matching generated path, preferring an exact match and otherwise the highest-numbered_cycles-variant.- Parameters:
run_dir (str) – The directory the simulation ran in.
name (str) – The reference report file name (e.g.
foo_report.html).
- Returns:
str – The path to the generated report file.
- pyretis.testing.example_compare._golden_ensemble_dirs(ref_dir)¶
Return the ensemble subdirectories that carry golden files.
The reference directory holds one zero-padded, three-digit subdirectory per compared ensemble (
000,001…). Some folders start at001(e.g. themake-tis-filesexamples), so the set is discovered fromref_dirrather than assumed to be0 .. n_interfaces.- Parameters:
ref_dir (str) – The committed reference directory (
results/).- Returns:
list of str – The ensemble directory names present, sorted ascending.
- pyretis.testing.example_compare._order_swap_ok(data0, data1, special)¶
Check order-parameter continuity across a swap (or full equality).
- pyretis.testing.example_compare._parse_ensemble_energy_terms(specifications, parser)¶
Parse repeated
ENSEMBLE:TERM,TERMCLI specifications.
- pyretis.testing.example_compare._parse_ensemble_status_counts(pathensemble_file)¶
Count the per-status rows in a
pathensemble.txt.- Parameters:
pathensemble_file (str) – Path to an ensemble’s
pathensemble.txt.- Returns:
dict – A count for each of
ACC/FTX/BTX/FTL/BTL/0-L.
- pyretis.testing.example_compare._pathensemble_rows(pathensemble_file)¶
Return the split non-comment rows of a
pathensemble.txt.
- pyretis.testing.example_compare._read_path_moves(run_dir, ens_number)¶
Read per-step move bookkeeping (and accepted-at map) for an ensemble.
- pyretis.testing.example_compare._read_pathensemble_rows(run_dir, ens_number)¶
Yield the non-comment rows of an ensemble’s
pathensemble.txt.
- pyretis.testing.example_compare._report_file_pair(name, equal, msg)¶
Log a single file comparison result and return its failure count.
- Parameters:
name (str) – The file name being compared (for the log message).
equal (bool) – Whether the comparison judged the files equal.
msg (str) – The descriptive message returned by the comparison primitive.
- Returns:
int – 0 when
equalis True, else 1.
- pyretis.testing.example_compare._resolved_ref_dir(ref_dir)¶
Yield a directory-shaped reference, extracting a tarball first.
Every check that reads
ref_direxpects a plain directory laid out as<ensemble>/<file>(a committedresults/, or a second live run directory). Some folders instead commit a single gzipped tarball with that same layout stored under aresults/prefix inside the archive – e.g. LAMMPS, where keeping the reference to one small binary-diffable file is preferable to a committed tree (generate_golden_tarball()writes it). Transparently extract it to a temporary directory so every check downstream stays unaware of which form the reference took.- Parameters:
ref_dir (str) – Either a plain reference directory, or the path to a
.tgz/.tar.gzarchive holding the same layout under aresults/prefix.- Yields:
str – A directory laid out as
<ensemble>/<file>–ref_diritself, or the archive’s extractedresults/subdirectory.
- pyretis.testing.example_compare._run_compare_subcommand(args, parser)¶
Handle the
comparesubcommand (single run vs golden/structural).
- pyretis.testing.example_compare._set_swap_parents(paths, ens_left, ens_right, acc_left, acc_right)¶
Tag each
s+/s-move with the parent path it swapped with.
- pyretis.testing.example_compare._snapshot_diff_pathint(snap1, snap2)¶
Return the summed squared position/velocity differences of a snapshot.
For snapshots loaded by
pyretis.inout.formats.path.PathIntFile, whose positions and velocities are(n_atoms, dim)arrays under thepos/velkeys.- Parameters:
snap1 (dict) – The first snapshot (keys
posandvel).snap2 (dict) – The second snapshot, compared against
snap1.
- Returns:
diff_pos (float) – The summed squared position difference over all atoms.
diff_vel (float) – The summed squared velocity difference over all atoms.
- pyretis.testing.example_compare._snapshot_diff_snapshot(snap1, snap2)¶
Return the summed squared position/velocity differences of a snapshot.
For snapshots loaded by
pyretis.inout.formats.snapshot.SnapshotFile, whose coordinates live in the per-axisx/y/zandvx/vy/vzkeys.- Parameters:
snap1 (dict) – The first snapshot (keys
x/y/zandvx/vy/vz).snap2 (dict) – The second snapshot, compared against
snap1.
- Returns:
diff_pos (float) – The summed squared position difference over all atoms.
diff_vel (float) – The summed squared velocity difference over all atoms.
- pyretis.testing.example_compare._store_is_empty(directory)¶
Return True if
directoryexists but contains no files at all.
- pyretis.testing.example_compare._struct_check_layout(run_dir, ens_dirs, has_zero_minus)¶
Structural check 1: the expected ensemble dirs and files exist.
- pyretis.testing.example_compare._struct_check_lockstep(run_dir, ens_dirs, require_finite)¶
Structural check 3: one order.txt block per pathensemble.txt row.
- pyretis.testing.example_compare._struct_check_moves(run_dir, ens_dirs)¶
Structural check 4: real shooting/swap moves (not only loaded).
- pyretis.testing.example_compare._struct_check_paths(run_dir, ens_dirs, min_length, require_maxo_ge_mino)¶
Structural check 2: every accepted path is a valid sampling path.
- pyretis.testing.example_compare._structural_ensemble_dirs(n_interfaces, has_zero_minus)¶
Return the ensemble directory names for a golden-less run.
- Parameters:
n_interfaces (int) – The number of interfaces in the config.
has_zero_minus (bool) – Whether the topology includes the
[0^-](000) ensemble.
- Returns:
list of str – Ensemble directory names –
000 .. 0(N-1)when[0^-]is present, else001 .. 0(N-1)(the explore positive ensembles).
- pyretis.testing.example_compare._traj_mse_flat(part_files, full_file, reader, snapshot_diff)¶
Accumulate per-snapshot squared errors for a concatenated restart.
The restart is split into
part_fileswritten to separate files. They are chained (dropping each overlapping restart frame; see_chained_restart_snaps()) and compared snapshot-for-snapshot against the full run. The residual flag reports a differing total snapshot count.- Parameters:
part_files (list of str) – The restart parts, in order.
full_file (str) – The uninterrupted run’s trajectory file.
reader (callable) – The trajectory reader class (
SnapshotFile).snapshot_diff (callable) – The per-snapshot difference function.
- Returns:
error_pos (list of float) – The per-snapshot squared position errors.
error_vel (list of float) – The per-snapshot squared velocity errors.
residual (bool) – True if the chained restart and the full run differ in length.
- pyretis.testing.example_compare._traj_mse_nested(part_files, full_file, reader, snapshot_diff)¶
Accumulate per-snapshot squared errors for a whole-file restart.
The restart already holds the whole history, so it is compared block-for-block (each block a path) and, within a block, snapshot-for-snapshot against the full run. The residual flag reports a differing number of path blocks (the trajectory-count check).
- Parameters:
part_files (list of str) – The restart trajectory file(s); the whole-file restart passes one.
full_file (str) – The uninterrupted run’s trajectory file.
reader (callable) – The trajectory reader class (
PathIntFile).snapshot_diff (callable) – The per-snapshot difference function.
- Returns:
error_pos (list of float) – The per-snapshot squared position errors.
error_vel (list of float) – The per-snapshot squared velocity errors.
residual (bool) – True if the two runs hold a different number of path blocks.
- pyretis.testing.example_compare.check_accepted_paths(run_dir, ensembles)¶
Validate every accepted path in every ensemble.
Each accepted path must have length >= 3, a start/middle/end interface label consistent with the ensemble, and cross its two bounding interfaces.
- Parameters:
run_dir (str) – The directory the simulation ran in.
ensembles (list) – The ensemble dictionaries from
pyretis.setup.createsimulation.create_ensembles().
- Returns:
int – The number of ensembles with a suspicious accepted path.
- pyretis.testing.example_compare.check_accepted_paths_relaxed(run_dir, ensembles, zero_left=False)¶
Validate accepted paths with the relaxed (sparse-load) rules.
Like
check_accepted_paths(), but themiddle == 'M'marker and the interface-crossing invariants are relaxed for the sparse-LOADED initial paths ONLY – the rows whose move isld. A short loaded[0^-]minus path need not reach the midpoint, so those stricter invariants do not apply to it; every genuinely sampled path (any other move) must still satisfy them, exactly as in the strict check. Length, start label and end label are always enforced.- Parameters:
run_dir (str) – The directory the simulation ran in.
ensembles (list) – The ensemble dictionaries from
create_ensembles.zero_left (bool, optional) – Whether the config sets
[simulation] zero_left. Underzero_left, the[0^-](ensemble 0) minus interface sits at thezero_left/interface[0]midpoint rather than atinterface[0]itself, so an accepted[0^-]path can legitimately end'L'(not only'R') – without this flag, such a (correct) path is indistinguishable from a genuine wrong-end bug and would be flagged as one.
- Returns:
int – The number of ensembles with a suspicious accepted path.
- pyretis.testing.example_compare.check_retis_swaps(run_dir, ensembles)¶
Check order-parameter continuity of accepted swaps in every ensemble.
- Parameters:
run_dir (str) – The directory the simulation ran in.
ensembles (list) – The ensemble dictionaries from
create_ensembles.
- Returns:
int – The number of failing swap checks (0 == all consistent and at least one accepted swap was examined).
- pyretis.testing.example_compare.check_structural_suite(run_dir, n_interfaces, task)¶
Run the structural validity checks for a golden-less run.
The
exploreandrepptis/pptisruns go through the infinite-swapping coordinator with a non-deterministic initiation, so a byte comparison against a stored reference is not meaningful. Instead this checks the run is a VALID sampling run: the expected per-ensemble output exists, every accepted path obeys the (task-specific) length and order-parameter rules,order.txtis in lockstep withpathensemble.txt, and real (non-loaded) moves were committed.- Parameters:
run_dir (str) – The directory the simulation ran in.
n_interfaces (int) – The number of interfaces in the config.
task (str) – The (lower-cased) simulation task; selects the profile from
_STRUCTURAL_PROFILES.
- Returns:
int – The number of failing structural checks (0 == valid run).
- pyretis.testing.example_compare.check_zero_left_contract(nozero_dir, withzero_dir, acc_ratio_max=3.0)¶
Check the two-run behavioural contract of the
zero_leftfeature.no-zeroandwith-zerorun the same short RETIS simulation and differ only in the[0^-]configuration.zero_leftmay reject paths with0-Lin[0^-](and propagate one to[0^+]via a failed swap-zero), but must never (a) introduce0-Lin the inner ensembles[1^+],[2^+]…, nor (b) introduce maxlength (FTX/BTX) rejections in[0^-]. The two runs’ accepted-path counts should also stay within a generous factor.- Parameters:
nozero_dir (str) – The directory holding the plain (no
zero_left) run’s ensembles.withzero_dir (str) – The directory holding the
zero_leftrun’s ensembles.acc_ratio_max (float, optional) – The largest tolerated ratio between the two runs’ accepted-path counts in an ensemble (default 3.0; the run is short, fixed-seed).
- Returns:
int – The number of violated contract clauses (0 == contract holds).
- pyretis.testing.example_compare.compare_archive_check(run_dir, ref_dir, energy_skip=None, frames='byte')¶
Compare the two-tier trajectory stores of two runs.
For each ensemble directory present under
ref_dir, byte-compares the per-ensemble OPERATIONAL archive (<ensemble>/paths/<pn>/, written bypyretis.inout.scheduler_archive. SchedulerPathStorage; the legacytrajsname is honoured for old references) between the two runs, and likewise the per-ensemble LONG-TERM store (<ensemble>/archive/<pn>/, the replaced paths) when either side has one – viacompare_traj_archive_soft()in both cases. This check is independent of thegoldencheck (which only compares the top-levelpathensemble.txt/order.txt/energy.txt): a restart or continuation can reproduce those exactly while still silently diverging in the raw archived frames, which is exactly what this check exists to catch.- Parameters:
run_dir (str) – The directory the simulation ran in.
ref_dir (str) – The committed reference directory, or a second live run directory.
energy_skip (list of str, optional) – Named energy terms to exclude from an archived
energy.txtfragment’s comparison (seecompare_traj_archive_soft()).
- Returns:
int – The number of stores that differ (0 == all equal). An ensemble whose archive exists on only ONE side is a loud failure; one absent on BOTH sides is skipped (no path was born there on either run) – but a check that ends up comparing nothing at all fails loudly rather than passing vacuously.
- pyretis.testing.example_compare.compare_ensemble_files_golden(run_dir, ref_dir, energy_skip=None, energy_unavailable=None, energy_unavailable_by_ensemble=None, path_skip=None, rel_tol=1e-05)¶
Compare every committed per-ensemble golden file against the run.
For each ensemble directory present under
ref_dir, every golden file it commits (pathensemble.txt/order.txt/energy.txt/traj.txt) is compared against the matching file the run produced, using the file-type-appropriate primitive. A folder therefore selects its golden comparison simply by which files it commits – a pure RETIS folder commits onlypathensemble.txt; a permeability or sparse-load folder also commitsorder.txt(andenergy.txt); a folder whose engine cannot be trusted to match a numerical tolerance across builds (e.g. LAMMPS, run at a pinned, reference-grade version) instead commitstraj.txtand compares it byte-for-byte.- Parameters:
run_dir (str) – The directory the simulation ran in (holds
000/,001/…).ref_dir (str) – The committed reference directory (
results/– or a second live run directory, e.g. for a restart/continuation-equivalence check that has no committed golden of its own).energy_skip (list of str, optional) – Named energy terms (as read by
EnergyPathFile, e.g.'vpot') to exclude fromenergy.txt. When given, the comparison switches from the default NaN-tolerantcompare_energy_data()to a by-column comparison that additionally excludes these named terms – for a case where a term is legitimately expected to differ (e.g. GROMACS applying the long-range dispersion correction differently across a restart), not merely absent (all-NaN).energy_unavailable (list of str, optional) – Named energy terms expected to be entirely NaN in every ensemble. The comparator verifies that they remain unavailable on both sides.
energy_unavailable_by_ensemble (dict, optional) – Per-ensemble unavailable terms, keyed by the three-digit ensemble directory name. This preserves finite coverage in other ensembles.
path_skip (list of int, optional) – Column indices to exclude from
pathensemble.txt.rel_tol (float, optional) – Relative tolerance forwarded to every numerical comparator (default matches each comparator’s own 1e-5 default).
- Returns:
int – The number of mismatching golden files (0 == all equal). A missing or empty reference, or a reference that holds none of the recognized golden files, is a loud failure (>= 1) rather than a vacuous “all equal”: a comparison that inspected nothing has validated nothing.
- pyretis.testing.example_compare.compare_reports_golden(run_dir, ref_dir)¶
Compare the committed top-level report / generated-config goldens.
For every non-directory file committed at the top of
ref_dir:*.toml(a generated per-interface config) is compared line by line ignoring the run-dependentexe_path;*.html/*.rst/*.tex(a report) is compared with version/timestamp normalisation, resolving the generated report’s_cycles-NNNsuffix.- Parameters:
run_dir (str) – The directory the simulation ran in.
ref_dir (str) – The committed reference directory (
results/).
- Returns:
int – The number of mismatching golden files (0 == all equal). A committed top-level reference file with no comparator (an unexpected extension) is a loud failure rather than being silently skipped, and a
reportscheck that compared nothing (no report/config golden underref_dir) also fails.
- pyretis.testing.example_compare.compare_restart_concat(part1_dir, part2_dir, full_dir)¶
Compare a two-part (concatenated) restart against the full run.
Part 1 plus part 2 (dropping the single overlapping record) must equal the full run for each output file. The concatenation-aware primitives from
pyretis.testing.simulation_comparisonhandle the overlap internally:cross.txt–compare_restarted_cross_files();energy.txtandorder.txt–compare_restarted_text_files().
- Parameters:
part1_dir (str) – The first part’s run directory.
part2_dir (str) – The second (restarted) part’s run directory.
full_dir (str) – The uninterrupted (full) run directory.
- Returns:
int – The total number of failing checks (0 == the restart reproduces the full run).
- pyretis.testing.example_compare.compare_restart_md(traj_files, text_triples, tol=1e-12)¶
Compare a concatenated MD restart against the full run.
The MD restart is split into two parts written with per-run file-name prefixes. The trajectory is compared by per-snapshot MSE (
compare_restart_traj_mse()withSnapshotFile, which drops the overlapping restart frame); the remaining text files (thermo, energy) are compared withcompare_restarted_text_files().- Parameters:
traj_files (list of str) – The trajectory files
[part1, ..., full]; the last is the full run, the rest are the ordered restart parts.text_triples (list of (list or tuple) of str) – Each entry is a
(part1, part2, full)triple of text-file paths (e.g. the thermo and energy files) checked with the concatenation-aware text comparison.tol (float, optional) – The trajectory MSE tolerance (1e-12).
- Returns:
int – The total number of failing checks (0 == the restart reproduces the full run).
- pyretis.testing.example_compare.compare_restart_traj_mse(part_files, full_file, reader, tol=1e-12)¶
Compare a restart trajectory against the full run by snapshot MSE.
The restart and full trajectories are read snapshot-by-snapshot with
readerand their per-snapshot squared position/velocity differences are averaged; each average must stay belowtol. The two must also hold the same number of snapshots (or path blocks, for the whole-file case). The reader selects the whole-file vs concatenated behaviour and the matching snapshot-difference function (see_TRAJ_READER_SPECS):PathIntFilereads a whole-file restart block-for-block,SnapshotFilechains the concatenated parts (dropping each later part’s overlapping first frame).- Parameters:
part_files (list of str) – The restart trajectory file(s). A whole-file restart passes a single file; a concatenated restart passes the ordered parts.
full_file (str) – The uninterrupted (full) run’s trajectory file.
reader (callable) – The trajectory reader class (
PathIntFileorSnapshotFile).tol (float, optional) – The tolerance each averaged error term must stay below (1e-12).
- Returns:
int – The number of failing checks: a length mismatch counts as 1, and each out-of-tolerance term (positions, velocities) adds 1.
- pyretis.testing.example_compare.compare_restart_whole(config_path, restart_dir, full_dir, tol=1e-12)¶
Compare a whole-file restart against the uninterrupted run.
The restart leg appends its steps onto the existing history, so its per-ensemble output already holds the WHOLE trajectory; it is compared file-for-file against the full run for the single ensemble named by the config’s
[tis] ensemble_number:the two-tier trajectory stores (
<ens>/paths/<pn>+ the per-ensemblearchive/) – byte-compared viacompare_archive_check(): every sampled path’s full trajectory, not just the initial one. (The former<ens>/traj.txtMSE compared a file that, since the in-process-loop retirement, only ever held the cycle-0 initiation block – a vacuous check the retired initiation dump masked.)energy.txt– column comparison skipping theetot/tempterms the internal engine leaves entirely NaN (an all-NaN term tests nothing;ekin/vpotare still compared);order.txt– numerical comparison.
- Parameters:
config_path (str) – The run config (
.toml); its[tis] ensemble_numbernames the single ensemble to compare.restart_dir (str) – The restarted run directory (holds the whole history).
full_dir (str) – The uninterrupted (full) run directory.
tol (float, optional) – Unused (kept for call compatibility); the archives are byte-compared.
- Returns:
int – The total number of failing checks (0 == the restart reproduces the full run).
- pyretis.testing.example_compare.compare_run(config_path, run_dir=None, ref_dir=None, checks=None, energy_skip=None, energy_unavailable=None, energy_unavailable_by_ensemble=None, path_skip=None, rel_tol=1e-05, archive_frames='byte')¶
Run the reference comparison for a completed example simulation.
- Parameters:
config_path (str) – The simulation config (
.toml) the example ran with.run_dir (str, optional) – Where the run produced its per-ensemble output (default: the config’s directory).
ref_dir (str, optional) – The committed reference directory (default:
results/next to the config). This may instead be a second, independently-run directory of the SAME config – e.g. a restart/load/two-engine equivalence check that has no committed golden of its own; the golden and archive checks only require a matching per-ensemble layout, not thatref_dirbe a “reference” in the historical sense.checks (list of str, optional) – The checks to run (any of
_ALL_CHECKS). WhenNonethe set is inferred from the task (_default_checks()). A folder overrides this when its faithful verdict is a subset – e.g. the permeability example istask = retisbut historically compared only the golden files (itszero_leftgeometry does not satisfy the generic accepted-path invariants), so it passeschecks=['golden'].energy_skip (list of str, optional) – Named energy terms to exclude from
energy.txt(golden check) and any archivedenergy.txtfragment (archive check) – seecompare_ensemble_files_golden()/compare_archive_check().energy_unavailable (list of str, optional) – Terms expected to be all-NaN in every golden
energy.txtfile.energy_unavailable_by_ensemble (dict, optional) – Per-ensemble expected unavailable terms for the golden check.
path_skip (list of int, optional) – Column indices to exclude from
pathensemble.txt(golden check only).rel_tol (float, optional) – Relative tolerance forwarded to the golden check’s numerical comparators (default 1e-5, matching each comparator’s own default).
- Returns:
int – The total number of failing checks (0 == success).
- pyretis.testing.example_compare.generate_golden_tarball(config_path, output_tgz, run_dir=None, files=None)¶
Pack a run’s own per-ensemble files into a golden reference tarball.
The “re-bless the reference” counterpart to the golden check’s tarball form (
_resolved_ref_dir()): for a folder whose engine is only bit-reproducible at a pinned, reference-grade version (e.g. LAMMPS), the committed reference is one small binary-diffable.tgzrather than a committed tree, generated by running the example once on that reference build and packing its own output. Every ensemble’straj.txtis reconstructed first (a no-op for an ensemble that already writes it directly) viareconstruct_traj_for_run().- Parameters:
config_path (str) – The simulation config (
.toml) the run used.output_tgz (str) – Where to write the
.tgzarchive.run_dir (str, optional) – Where the run produced its per-ensemble output (default: the config’s directory).
files (list of str) – The per-ensemble file names to pack (e.g.
['pathensemble.txt', 'order.txt', 'traj.txt']) – deliberately explicit and required, since this writes the reference every future run of this folder is graded against.
- Returns:
int – The number of requested files missing from the run (and therefore not packed); 0 means every requested file, for every ensemble, was found and written.
- pyretis.testing.example_compare.main(argv=None)¶
Command-line entry point for the shared example comparison.
Subcommands¶
compare <config.toml>Compare one completed run against its committed
results/reference (golden files + task-appropriate structural checks; override with--checks/--ref-dir).zero-left <nozero_dir> <withzero_dir>Check the two-run
zero_leftbehavioural contract.restart-whole <config> <restart_dir> <full_dir>Check a whole-file restart reproduces the uninterrupted run.
restart-concat <part1_dir> <part2_dir> <full_dir>Check a two-part concatenated restart equals the full run.
restart-md --traj P1 P2 FULL --text P1 P2 FULL ...Check a concatenated MD restart (trajectory + text files).
reconstruct-traj <config.toml>Reconstruct fragmented
traj.txtfiles beforecompare.generate-golden-tarball <config.toml> <output.tgz> --files ...Re-bless a tarball-form golden reference from the run’s own output.
- pyretis.testing.example_compare.reconstruct_traj_for_run(config_path, run_dir=None)¶
Reconstruct every ensemble’s fragmented
traj.txtfor a run.A thin per-run driver over
reconstruct_trajectory_text(): some engines (e.g. LAMMPS) scatter an ensemble’s trajectory across per-trial fragments instead of writing a singletraj.txtat the ensemble root, so a folder that commitstraj.txtas a golden file (seecompare_ensemble_files_golden()) must reconstruct it before comparing – run this once, right after the simulation and beforecompare.- Parameters:
config_path (str) – The simulation config (
.toml) the run used.run_dir (str, optional) – Where the run produced its per-ensemble output (default: the config’s directory).
- Returns:
int – The number of ensembles whose
traj.txtwas (re)written (0 is not an error by itself – an ensemble whose engine never fragments its trajectory has nothing to reconstruct).
pyretis.testing.reference_manifest module¶
Validate provenance and content digests for numerical references.
- pyretis.testing.reference_manifest._artifact_path(root, relative)¶
Resolve one safe repository-relative artifact path.
- pyretis.testing.reference_manifest._content_sha256(path)¶
Hash a file without loading the complete artifact into memory.
- pyretis.testing.reference_manifest._required_text(mapping, key, context)¶
Return a required non-empty string from a manifest object.
- pyretis.testing.reference_manifest._validate_artifact_digests(artifact_set, name, root)¶
Compare one set’s declared digests against the on-disk artifacts.
- pyretis.testing.reference_manifest._validate_artifact_set(artifact_set, name, context, root)¶
Validate one artifact set’s provenance fields and content digests.
- pyretis.testing.reference_manifest._validate_energy_term_list(terms, context)¶
Validate one explicit list of unavailable physical quantities.
Validate global or per-ensemble unavailable-energy declarations.
- pyretis.testing.reference_manifest.calculate_artifact_set(root, paths)¶
Calculate a deterministic digest and inventory for artifact paths.
Directory inputs are expanded recursively. The tree digest includes each repository-relative path, byte count, and file-content SHA-256 digest, in lexicographic path order. Overlapping path declarations are rejected.
- Parameters:
root (path-like) – Repository root used to resolve the relative paths.
paths (sequence of str) – Files or directories included in one reference artifact set.
- Returns:
dict –
tree_sha256,file_count, andbyte_countvalues suitable for the manifest’sartifactsobject.
- pyretis.testing.reference_manifest.main(argv=None)¶
Run reference-manifest validation from the command line.
- pyretis.testing.reference_manifest.validate_manifest(manifest_path, root=None)¶
Validate manifest schema, provenance fields, and artifact digests.
- Parameters:
manifest_path (path-like) – JSON provenance manifest to validate.
root (path-like, optional) – Repository root. By default this is inferred for the canonical
examples/tests/reference_provenance.jsonlocation.
- Returns:
list of str – Names of the artifact sets successfully validated.
pyretis.testing.simulation_comparison module¶
Methods for comparing simulation results.
This module defines methods that can be used for comparing results from different simulations, such as output files, reports, and path ensembles.
- pyretis.testing.simulation_comparison._compare_block_comments(comment1, comment2)¶
Compare two block comment lists, tolerating 1-ULP float differences.
- Parameters:
comment1 (list of str) – Comment lines from the first file block.
comment2 (list of str) – Comment lines from the second file block.
- Returns:
bool – True if the comments are considered equal.
- pyretis.testing.simulation_comparison._files_agree_over_common_prefix(file1, file2)¶
Check two binary files agree byte-for-byte over their common prefix.
Engine frame payloads (e.g. GROMACS
.trrsegments) may carry unreferenced TRAILING surplus frames: the propagation dump interval does not stop exactly at the frame the path keeps, and how much surplus is written is not reproducible between two runs (the ratified init-procedure rule: logic preserved, not byte-identical). The frames a path actually references are pinned by itstraj.txt, which is compared exactly and separately. A rewrite, corruption, or genuine divergence of trajectory data shows up inside the common prefix and still fails.- Parameters:
file1 (str) – The path to the first file to compare.
file2 (str) – The path to the second file to compare.
- Returns:
equal (bool) – True if the files agree over their whole common prefix.
surplus (bool) – True if the files agree but one carries trailing surplus bytes.
- pyretis.testing.simulation_comparison._read_file_lines(filepath)¶
Read all lines from a file.
- pyretis.testing.simulation_comparison.compare_data_by_columns(file1, file2, file_type, skip=None)¶
Compare two output PyRETIS data files by columns.
This method compares files where numbers are stored in columns and the columns have specific labels. Here, we also compare labels and comments.
- Parameters:
file1 (str) – The path to the first file to compare.
file2 (str) – The path to the second file to compare.
file_type (str) – A string used to determine the file type (e.g., ‘energy’).
skip (list of str, optional) – A list of items from the loaded data we are to skip. This can, for instance, be certain energy terms that are not absolute and can’t easily be compared.
- Returns:
equal (bool) – True if the files are deemed to be equal.
msg (str) – A descriptive message of the result of the comparison.
- pyretis.testing.simulation_comparison.compare_energy_columns_mse(energy, reference, pairs, tol=1e-05)¶
Per-term MSE check of a pyretis
energy.txtarray vs an engine’s.The
test-integrateexample comparators (cp2k, gromacs) share this: each checks that pyretis reproduces the engine’s own energies term by term, differing only in whichenergy.txtcolumn maps to which engine-output key.- Parameters:
energy (numpy.ndarray) – The pyretis
energy.txtdata (asnumpy.loadtxt()returns; columns cycle, vpot, ekin, etot, temp, …).reference (mapping of str to numpy.ndarray) – The engine’s energies keyed by term name (the keys used in
pairs).pairs (sequence of (int, str)) –
(column_index_in_energy, reference_key)pairs to compare, e.g.((1, 'vpot'), (2, 'ekin'), (3, 'etot'), (4, 'temp')).tol (float, optional) – Per-term MSE tolerance; a falsy
tolreports the MSEs without judging them.
- Returns:
equal (bool) – True when every compared term matches in length and (if
tol) is within tolerance.msg (str) – The per-term MSEs, plus the failing term / tolerance on failure.
- pyretis.testing.simulation_comparison.compare_energy_data(file1, file2, rel_tol=1e-05, unavailable_terms=None)¶
Compare two
energy.txtfiles with explicit unavailable terms.Energy files always carry a fixed set of columns (time, potential, kinetic, total, temperature), but not every engine or path populates all of them: paths loaded from disk carry no computed energy, and an engine may not report e.g. the total energy or the temperature. Such a term is written as an entirely-NaN column.
This wraps
compare_numerical_data()with energy-specific handling of those columns. Unavailable physical quantities must be named by the caller; matching all-NaN columns are not inferred as a success:A term named in
unavailable_termsmust be entirely NaN in both files and is then excluded from the numerical comparison.An all-NaN term that was not declared is an unexpected coverage gap and fails.
Every other column is compared normally. A column that is all-NaN in only one file (a run that suddenly computes – or stops computing – a term) therefore still fails, via the NaN-position check, rather than being silently skipped.
- Parameters:
file1 (str) – The path to the first file to compare.
file2 (str) – The path to the second file to compare.
rel_tol (float, optional) – Relative tolerance forwarded to
compare_numerical_data().unavailable_terms (sequence of str, optional) – Energy terms that this reference intentionally cannot provide. Valid names are
vpot,ekin,etot, andtemp.
- Returns:
equal (bool) – True if the files are deemed to be equal.
msg (str) – A descriptive message of the result of the comparison.
- pyretis.testing.simulation_comparison.compare_numerical_data(file1, file2, rel_tol=1e-05, skip_cols=None)¶
Compare two files containing numerical data.
Here, we compare files that contain numerical data. We don’t care about comments here, we just compare the actual numerical data.
A meaningful comparison must not pass on degenerate input. This rejects empty data, shape mismatches, NaNs that sit at different positions in the two files (a divergence that turned a finite value into NaN or vice versa), and data/columns that are entirely NaN (which test nothing). Partial NaN at matching positions – e.g. loaded (
ld) frames that legitimately have no computed energy – is allowed; the finite values around them are still compared. Columns that are unavailable for an engine (e.g. a potential energy that engine never reports) must be excluded explicitly viaskip_colsso the gap is visible rather than silently “equal”.- Parameters:
file1 (str) – The path to the first file to compare.
file2 (str) – The path to the second file to compare.
rel_tol (float, optional) – Relative tolerance for the comparison.
skip_cols (list of int, optional) – Column indices to exclude from the comparison (e.g. a column an engine does not populate). Excluding a column is explicit and visible, unlike letting NaN==NaN pass.
- Returns:
equal (bool) – True if the files are deemed to be equal.
msg (str) – A descriptive message of the result of the comparison.
- pyretis.testing.simulation_comparison.compare_numerical_mse(file1, file2, tol=1e-12)¶
Compare two numerical files using mean squared error.
- Parameters:
file1 (str) – The path to the first file to compare.
file2 (str) – The path to the second file to compare.
tol (float, optional) – Tolerance for the mean squared error.
- Returns:
equal (bool) – True if the MSE is below the tolerance.
msg (str) – A descriptive message with the MSE value.
- pyretis.testing.simulation_comparison.compare_path_ensemble_data(file1, file2, rel_tol=1e-05, skip=None)¶
Compare two path ensemble files.
We compare line-by-line, but skip comments and we check that numbers are close, as judged by the given relative tolarance.
- Parameters:
file1 (str) – The path to the first file to consider in the comparison.
file2 (str) – The path to the second file to consider in the comparison.
rel_tol (float, optional) – A relative tolerance used to determine if numbers are equal.
skip (list of int, optional) – These are columns we are to skip in the comparison.
- Returns:
equal (bool) – True if the files are equal, False otherwise.
msg (str) – A message describing the result of the comparison.
- pyretis.testing.simulation_comparison.compare_reports_normalized(fil1, fil2)¶
Compare two reports, normalizing common version/time differences.
This function ignores Docutils version meta-data, timestamps, and common spelling variations (grey/gray) in CSS to remain robust against environment differences.
- Parameters:
fil1 (str) – The path to the first report to compare.
fil2 (str) – The path to the second report to compare.
- Returns:
equal (bool) – True if reports are essentially equal.
msg (str) – Description of mismatch if found.
- pyretis.testing.simulation_comparison.compare_restarted_cross_files(file11, file12, file2)¶
Compare CrossFile data from a restarted simulation.
- Parameters:
file11 (str) – Path to the first part of the crossing data.
file12 (str) – Path to the second part of the crossing data.
file2 (str) – Path to the full (continuous) crossing data.
- Returns:
equal (bool) – True if the crossing data matches.
msg (str) – A descriptive message.
- pyretis.testing.simulation_comparison.compare_restarted_text_files(file11, file12, file2)¶
Check if file2 is equal to file11 + file12 minus one overlapping line.
We handle headers (lines starting with ‘#’) by skipping them in the second file part.
- Parameters:
file11 (str) – Path to the first part of the restarted simulation output.
file12 (str) – Path to the second part of the restarted simulation output.
file2 (str) – Path to the full (continuous) simulation output.
- Returns:
equal (bool) – True if the files match the pattern.
msg (str) – A descriptive message of the result.
- pyretis.testing.simulation_comparison.compare_simulation_files(file1, file2, skip=None, mode='line')¶
Top-level function to compare two simulation output files.
- Parameters:
file1 (str) – The path to the first file to compare.
file2 (str) – The path to the second file to compare.
skip (list of str or list of int, optional) – A list of items that are to be skipped in the comparison.
mode (str, optional) – A string used to determine how we do the comparison: ‘numerical’ will select a comparison of numerical blocks; ‘line’ will select a line-by-line text comparison; anything else will perform a literal file comparison.
- Returns:
equal (bool) – True if the files were found to be equal, False otherwise.
msg (str) – A string with information about the comparison result.
- pyretis.testing.simulation_comparison.compare_text_line_by_line(file1, file2, skip=None, skip_keys=None)¶
Compare two files, line by line.
- Parameters:
file1 (str) – The path to the first file to compare.
file2 (str) – The path to the second file to compare.
skip (list of int, optional) – These are 0-indexed line numbers we are to skip.
skip_keys (list of str, optional) – Lines whose first token matches any key in this list are filtered out from both files before comparison. Useful for ignoring settings like
exe_paththat differ by run directory.
- Returns:
equal (bool) – True if the files are deemed to be equal.
msg (str) – A descriptive message of the result of the comparison.
- pyretis.testing.simulation_comparison.compare_traj_archive(dir1, dir2)¶
Compare archived trajectories between two directories.
These archives consist of trajectory information such as energies, order parameters and positions. Here, we verify that the output written by PyRETIS is identical in the two cases.
- Parameters:
dir1 (str) – The path to the first directory to use in the comparison.
dir2 (str) – The path to the second directory to use in the comparison.
- Returns:
errors (list of tuple) – This list contains the files which differed, if any. A directory that is absent on either side is reported as a difference, never silently equated: two non-existent archives would otherwise both yield empty file lists and be judged “equal”.
- pyretis.testing.simulation_comparison.compare_traj_archive_soft(dir1, dir2, energy_skip=None, frames='byte')¶
Compare an archived trajectory, tolerating named energy terms.
Like
compare_traj_archive()(byte-exact for every archived file), with engine-facing relaxations for the run-vs-run self-consistency suites:an archived
energy.txtfragment is compared by column instead of byte-for-byte, skipping the named terms inenergy_skip. Some external engines recompute a term (e.g. GROMACS’s long-range dispersion correction to the potential energy) slightly differently when continuing a run;with
frames='byte'(the default), engine frame payloads (any file that is not one of the PyRETIS-writtenenergy.txt/order.txt/traj.txt) must agree byte-for-byte over their COMMON PREFIX – trailing unreferenced surplus frames are logged and tolerated (see_files_agree_over_common_prefix());with
frames='names', frame payloads are checked by name and count only. This is for comparisons across DIFFERENT engine implementations of the same MD (e.g. the relaunch vs streaming GROMACS engines), whose physics text output is exact-equal while their archived payload framing (frame counts, dump cadence) is implementation-specific and never byte-comparable.
- Parameters:
dir1 (str) – The path to the first directory to use in the comparison.
dir2 (str) – The path to the second directory to use in the comparison.
energy_skip (list of str, optional) – Energy terms (as read by
EnergyPathFile, e.g.'vpot') to exclude from the comparison of any archivedenergy.txtfragment.Nonecompares every term.frames (str, optional) –
'byte'(default) or'names'; see above. The PyRETIS-written text files are compared exactly in BOTH modes.
- Returns:
errors (list of tuple) – The files which differed, if any (see
compare_traj_archive()for the missing-directory behaviour).
- pyretis.testing.simulation_comparison.read_files(*files, read_comments=True)¶
Read files into memory.
Here, we assume that we are given small files and that we can read these into memory.
- Parameters:
files (tuple of str) – These are the paths to the files we are to read.
read_comments (bool, optional) – If False, we skip lines starting with a “#”.
- Returns:
all_data (list of list of str) – The data read from the different files.
- pyretis.testing.simulation_comparison.reconstruct_trajectory_text(ensemble_dir)¶
Reconstruct a consolidated
traj.txtfrom per-trial fragments.Some engines (e.g. LAMMPS) write one
traj.txtfragment per accepted trial, nested under<ensemble_dir>/traj/<trial>/, rather than a single runningtraj.txtat the ensemble root the way most engines do. Each fragment’s first line carries a# Cycle:<n>, ...header; concatenating the fragments in ascending cycle order reconstructs the same<ensemble_dir>/ traj.txta non-fragmenting engine would have written directly, so the two can be compared with the same golden-file logic.- Parameters:
ensemble_dir (str) – Path to a single ensemble’s output directory (e.g.
.../000).- Returns:
written (bool) – True if at least one fragment was found and
traj.txtwas (re)written; False if<ensemble_dir>/trajdoes not exist or holds notraj.txtfragment, in which case nothing is written (the ensemble has no fragmented trajectory to reconstruct – not a failure by itself).
pyretis.testing.helpers module¶
Methods that might be useful for testing.
This module defines generic methods for testing.
- pyretis.testing.helpers.VALIDATE_ENV = 'PYRETIS_VALIDATE'¶
Environment variable that turns the numerical reference comparison on (
"1", the default) or off ("0"). It is set to"0"by the engine test runners when only a non-reference-grade external MD engine is available (for example a single-precision GROMACS build when the reference data was generated in double precision). External MD engines are not bit-for-bit reproducible across build, precision and hardware, so a reference comparison is only meaningful against the exact reference-grade engine.
- pyretis.testing.helpers.clean_dir(dirname)¶
Remove ALL files in the given directory.
- pyretis.testing.helpers.reference_validation_enabled()¶
Return whether numerical reference comparison should be performed.
- Returns:
out (boolean) –
Trueunless thePYRETIS_VALIDATEenvironment variable is set to"0". The default (variable unset) isTrueso that the validated path is unchanged when a reference-grade engine is present.
- pyretis.testing.helpers.search_for_files(rootdir, match=None)¶
Find files by walking the given directory.
- Parameters:
rootdir (string) – The path where we will search from.
match (string, optional) – If given, the method will only return files that are equal to the given match.
- Returns:
out (list of strings) – The paths of the found files.
- pyretis.testing.helpers.skip_reference_validation(reason)¶
Report that the run was executed but not numerically validated.
This prints a clearly labelled
NOT VALIDATEDmessage and exits with status0. It is used by the engine test scripts as the “execution smoke” outcome: the simulation ran without error, but the numerical comparison against the committed reference was skipped because no reference-grade engine was available. Following the project rule “better a fail than a wrong pass”, a skipped comparison is never reported as a pass.- Parameters:
reason (string) – Why the numerical comparison was skipped (for example
"single-precision GROMACS; reference is double precision").
pyretis.testing.systemhelp module¶
Methods that might be useful for testing.
This module defines methods that are useful in connection with systems.
- pyretis.testing.systemhelp.create_system_ext(pos=None, vel=False)¶
Create an external system with given positions and velocities.