Dashboard logic

The non-visual part of the dashboard (works without Streamlit).

handoverlab.gui

Browser dashboard (optional extra gui): pip install handoverlab[gui], then handoverlab gui.

The dashboard runs on your own computer: handoverlab gui starts a local Streamlit server (default http://localhost:8501) and opens it in the browser. No account, server or domain is needed. It lets you choose a scenario (street grid or open area, speed profile, carrier frequency, path loss, users, run length, seeds) and up to four handover rules with their parameters, runs them with a progress bar, shows the users moving on the layout coloured by their serving cell, charts of handovers, failures and rate, a table of metrics, and offers the results (CSV, JSON, event logs, traces), the figures (PNG) and an experiment file for handoverlab run as downloads.

Only handoverlab.gui.app imports Streamlit; the logic behind it (handoverlab.gui.logic) needs NumPy and matplotlib only, and the core package does not depend on either.

streamlit_args(port: int = 8501, headless: bool = False, address: str = 'localhost') -> List[str]

Command-line arguments of streamlit run for the dashboard.

launch(port: int = 8501, headless: bool = False, address: str = 'localhost', argv: Optional[List[str]] = None) -> int

Start the dashboard server in this process (blocks until it is stopped with Ctrl+C).

handoverlab.gui.logic

Non-visual logic of the dashboard: settings -> configuration, runs, map frames, figures, downloads.

Everything here works without Streamlit (it needs NumPy and, for figures, matplotlib), so it can be tested and reused in scripts and notebooks::

from handoverlab.gui import logic
s = logic.Settings(layout="street_grid", users=20, profile="veh16")
out = logic.run(s, [logic.RuleSettings("a3"), logic.RuleSettings("cho")])
fig = logic.map_figure(out, rule=0, frame=10)
open("metrics.csv", "wb").write(logic.metrics_csv(out))

Settings dataclass

Scenario settings as chosen in the dashboard (defaults: a quick street-grid run).

check() -> List[str]

Problems with these settings (empty if none).

RuleSettings dataclass

One handover rule as chosen in the dashboard; params override the rule's defaults.

Outcome dataclass

Results of a dashboard run: every rule on every seed, and the map data of the first seed.

scenario_dict(s: Settings) -> Dict[str, Any]

Scenario dictionary (as in a configuration file) for dashboard settings.

rule_specs(rules: Sequence[RuleSettings]) -> List[Dict[str, Any]]

Rule specifications with unique names (a number is appended to repeated names).

experiment_dict(s: Settings, rules: Sequence[RuleSettings]) -> Dict[str, Any]

An experiment configuration that handoverlab run repeats exactly.

run(s: Settings, rules: Sequence[RuleSettings], frame_s: float = 0.5, progress: Optional[Callable[[float, str], None]] = None) -> Outcome

Run every rule on every seed (the first seed with the full event-log level for the map).

progress(share, text) is called while the run proceeds (share from 0 to 1).

counts_until(out: Outcome, rule: int, t: float) -> Dict[str, int]

What happened to the users of the first seed up to time t under one rule (warm-up included).

summary_rows(out: Outcome) -> List[Dict[str, Any]]

Mean of every table metric per rule over the seeds (with the number of seeds).

comparison_rows(out: Outcome, metrics: Sequence[str] = tuple(CHART_METRICS), level: float = 0.95) -> List[Dict[str, Any]]

Every rule against the first one, metric by metric: means, their t intervals over the seeds and the paired difference with its interval (the same statistics as the study report; needs two or more seeds for the intervals).

comparison_figure(out: Outcome, metrics: Sequence[str] = tuple(CHART_METRICS), level: float = 0.95)

One panel per metric: mean of every rule with its confidence interval over the seeds.

event_points(out: Outcome, rule: int = 0) -> Dict[str, np.ndarray]

Places of the handovers, unnecessary handovers and failures of the first seed under one rule.

events_map_figure(out: Outcome, rule: int = 0)

The paths of the users of the first seed with the places of handovers, unnecessary handovers and failures under one rule.

study_status_lines(folder: str) -> List[str]

What handoverlab status prints for a study folder, or the reason it cannot be read.

cell_colours(sites: np.ndarray, n_colours: int = 8) -> List[int]

Colour slot of every cell such that near cells get different slots (greedy, nearest first).

With more cells than colours a slot repeats only between cells that are far apart; the map also draws a line from every user to its serving site and labels the sites, so identity never rests on colour alone.

map_figure(out: Outcome, rule: int = 0, frame: int = 0, tail: int = 6)

Users on the layout at one frame, coloured by serving cell (grey: executing or re-establishing).

metrics_figure(out: Outcome, metrics: Sequence[str] = tuple(CHART_METRICS))

One small panel per metric: mean per rule over the seeds, with the range of the seeds.

causes_figure(out: Outcome)

Failures per UE-minute by cause, one row per rule (mean over the seeds).

timeline_figure(out: Outcome)

Cumulative handovers and failures over time on the first seed, one line per rule (two panels).

metrics_csv(out: Outcome) -> bytes

One row per seed and rule: parameters and every metric (as handoverlab run writes it).

results_json(out: Outcome) -> bytes

Settings, the resolved scenario, the rules, every run's metrics and fingerprint, and versions.

events_csv(out: Outcome) -> bytes

Event logs of every run (one row per attempt and per failure without a handover).

trace_csv(out: Outcome) -> bytes

Procedure traces of the first seed (event-log level full).