metric_sweep — one run, many result rows
Sources: examples/workflow_metric_sweep — settings in workflows/metric_sweep/. This one is not listed in the shipped workflow_settings.yml — add it to the workflows: list to run it:
workflows:
- metric_sweep + channel_gain/*
Some tools do not produce a result, they produce a curve. A BER simulation sweeps its own Eb/N0 axis internally and writes one CSV row per point:
tasks:
- name: main
commands:
- python3 simulate_ber.py --channel_gain ${channel_gain} --ebno_from 1 --ebno_to 3 --ebno_step 0.5
variables:
channel_gain:
type: list
settings:
list: [0.5, 1.0]
Two configurations, five Eb/N0 points each. Taking the first row of the CSV and discarding the rest would throw away most of the run, so multiple: true extracts every row, and a metadata block tags each one with the value it belongs to:
metrics:
FER:
type: csv
multiple: true
settings:
file: results.csv
key: FER
BER:
type: csv
multiple: true
settings:
file: results.csv
key: BER
# "operation" metrics are evaluated once per expanded row, using that row's
# own FER/BER values.
fer_over_ber:
type: operation
settings:
op: "FER / BER"
metadata:
EBNO:
type: csv
multiple: true
settings:
file: results.csv
key: EBNO
The two runs expand into ten result records, each carrying its own EBNO — as if each point had been run as a separate configuration, without paying the cost of ten separate jobs.
Two mechanisms worth separating:
multiple: trueturns one job into several records.metadatais what makes them distinguishable; without it, ten records would share the same identity.type: operationcomputes a metric from other metrics of the same record. Here it is evaluated per row, with that row’s own values — not once for the job.
This is the right shape for any tool with an internal sweep — a simulator stepping through SNR points, a benchmark suite reporting per-test numbers, a profiler with per-function results. Let the tool do the inner loop, and let Odatix do the outer one.