Opp repl result analysis
Read simulation scalar / vector / histogram results from a completed run. On current opp_repl (>= commit 2e6835e, Apr 2026), `SimulationTaskResult` and `MultipleSimulationTaskResults` expose `get_scalars()`, `get_vectors()`, and `get_histograms()` methods that return pandas DataFrames directly. Fallbacks: `opp_scavetool` CLI (for shell / CI) and the `omnetpp.scave.results` Python API (for older opp_repl). Load whenever a workflow needs to compare simulation output against analytical/reference values, aggregate across replications, or feed numbers into pandas/numpy.From its SKILL.md
npx -y skills add tabgab/opp_repl-skill --skill opp-repl-result-analysisAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
9.3 KB, ~2.3k tokens by cl100k_base, as published. Nobody here has run it
Analyzing OMNeT++ simulation results
On current opp_repl main, reading results from a completed
run_simulations() is a one-liner — .get_scalars() / .get_vectors()
/ .get_histograms() on the result object returns pandas DataFrames
ready for aggregation. For older opp_repl or for external / CLI
scripting, use opp_scavetool or the scave Python API directly.
| Approach | Use when |
|---|---|
(A) r.get_scalars() etc. | Current opp_repl, inside the REPL / MCP. |
(B) opp_scavetool CLI | Shell scripts, CI, agents without Python deps |
(C) omnetpp.scave.results | Direct scave API (older opp_repl, more control) |
Path A — result-object methods (current opp_repl)
Per-run (one SimulationTaskResult)
r = run_simulations(simulation_project=p, sim_time_limit="100s")
tr = r.results[0]
df = tr.get_scalars() # .sca -> DataFrame
df = tr.get_scalars(include_fields=False) # skip statistic fields
df = tr.get_scalars(include_runattrs=True) # add run attributes as columns
df = tr.get_vectors() # .vec -> DataFrame
df = tr.get_histograms() # histograms from .sca
Docstrings quote the exact signatures:
get_scalars(include_fields=True, include_runattrs=False, **kwargs)
get_vectors(include_runattrs=False, **kwargs)
get_histograms(include_runattrs=False, **kwargs)
Aggregated (one MultipleSimulationTaskResults)
r = run_simulations(simulation_project=p, sim_time_limit="100s")
df = r.get_scalars() # concatenated across all DONE runs
df = r.get_vectors() # same
df = r.get_histograms() # same
MultipleSimulationTaskResults.get_*() skips any non-DONE result
(an FAILed / ERRORed task contributes nothing) and concatenates the
remaining per-run DataFrames with ignore_index=True.
Typical aggregation pattern
df = r.get_scalars()
means = df.groupby("name").value.mean()
sems = df.groupby("name").value.sem() # if you want error bars
# Per-module, per-metric
agg = df.groupby(["module", "name"]).value.mean()
Columns in the returned DataFrame: runID, module, name, value,
configname, experiment, inifile, network, repetition,
runnumber, seedset, plus whatever run attributes the simulation
emitted. include_runattrs=True adds extra run-attr columns.
Reference: https://github.com/omnetpp/opp_repl/blob/main/doc/task_results.md#reading-simulation-results
Path B — opp_scavetool CLI
The opp_scavetool binary queries and exports .sca / .vec
files. Useful when you want CSV / JSON for an external pipeline or
when omnetpp is not importable in the calling Python process.
Query: list result items
opp_scavetool query -l results/*.sca # list all items
opp_scavetool query -n -T s results/*.sca # unique scalar names
opp_scavetool query -l -p -g --tabs results/*.sca # per-run, machine-readable
Export to CSV-R (records, Pandas-friendly)
opp_scavetool export -F CSV-R \
--add-fields-as-scalars \
-o scalars.csv \
results/*.sca
CSV columns include: run, type, module, name, value, count, mean, stddev, min, max, vectime, vecvalue ...
Export to JSON
opp_scavetool export -F JSON -o scalars.json results/*.sca
Index vector files for faster random access
opp_scavetool index results/*.vec
Filter expressions
opp_scavetool query -l --filter 'name("dropCount")' results/*.sca
opp_scavetool query -l --filter 'module("*queue*")' results/*.sca
Run opp_scavetool help filter for the full grammar.
Path C — omnetpp.scave.results Python API
This module is bundled with every OMNeT++ install at
$__omnetpp_root_dir/python/omnetpp/scave/results.py. After
sourcing OMNeT++'s setenv, its path is on PYTHONPATH.
from omnetpp.scave.results import (
read_result_files, # load .sca/.vec into internal table
get_scalars, # DataFrame of scalars
get_vectors, # DataFrame of time-series
get_statistics, # aggregated statistics
get_histograms, # histograms
get_parameters, # NED parameter assignments
get_runs, # run metadata
get_runattrs, # per-run attributes
get_itervars, # iteration variables
)
df = read_result_files("results/*.sca",
include_fields_as_scalars=True)
scalars = get_scalars(df, include_runattrs=True)
r.get_scalars() (path A) is a thin wrapper over this; use path C
directly when you need read_result_files glob / filter parameters
that the task-result method doesn't expose.
Bundled helper script (for shells / MCP / external agents)
scripts/parse_scalars.py wraps both paths B and C so any caller
can get scalars out of a results directory without needing to reason
about which path is available:
python3 scripts/parse_scalars.py results/
python3 scripts/parse_scalars.py results/ --filter 'name("dropCount")'
python3 scripts/parse_scalars.py results/ --group-by name --output table
The script sets up $__omnetpp_root_dir/python on PYTHONPATH
itself, tries the Python API first, falls back to opp_scavetool
on ImportError. Outputs valid JSON (NaN-clean), CSV, or ASCII
table.
Use the script when:
- An external agent (not running inside opp_repl) needs scalars.
- You're in a shell script / Makefile / CI that doesn't call Python.
- You want a language-neutral command-line probe during debugging.
When you're already inside opp_repl, prefer r.get_scalars() — same
result, no subprocess.
Raw .sca file format
.sca is line-oriented text. Keywords per line:
version 3
run PureAloha1-0-20260420-13:30:58-35234
attr configname PureAloha1
config cpu-time-limit 1s
param Aloha.host[*].iaTime exponential(2s)
scalar Aloha.host[0] channelUtilization 0.1234
statistic Aloha.server collisionLength:mean 0.0456
field Aloha.server collisionLength:mean:count 123
Do NOT write a regex parser — the format has edge cases (quoting, multi-line histograms, encoding) that make hand-rolled parsers fragile. Always go through scavetool or the Python API.
Integrating with opp_repl results
Each SimulationTaskResult exposes file paths too, for cases the
.get_*() methods don't cover:
tr.stdout_file_path # e.g. "results/General-#0.out"
tr.scalar_file_path # e.g. "results/General-#0.sca"
tr.vector_file_path # e.g. "results/General-#0.vec"
tr.eventlog_file_path # eventlog, if recorded
To feed these into scavetool / read_result_files manually:
p = tr.task.simulation_config.simulation_project
working_dir = tr.task.simulation_config.working_directory
sca_path = p.get_full_path(working_dir + "/" + tr.scalar_file_path)
But 9 times out of 10 tr.get_scalars() is what you want.
Pitfalls
.vecneeds indexing for random access — the.vecfiles written by the simulation don't have a.vciindex untilopp_scavetool indexruns (or any export / get_vectors call reads them). Large batches — index once after the batch finishes.- Replications aren't auto-averaged —
r.get_scalars()returns one row per (run, module, name). Aggregate explicitly:df.groupby(["module","name"]).value.mean(). include_fields=True(the default ontr.get_scalars()) unpacks statistic fields (count, mean, stddev, min, max) as individual scalar rows. For run comparisons that's usually what you want. For raw per-@statisticqueries, passinclude_fields=False.- Large
.vecfiles — an unfilteredr.get_vectors()loads every timestamp into memory. Filter at the scavetool level first when working with long time-series:opp_scavetool export -F CSV-R --filter 'name("throughput")' -o thr.csv results/*.vec. - Result dir vs working dir —
results/is ALWAYS relative to the simulation's working directory, not the project root or the CWD of the REPL. Usesimulation_project.get_full_path(...)when building paths manually. - ERRORed runs contribute nothing —
MultipleSimulationTaskResults.get_*()silently skips non-DONE results. Checkr.is_all_results_done()orr.get_error_results()first if your aggregation looks off.
See also
opp-repl-running-simulations— produces the .sca / .vec files.opp-repl-tasks-and-results— fullSimulationTaskResultAPI.opp-repl-project-scaffolding— getting to a state where .sca files exist in the first place.opp-repl-troubleshooting— when runs fail before producing results.
What ships with it: 1 file
6.4 KB alongside SKILL.md, 1 of them executable
scripts/
- parse_scalars.pyruns6.4 KB
Gives 0 of the 12 instructions most research analysis skills give in ~2.3k tokens
Counted across 1,063 of the 1,754 authors here whose files we hold, read 2026-08-07
- Generate a markdown reportin 32 of 1063, across 23 files
- Cite each claim's sourcein 30 of 1063, across 15 files
- Define the ideal customer profilein 20 of 1063, across 2 files
- Search for companies matching the criteriain 20 of 1063, across 2 files
- Assign a fit score from one to tenin 20 of 1063, across 2 files
- Analyze the codebase to understand the productin 19 of 1063, across 1 file
- Ask clarifying questions about the value propositionin 19 of 1063, across 1 file
- Look for signals of immediate needin 19 of 1063, across 1 file
- Identify the target decision maker rolein 19 of 1063, across 1 file
- Suggest a personalized contact strategyin 19 of 1063, across 1 file
- Provide conversation starters for outreachin 19 of 1063, across 1 file
- Format results in a scannable markdown templatein 19 of 1063, across 1 file
Said here and by no other author read
- use result-object methods inside the repl
- use opp_scavetool cli in shell scripts
- aggregate replications explicitly via pandas
- index vector files before random access
- verify all runs are done before aggregating
- filter large vector files before loading
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.