Merge
merge_simulation_files combines multiple scene JSON files that share the same
bodies/terrain into one scene with extra batches, resampling every file but the
first onto the first file's timeline by nearest timestamp. Pass selections to
take only some of a file's batches (the CLI spells this file.json#1,3). See
Comparing multiple runs
for the CLI-facing version of this.
simview.merge.merge_simulation_files
merge_simulation_files(
paths: Sequence[str | Path],
selections: Sequence[str | Sequence[int] | None]
| None = None,
) -> dict
Load and merge paths into a single {"model": ..., "states": ...} dict
where each file's batches are concatenated into the output's batch dimension.
selections, if given, must be parallel to paths: each entry is None
(contribute every batch of that file) or a batch selector -- a string like
"1", "0,2", "1-3", "-1" or a batch name, or an explicit
sequence of indices (see parse_batch_selection). Selecting a subset is
what lets several files that each carry the same ground-truth batch be
merged without duplicating it, and it is the one case where a single file
is a valid merge input.
simview.merge.parse_batch_selection
parse_batch_selection(
selector: str | Sequence[int],
batch_size: int,
batch_names: Sequence[str] | None,
label: str,
) -> list[int]
Resolve one file's batch selector to a list of that file's batch indices.
selector is either an explicit sequence of indices or a comma-separated
string whose entries are an index (2), a negative index counting from
the end (-1), an inclusive range (0-3), or one of the file's own
batchNames. Anything that parses as an index or a range is read as such,
so a batch named "2" can only be selected by its index. The selected
order is the merged order, and selecting the same batch twice is rejected
as a typo rather than silently duplicating it.
simview.merge.split_batch_spec
Split a CLI input like scene.json#1,3 into ("scene.json", "1,3"),
or return (spec, None) when it names no batch subset.
Purely syntactic apart from one filesystem check: an existing local file
wins over the selector reading (mirroring remote.is_remote_spec), so a
file literally named odd#name.json still opens as itself.