Create a self-contained bottle archive from a registered run.
By default, copies data files into the archive and raises if any are missing. Use omit_jshd=True for lightweight archives when the recipient has the data locally.
Detect run<->analysis drift between the execution and data tables.
Guards the principle that the registry (analysis) must reflect what running produced. Checks (scoped to run_hash if given, else all runs):
data_without_config — cell_data for a run_hash with no job_configs row (orphaned data; error).
orphan_cell_data — cell_data whose run_id is absent from job_runs (the FK should prevent this; error if seen).
duplicate_replicate — a (run_hash, replicate) present under more than one run_id (row inflation from a pre-fix re-ingest; error).
ran_not_ingested — a run_hash with a succeeded job_runs row but no cell_data (ran but results never loaded; warning).
Parameters
Name
Type
Description
Default
run_hash
str | None
Limit the check to one run, or None for the whole registry.
None
strict
bool
If True, raise RuntimeError when any issue is found.
False
Returns
Name
Type
Description
list[ConsistencyIssue]
A list of :class:ConsistencyIssue (empty if consistent).
Raises
Name
Type
Description
RuntimeError
If strict and any issue is found.
check_sparsity
registry.RunRegistry.check_sparsity()
Check for sparse columns in cell_data.
Sparse columns (>50% NULL by default) often indicate that different simulation types are being mixed in the same registry, which hurts query performance.
Returns
Name
Type
Description
SparsityReport
SparsityReport with statistics for each variable column.
Job configuration containing simulation, template, and sweep info. Must have simulation, template_path, and to_dict() attributes (typically a JobConfig from joshpy.jobs).
required
experiment_name
str | None
Name for the experiment. Defaults to config.simulation.
None
session_id
str | None
Optional externally-provided session ID. If None, generates a UUID. This allows the frontend/API layer to manage session IDs (e.g., using project IDs).
total_jobs and total_replicates are computed from the JobSet after job expansion. Use job_set.total_jobs and job_set.total_replicates.
describe_labels
registry.RunRegistry.describe_labels()
Human-readable listing of all labeled runs.
Convenience wrapper around :func:joshpy.inspect.format_labels.
Returns
Name
Type
Description
str
A formatted table of labels with run_hash and creation time.
describe_run
registry.RunRegistry.describe_run(label_or_hash)
Human-readable detail for a single run.
Convenience wrapper around :func:joshpy.inspect.format_run_info.
Parameters
Name
Type
Description
Default
label_or_hash
str
Label or run_hash of the run to describe.
required
Returns
Name
Type
Description
str
A multi-section detail string (parameters, data files, replicates,
str
and per-run results).
Raises
Name
Type
Description
KeyError
If the label or hash is not found.
describe_sessions
registry.RunRegistry.describe_sessions()
Human-readable listing of all sweep sessions.
Convenience wrapper around :func:joshpy.inspect.format_sessions.
Returns
Name
Type
Description
str
A formatted table of sessions with experiment name, status, and
str
run counts.
describe_summary
registry.RunRegistry.describe_summary()
Human-readable overview of everything in the registry.
Convenience wrapper around :func:joshpy.inspect.format_summary.
Returns
Name
Type
Description
str
A high-level data summary for the whole registry.
drop_run
registry.RunRegistry.drop_run(label_or_hash)
Delete all registry state for a run, so its config can be redone.
This is the only operation that deletes or replaces existing run data. All other registry writes are append-only (runs, cell_data) or metadata (labels, session status). Use this to clear a run before re-running it from scratch — e.g. when a sweep’s outputs are bad and you want a clean slate rather than pooling more replicates onto them.
Removes, in foreign-key order, everything tied to the run’s hash: cell_data, run_outputs, job_runs, config_parameters, session_configs, and the job_configs row (including its label). The owning session row is left intact (it may hold other runs).
Parameters
Name
Type
Description
Default
label_or_hash
str
Label or run_hash of the run to drop.
required
Returns
Name
Type
Description
A
DropSummary
class:DropSummary with per-table deleted-row counts.
Get the number of distinct replicates for a run hash from cell_data.
This is the source-of-truth count, derived from actual loaded data rather than from job_runs metadata. Returns 0 if no data has been loaded yet.
The replicate index is the identity of a replicate: counting distinct replicate values gives the number of replicates loaded for this run, regardless of which execution (run_id) produced each one. Pooled runs dispatch fresh, non-colliding indices, so distinct replicate == total replicates; re-ingesting an already-loaded index is a no-op (see :meth:loaded_replicates).
Parameters
Name
Type
Description
Default
run_hash
str
The run hash to count replicates for.
required
Returns
Name
Type
Description
int
Number of distinct replicates in cell_data.
get_run
registry.RunRegistry.get_run(run_id)
Get run information by ID.
Parameters
Name
Type
Description
Default
run_id
str
The run ID to look up.
required
Returns
Name
Type
Description
RunInfo | None
RunInfo if found, None otherwise.
get_run_info
registry.RunRegistry.get_run_info(label_or_hash)
Get aggregated structured detail for a single run.
Combines :meth:get_config_by_hash, :meth:get_runs_for_hash, and :meth:get_replicate_count into one :class:RunDetail. This is the structured, data-layer counterpart to :meth:describe_run, which formats this same information as a human-readable string.
Parameters
Name
Type
Description
Default
label_or_hash
str
Label or run_hash of the run.
required
Returns
Name
Type
Description
A
RunDetail
class:RunDetail aggregating the config, recorded runs, and
Assign a human-readable label to a run configuration.
Labels are unique within a registry. When a collision occurs, the behavior depends on force and on_collision:
Default: raise ValueError
force=True: silently drop the old label and reassign
on_collision="timestamp": rename the old label with a timestamp suffix (e.g., baseline → baseline_20260402_153000) and assign the bare label to the new run
If True, reassign the label even if already taken.
False
on_collision
str | None
Collision strategy. "timestamp" archives the old label with a timestamp suffix. Mutually exclusive with force.
None
Raises
Name
Type
Description
KeyError
If run_hash does not exist.
ValueError
If label is already assigned to a different run and neither force nor on_collision is set, or if both force and on_collision are set, or if on_collision has an invalid value.
list_config_columns
registry.RunRegistry.list_config_columns()
List all parameter column names in config_parameters.
Returns the dynamically-added parameter columns. Column names preserve original names with special characters (e.g., ‘soil.moisture’).
List all export variable names from simulation outputs.
These are the variables exported by Josh simulations, stored as typed columns in the cell_data table. Variable names preserve original .josh names (e.g., ‘avg.height’).
When session_id is provided, only returns variables that have at least one non-NULL value for runs in that session.
Parameters
Name
Type
Description
Default
session_id
str | None
Optional session ID to filter by. If provided, only returns variables with data in that session.
Load debug messages for a run from registered debug output files.
Parameters
Name
Type
Description
Default
label_or_hash
str
Run label or run_hash.
required
run_id
str | None
Optional explicit run execution ID. If omitted, uses latest.
None
entity_types
list[str] | None
Optional debug entity types to include.
None
existing_only
bool
If True, only load files that currently exist.
True
Returns
Name
Type
Description
Any
DebugMessageStore with messages merged across all selected files.
Raises
Name
Type
Description
KeyError
If run/run execution is not found.
ValueError
If no matching debug files are available.
FileNotFoundError
If existing_only=False and any file is missing.
loaded_replicates
registry.RunRegistry.loaded_replicates(run_hash)
Return the set of replicate indices already loaded for a run hash.
The single source of truth for “what’s already ingested”. Ingestion skips any replicate index already in this set (idempotent re-ingest); the replicate index is the dedup identity.
Parameters
Name
Type
Description
Default
run_hash
str
The run hash to inspect.
required
Returns
Name
Type
Description
set[int]
Set of distinct replicate indices present in cell_data.
query
registry.RunRegistry.query(sql, params=None)
Execute a SQL query with parameters.
This provides direct access to DuckDB for custom queries beyond the pre-built methods. Use this when you need to run complex queries or explore the data in ways not covered by the API.
Parameters
Name
Type
Description
Default
sql
str
SQL query with ? placeholders for parameters.
required
params
list | None
List of parameter values.
None
Returns
Name
Type
Description
Any
DuckDB relation (call .df() for DataFrame, .fetchall() for tuples).
Examples
>>># Get DataFrame>>> df = registry.query(... "SELECT * FROM cell_data WHERE step BETWEEN ? AND ?",... [0, 10]... ).df()
>>># Get raw results>>> rows = registry.query(... "SELECT COUNT(*) FROM cell_data WHERE run_hash = ?",... ["abc123"]... ).fetchone()
Locate the original .jshc file on disk and check if it still matches.
Looks up the session metadata to find the original config_path, then checks whether the file exists and whether its content has changed since it was registered.
Parameters
Name
Type
Description
Default
run_hash
str
The run hash to look up.
required
Returns
Name
Type
Description
A
ConfigSourceInfo
class:ConfigSourceInfo describing the file’s status.
>>># Nested with time filter>>>with registry.spatial_filter(geojson=park_boundary):... with registry.time_filter(step_range=(0, 50)):... df = queries.get_timeseries("height", run_hash="abc123")