Event logs¶
Event-log levels, fingerprints, event and trace tables.
handoverlab.eventlog
¶
Event logs: fingerprints and tables.
An event log has one row per handover attempt and per link failure without a
handover (see EVENT_FIELDS). Times are rounded to 0.1 ms, gains and
offsets to 0.001 dB and positions to 0.1 m when the engine writes a row.
Fingerprint
The SHA-256 of the canonical CSV of a log: a header with the field
names, then one line per row in log order, fields separated by commas,
numbers written with Python's shortest round-trip representation
(repr(float); -0.0 is written as 0.0), lines ending in \n.
It does not depend on how the log was stored (CSV, Parquet, memory), so
a stored log can be checked against a recomputed one on any machine.
Levels
How much a run keeps (LEVELS, event_level):
off metrics and the fingerprint only (the default; tuning stages);
summary the event log above (RunResult.events);
full the event log plus a *trace* of the procedure
(RunResult.trace, TRACE_FIELDS): the initial
serving cell of every user, measurement reports,
preparations, releases, configurations reaching the UE or
lost, executions, attachments after a handover or a
re-establishment, and failures. The trace gives the serving
cell of every user at any time (serving_cells).
The level never changes a result or the fingerprint: the fingerprint is
always that of the summary log.
Tables
write_events writes the logs of several runs as one table with the
columns seed, rule and EVENT_FIELDS: Parquet (typed
columns, needs pyarrow) for a .parquet file name, CSV otherwise.
read_events reads either back; write_trace and
read_trace do the same for traces.
event_level(value: Any) -> str
¶
Normalise an event-log level.
False/None -> "off", True -> "summary", or a name of LEVELS.
canonical_csv(events: Iterable) -> str
¶
Canonical CSV text of an event log (rows as dictionaries or tuples in EVENT_FIELDS order).
fingerprint(events: Iterable) -> str
¶
SHA-256 (hex) of the canonical CSV of an event log.
parquet_available() -> bool
¶
True if pyarrow can be imported (needed for Parquet files).
to_columns(results: Sequence) -> Dict[str, list]
¶
Event logs of results (RunResult with events) as columns.
write_events(results: Sequence, path: str) -> str
¶
Write the event logs of results to path and return the path written.
.parquet writes Parquet if pyarrow is installed; without it the
table is written as CSV next to it (.csv instead of .parquet) and a
warning is issued. Any other name writes CSV.
read_events(path: str) -> List[dict]
¶
Rows of an event table written by write_events (typed values, in file order).
write_trace(results: Sequence, path: str) -> str
¶
Write the traces of results (runs at level full) as one table; returns the path written.
Columns: seed, rule and TRACE_FIELDS; Parquet or CSV as
in write_events.
read_trace(path: str) -> List[dict]
¶
Rows of a trace table written by write_trace (typed values, in file order).
trace_path(events_path: str) -> str
¶
Name of the trace table that goes with an event table: events.parquet -> events-trace.parquet.
serving_cells(trace: Iterable[dict], n_users: int, times: Sequence[float])
¶
Serving cell of every user at times from a trace: an array (len(times), n_users).
-1 while a user is executing a handover or re-establishing (not connected).
group_logs(rows: Iterable[dict]) -> Dict[Tuple[int, str], List[dict]]
¶
Rows of an event table -> {(seed, rule): event log}.