KPI Decomposition Deep Dive
Break down production, mobilisation, sequencing, and downtime metrics for the tiny7 scenario.
[1]:
import sys
from pathlib import Path
PROJECT_ROOT = Path.cwd().resolve()
while PROJECT_ROOT != PROJECT_ROOT.parent and not (PROJECT_ROOT / "pyproject.toml").exists():
PROJECT_ROOT = PROJECT_ROOT.parent
if not (PROJECT_ROOT / "pyproject.toml").exists():
raise RuntimeError(
"Notebook must be executed within a FHOPS checkout (pyproject.toml not found)."
)
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
import pandas as pd
from docs.examples.analytics import utils
from fhops.evaluation import playback_summary_metrics
from fhops.scenario.io import load_scenario
SCENARIO = PROJECT_ROOT / "examples/tiny7/scenario.yaml"
ASSIGNMENTS = PROJECT_ROOT / "tests/fixtures/playback/tiny7_assignments.csv"
playback_tables = utils.load_deterministic_playback(SCENARIO, ASSIGNMENTS)
Scenario Overview
[2]:
scenario = load_scenario(SCENARIO)
summary_metrics = playback_summary_metrics(playback_tables.shift, playback_tables.day)
pd.Series(summary_metrics)
[2]:
samples 1.000000
total_production 17658.811008
total_hours 576.000000
mobilisation_cost 479.160000
average_utilisation 0.380952
dtype: float64
Production vs Mobilisation
[3]:
prod_metrics = playback_tables.day[["day", "production_units", "mobilisation_cost"]]
prod_metrics
[3]:
| day | production_units | mobilisation_cost | |
|---|---|---|---|
| 0 | 1 | 2007.912755 | 0.00 |
| 1 | 2 | 1438.086529 | 0.00 |
| 2 | 3 | 3193.795810 | 53.24 |
| 3 | 4 | 4047.344153 | 106.48 |
| 4 | 5 | 2969.193965 | 106.48 |
| 5 | 6 | 1595.687799 | 53.24 |
| 6 | 7 | 2406.789997 | 159.72 |
Sequencing & Downtime
[4]:
seq_metrics = playback_tables.day[
["day", "sequencing_violations", "downtime_hours", "downtime_events"]
]
seq_metrics
[4]:
| day | sequencing_violations | downtime_hours | downtime_events | |
|---|---|---|---|---|
| 0 | 1 | 0 | 0.0 | 0 |
| 1 | 2 | 0 | 0.0 | 0 |
| 2 | 3 | 0 | 0.0 | 0 |
| 3 | 4 | 0 | 0.0 | 0 |
| 4 | 5 | 0 | 0.0 | 0 |
| 5 | 6 | 0 | 0.0 | 0 |
| 6 | 7 | 0 | 0.0 | 0 |
Visualise Utilisation
[5]:
chart = utils.plot_utilisation_heatmap(playback_tables.shift)
chart
[5]: