LTDS to Powerflow Quality Control¶
This tutorial demonstrates a practical quality-control workflow for power flow time series by:
- Selecting a substation from LTDS data
- Pulling associated LTDS lines (Table 1) and transformers (Tables 2A/2B)
- Cross-referencing with monthly powerflow circuits/transformers
- Selecting a month with the least redaction
- Running QC checks (gaps, anomalies, step changes, and flow balance)
Prerequisites:
- Complete 01-getting-started.ipynb first
- Have your
UKPN_API_KEYenvironment variable set - These tutorials require additional dependencies. Install them with
pip install "ukpyn[all]"— see Tutorial 01 for full setup instructions - complete
01-getting-started.ipynband06-powerflow-timeseries.ipynb.
In [1]:
Copied!
import ukpyn
ukpyn.check_api_key()
print("API key configured!")
import ukpyn
ukpyn.check_api_key()
print("API key configured!")
API key configured!
In [13]:
Copied!
import pandas as pd
from ukpyn import ltds, powerflow
from ukpyn.utils import (
detect_rolling_anomalies,
detect_step_changes,
fill_gaps,
identify_gaps,
quality_control,
summarize_flow_balance,
summarize_redaction_by_period,
)
try:
import matplotlib.pyplot as plt
HAS_MATPLOTLIB = True
except ImportError:
HAS_MATPLOTLIB = False
LICENCE_AREA = "Eastern Power Networks (EPN)"
REDaction_MARKERS = ["REDACTED", "SUPPRESSED", "MASKED"]
VALUE_FIELDS = [
"active_power_mw",
"reactive_power_mvar",
"apparent_power_mva",
"loading_percent",
]
print("Imports complete")
import pandas as pd
from ukpyn import ltds, powerflow
from ukpyn.utils import (
detect_rolling_anomalies,
detect_step_changes,
fill_gaps,
identify_gaps,
quality_control,
summarize_flow_balance,
summarize_redaction_by_period,
)
try:
import matplotlib.pyplot as plt
HAS_MATPLOTLIB = True
except ImportError:
HAS_MATPLOTLIB = False
LICENCE_AREA = "Eastern Power Networks (EPN)"
REDaction_MARKERS = ["REDACTED", "SUPPRESSED", "MASKED"]
VALUE_FIELDS = [
"active_power_mw",
"reactive_power_mvar",
"apparent_power_mva",
"loading_percent",
]
print("Imports complete")
Imports complete
In [14]:
Copied!
def records_to_dataframe(records: list[object]) -> pd.DataFrame:
rows = []
for record in records:
if hasattr(record, "fields") and record.fields:
rows.append(record.fields)
elif isinstance(record, dict):
rows.append(record)
return pd.DataFrame(rows)
def substation_mask(df: pd.DataFrame, substation: str) -> pd.Series:
if df.empty:
return pd.Series([], dtype=bool)
text_columns = [
col
for col in df.columns
if pd.api.types.is_object_dtype(df[col])
or pd.api.types.is_string_dtype(df[col])
]
if not text_columns:
return pd.Series(False, index=df.index)
needle = str(substation).strip().lower()
mask = pd.Series(False, index=df.index)
for col in text_columns:
mask = mask | df[col].astype("string").str.lower().str.contains(
needle, na=False
)
return mask
def infer_rating_columns(df: pd.DataFrame) -> list[str]:
if df.empty:
return []
candidates = []
for col in df.columns:
name = col.lower()
if "rating" in name or "mva" in name:
candidates.append(col)
return candidates
def records_to_dataframe(records: list[object]) -> pd.DataFrame:
rows = []
for record in records:
if hasattr(record, "fields") and record.fields:
rows.append(record.fields)
elif isinstance(record, dict):
rows.append(record)
return pd.DataFrame(rows)
def substation_mask(df: pd.DataFrame, substation: str) -> pd.Series:
if df.empty:
return pd.Series([], dtype=bool)
text_columns = [
col
for col in df.columns
if pd.api.types.is_object_dtype(df[col])
or pd.api.types.is_string_dtype(df[col])
]
if not text_columns:
return pd.Series(False, index=df.index)
needle = str(substation).strip().lower()
mask = pd.Series(False, index=df.index)
for col in text_columns:
mask = mask | df[col].astype("string").str.lower().str.contains(
needle, na=False
)
return mask
def infer_rating_columns(df: pd.DataFrame) -> list[str]:
if df.empty:
return []
candidates = []
for col in df.columns:
name = col.lower()
if "rating" in name or "mva" in name:
candidates.append(col)
return candidates
1) Select a candidate substation from LTDS¶
We use LTDS Table 3A to discover a substation name that can then be cross-referenced into circuit and transformer datasets.
In [15]:
Copied!
table_3a = ltds.get_table_3a(licence_area=LICENCE_AREA, limit=100)
print(table_3a)
df_3a = records_to_dataframe(table_3a.records)
print(df_3a.head())
if df_3a.empty or "substation" not in df_3a.columns:
raise RuntimeError("Could not discover substations from LTDS table 3A")
substations = sorted(df_3a["substation"].dropna().astype(str).unique())
selected_substation = substations[0]
print(f"Selected substation: {selected_substation}")
print(f"Candidate substations found: {len(substations)}")
table_3a = ltds.get_table_3a(licence_area=LICENCE_AREA, limit=100)
print(table_3a)
df_3a = records_to_dataframe(table_3a.records)
print(df_3a.head())
if df_3a.empty or "substation" not in df_3a.columns:
raise RuntimeError("Could not discover substations from LTDS table 3A")
substations = sorted(df_3a["substation"].dropna().astype(str).unique())
selected_substation = substations[0]
print(f"Selected substation: {selected_substation}")
print(f"Candidate substations found: {len(substations)}")
total_count=1110 links=None records=[Record(id=4, timestamp=None, size=None, fields={'gridsupplypoint': 'Amersham', 'substation': 'Coldharbour Farm 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 2.9, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 2.9, 'forecast_m_d_mw_26_27': 2.9, 'forecast_m_d_mw_27_28': 2.9, 'forecast_m_d_mw_28_29': 2.8, 'forecast_m_d_mw_29_30': 2.8, 'firm_capacity_mw': 11.5, 'minimum_load_scaling_factor': '28.8%', 'unutilised_capacity_percent': 74.78260869565217, 'functional_location': 'EPN-S0000000H8009', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=15, timestamp=None, size=None, fields={'gridsupplypoint': 'Barking 132kV', 'substation': 'Chase Cross Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 14.6, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 14.8, 'forecast_m_d_mw_26_27': 15.6, 'forecast_m_d_mw_27_28': 15.8, 'forecast_m_d_mw_28_29': 16.2, 'forecast_m_d_mw_29_30': 16.8, 'firm_capacity_mw': 18.5, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 21.081081081081088, 'functional_location': 'EPN-S0000000H7142', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=17, timestamp=None, size=None, fields={'gridsupplypoint': 'Barking 132kV', 'substation': 'Crowlands Grid 33kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 54.6, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 54.8, 'forecast_m_d_mw_26_27': 76.1, 'forecast_m_d_mw_27_28': 88.3, 'forecast_m_d_mw_28_29': 100.8, 'forecast_m_d_mw_29_30': 113.5, 'firm_capacity_mw': 109.7, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 50.22789425706472, 'functional_location': 'EPN-S0000000D7124', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=19, timestamp=None, size=None, fields={'gridsupplypoint': 'Barking 132kV', 'substation': 'Romford Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 28.8, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 28.7, 'forecast_m_d_mw_26_27': 30.3, 'forecast_m_d_mw_27_28': 30.8, 'forecast_m_d_mw_28_29': 31.5, 'forecast_m_d_mw_29_30': 32.3, 'firm_capacity_mw': 42.3, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 31.914893617021267, 'functional_location': 'EPN-S0000000H7150', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=21, timestamp=None, size=None, fields={'gridsupplypoint': 'Barking 132kV', 'substation': 'Selinas Ln Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 13.5, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 13.6, 'forecast_m_d_mw_26_27': 14.7, 'forecast_m_d_mw_27_28': 15.3, 'forecast_m_d_mw_28_29': 16.0, 'forecast_m_d_mw_29_30': 16.7, 'firm_capacity_mw': 25.0, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 46.0, 'functional_location': 'EPN-S0000000H7133', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=24, timestamp=None, size=None, fields={'gridsupplypoint': 'Barking West 33kV', 'substation': 'Becontree Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 7.4, 'maximum_demand_24_25_pf': 0.92, 'forecast_m_d_mw_25_26': 7.5, 'forecast_m_d_mw_26_27': 10.1, 'forecast_m_d_mw_27_28': 11.2, 'forecast_m_d_mw_28_29': 12.3, 'forecast_m_d_mw_29_30': 13.4, 'firm_capacity_mw': 16.6, 'minimum_load_scaling_factor': '25.8%', 'unutilised_capacity_percent': 55.42168674698795, 'functional_location': 'EPN-S0000000H7058', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=25, timestamp=None, size=None, fields={'gridsupplypoint': 'Barking West 33kV', 'substation': 'Chequers Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 10.7, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 10.7, 'forecast_m_d_mw_26_27': 12.9, 'forecast_m_d_mw_27_28': 13.7, 'forecast_m_d_mw_28_29': 14.5, 'forecast_m_d_mw_29_30': 15.2, 'firm_capacity_mw': 25.0, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 57.2, 'functional_location': 'EPN-S0000000H7090', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=29, timestamp=None, size=None, fields={'gridsupplypoint': 'Barking West 33kV', 'substation': 'May & Baker Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 7.7, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 7.6, 'forecast_m_d_mw_26_27': 8.6, 'forecast_m_d_mw_27_28': 8.9, 'forecast_m_d_mw_28_29': 9.3, 'forecast_m_d_mw_29_30': 9.6, 'firm_capacity_mw': 20.4, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 62.254901960784316, 'functional_location': 'EPN-S0000000H7016', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=32, timestamp=None, size=None, fields={'gridsupplypoint': 'Braintree', 'substation': 'Braintree Depot Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 16.6, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 16.6, 'forecast_m_d_mw_26_27': 18.7, 'forecast_m_d_mw_27_28': 19.5, 'forecast_m_d_mw_28_29': 20.6, 'forecast_m_d_mw_29_30': 21.7, 'firm_capacity_mw': 28.8, 'minimum_load_scaling_factor': '25.6%', 'unutilised_capacity_percent': 42.36111111111111, 'functional_location': 'EPN-S0000000H3014', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=39, timestamp=None, size=None, fields={'gridsupplypoint': 'Braintree', 'substation': 'Lake & Elliot Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 8.6, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 8.5, 'forecast_m_d_mw_26_27': 9.2, 'forecast_m_d_mw_27_28': 9.3, 'forecast_m_d_mw_28_29': 9.5, 'forecast_m_d_mw_29_30': 9.8, 'firm_capacity_mw': 12.5, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 31.200000000000006, 'functional_location': 'EPN-S0000000H3069', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=44, timestamp=None, size=None, fields={'gridsupplypoint': 'Braintree', 'substation': 'Witham Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 16.4, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 16.5, 'forecast_m_d_mw_26_27': 18.2, 'forecast_m_d_mw_27_28': 18.7, 'forecast_m_d_mw_28_29': 19.3, 'forecast_m_d_mw_29_30': 20.0, 'firm_capacity_mw': 33.1, 'minimum_load_scaling_factor': '10.5%', 'unutilised_capacity_percent': 50.45317220543808, 'functional_location': 'EPN-S0000000H3054', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=50, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Barsham Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 7.2, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 7.2, 'forecast_m_d_mw_26_27': 9.2, 'forecast_m_d_mw_27_28': 9.7, 'forecast_m_d_mw_28_29': 10.3, 'forecast_m_d_mw_29_30': 10.9, 'firm_capacity_mw': 9.6, 'minimum_load_scaling_factor': '13.1%', 'unutilised_capacity_percent': 25.0, 'functional_location': 'EPN-S0000000H5086', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=51, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Beccles Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 8.5, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 8.4, 'forecast_m_d_mw_26_27': 9.5, 'forecast_m_d_mw_27_28': 9.9, 'forecast_m_d_mw_28_29': 10.5, 'forecast_m_d_mw_29_30': 11.0, 'firm_capacity_mw': 14.4, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 40.97222222222222, 'functional_location': 'EPN-S0000000H5049', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=52, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Beccles Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 6.8, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 6.9, 'forecast_m_d_mw_26_27': 8.0, 'forecast_m_d_mw_27_28': 8.4, 'forecast_m_d_mw_28_29': 9.0, 'forecast_m_d_mw_29_30': 9.5, 'firm_capacity_mw': 11.0, 'minimum_load_scaling_factor': '19.4%', 'unutilised_capacity_percent': 38.18181818181819, 'functional_location': 'EPN-S0000000H5049', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=53, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Benhall Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 5.2, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 5.6, 'forecast_m_d_mw_26_27': 5.6, 'forecast_m_d_mw_27_28': 5.6, 'forecast_m_d_mw_28_29': 5.6, 'forecast_m_d_mw_29_30': 5.7, 'firm_capacity_mw': 12.5, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 58.4, 'functional_location': 'EPN-S0000000H5027', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=54, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Benhall Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 3.3, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 3.8, 'forecast_m_d_mw_26_27': 3.8, 'forecast_m_d_mw_27_28': 3.8, 'forecast_m_d_mw_28_29': 3.8, 'forecast_m_d_mw_29_30': 3.9, 'firm_capacity_mw': 9.6, 'minimum_load_scaling_factor': '25.8%', 'unutilised_capacity_percent': 65.625, 'functional_location': 'EPN-S0000000H5027', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=61, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Brantham Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 5.0, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 5.0, 'forecast_m_d_mw_26_27': 4.9, 'forecast_m_d_mw_27_28': 4.9, 'forecast_m_d_mw_28_29': 4.9, 'forecast_m_d_mw_29_30': 4.9, 'firm_capacity_mw': 17.3, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 71.09826589595376, 'functional_location': 'EPN-S0000000H3043', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=67, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Bury Grid 33kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 64.9, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 65.2, 'forecast_m_d_mw_26_27': 70.6, 'forecast_m_d_mw_27_28': 76.5, 'forecast_m_d_mw_28_29': 81.3, 'forecast_m_d_mw_29_30': 86.2, 'firm_capacity_mw': 109.7, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 40.83865086599817, 'functional_location': 'EPN-S0000000D1012', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=71, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Clacton 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 11.2, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 12.0, 'forecast_m_d_mw_26_27': 11.9, 'forecast_m_d_mw_27_28': 12.0, 'forecast_m_d_mw_28_29': 12.1, 'forecast_m_d_mw_29_30': 12.4, 'firm_capacity_mw': 23.0, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 51.30434782608696, 'functional_location': 'EPN-S0000000H3027', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=72, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Clacton 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 8.0, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 9.0, 'forecast_m_d_mw_26_27': 9.1, 'forecast_m_d_mw_27_28': 9.2, 'forecast_m_d_mw_28_29': 9.5, 'forecast_m_d_mw_29_30': 9.8, 'firm_capacity_mw': 17.3, 'minimum_load_scaling_factor': '23.9%', 'unutilised_capacity_percent': 53.75722543352601, 'functional_location': 'EPN-S0000000H3027', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=77, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Cliff Quay Grid 33kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 91.3, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 90.1, 'forecast_m_d_mw_26_27': 98.5, 'forecast_m_d_mw_27_28': 100.9, 'forecast_m_d_mw_28_29': 103.7, 'forecast_m_d_mw_29_30': 106.8, 'firm_capacity_mw': 149.8, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 39.0520694259012, 'functional_location': 'EPN-S0000000D1041', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=79, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Colchester Grid 33kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 50.5, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 50.2, 'forecast_m_d_mw_26_27': 51.2, 'forecast_m_d_mw_27_28': 51.5, 'forecast_m_d_mw_28_29': 52.6, 'forecast_m_d_mw_29_30': 54.0, 'firm_capacity_mw': 68.6, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 26.384839650145764, 'functional_location': 'EPN-S0000000D3044', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=83, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Debenham Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 6.5, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 6.4, 'forecast_m_d_mw_26_27': 6.3, 'forecast_m_d_mw_27_28': 6.3, 'forecast_m_d_mw_28_29': 6.4, 'forecast_m_d_mw_29_30': 6.5, 'firm_capacity_mw': 14.4, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 54.861111111111114, 'functional_location': 'EPN-S0000000H1070', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=84, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Debenham Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 4.8, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 4.7, 'forecast_m_d_mw_26_27': 4.7, 'forecast_m_d_mw_27_28': 4.6, 'forecast_m_d_mw_28_29': 4.7, 'forecast_m_d_mw_29_30': 4.7, 'firm_capacity_mw': 11.5, 'minimum_load_scaling_factor': '30.4%', 'unutilised_capacity_percent': 58.26086956521739, 'functional_location': 'EPN-S0000000H1070', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=85, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Diss Grid 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 11.2, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 11.5, 'forecast_m_d_mw_26_27': 12.2, 'forecast_m_d_mw_27_28': 12.9, 'forecast_m_d_mw_28_29': 13.6, 'forecast_m_d_mw_29_30': 14.4, 'firm_capacity_mw': 14.4, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 22.222222222222232, 'functional_location': 'EPN-S0000000H1014', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=86, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Diss Grid 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 7.9, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 8.4, 'forecast_m_d_mw_26_27': 9.3, 'forecast_m_d_mw_27_28': 10.1, 'forecast_m_d_mw_28_29': 11.0, 'forecast_m_d_mw_29_30': 11.9, 'firm_capacity_mw': 11.0, 'minimum_load_scaling_factor': '27.0%', 'unutilised_capacity_percent': 28.181818181818173, 'functional_location': 'EPN-S0000000H1014', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=91, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Dovercourt Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 14.2, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 14.1, 'forecast_m_d_mw_26_27': 14.3, 'forecast_m_d_mw_27_28': 14.5, 'forecast_m_d_mw_28_29': 14.9, 'forecast_m_d_mw_29_30': 15.3, 'firm_capacity_mw': 21.9, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 35.15981735159818, 'functional_location': 'EPN-S0000000H3003', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=92, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Dovercourt Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 8.9, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 8.9, 'forecast_m_d_mw_26_27': 9.3, 'forecast_m_d_mw_27_28': 9.7, 'forecast_m_d_mw_28_29': 10.1, 'forecast_m_d_mw_29_30': 10.7, 'firm_capacity_mw': 16.6, 'minimum_load_scaling_factor': '29.1%', 'unutilised_capacity_percent': 46.3855421686747, 'functional_location': 'EPN-S0000000H3003', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=96, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'East Bay Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 7.2, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 7.2, 'forecast_m_d_mw_26_27': 7.4, 'forecast_m_d_mw_27_28': 7.5, 'forecast_m_d_mw_28_29': 7.7, 'forecast_m_d_mw_29_30': 7.8, 'firm_capacity_mw': 16.6, 'minimum_load_scaling_factor': '30.7%', 'unutilised_capacity_percent': 56.62650602409639, 'functional_location': 'EPN-S0000000H3036', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=98, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Elmswell Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 3.9, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 3.8, 'forecast_m_d_mw_26_27': 3.9, 'forecast_m_d_mw_27_28': 4.0, 'forecast_m_d_mw_28_29': 4.2, 'forecast_m_d_mw_29_30': 4.5, 'firm_capacity_mw': 7.2, 'minimum_load_scaling_factor': '48.0%', 'unutilised_capacity_percent': 45.833333333333336, 'functional_location': 'EPN-S0000000H1004', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=99, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Eye Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 13.6, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 13.5, 'forecast_m_d_mw_26_27': 13.4, 'forecast_m_d_mw_27_28': 13.3, 'forecast_m_d_mw_28_29': 13.2, 'forecast_m_d_mw_29_30': 13.3, 'firm_capacity_mw': 14.6, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 6.849315068493156, 'functional_location': 'EPN-S0000000H1043', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=101, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Fagbury Rd Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 4.3, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 4.3, 'forecast_m_d_mw_26_27': 5.4, 'forecast_m_d_mw_27_28': 5.7, 'forecast_m_d_mw_28_29': 6.1, 'forecast_m_d_mw_29_30': 6.4, 'firm_capacity_mw': 20.4, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 78.92156862745098, 'functional_location': 'EPN-S0000000H1072', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=109, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Fornham Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 13.6, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 13.5, 'forecast_m_d_mw_26_27': 15.0, 'forecast_m_d_mw_27_28': 15.6, 'forecast_m_d_mw_28_29': 16.2, 'forecast_m_d_mw_29_30': 16.8, 'firm_capacity_mw': 21.8, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 37.61467889908258, 'functional_location': 'EPN-S0000000H1062', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=112, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Foxash Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 5.9, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 5.8, 'forecast_m_d_mw_26_27': 6.0, 'forecast_m_d_mw_27_28': 6.1, 'forecast_m_d_mw_28_29': 6.3, 'forecast_m_d_mw_29_30': 6.7, 'firm_capacity_mw': 9.6, 'minimum_load_scaling_factor': '29.3%', 'unutilised_capacity_percent': 38.541666666666664, 'functional_location': 'EPN-S0000000H3028', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=115, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Frinton Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 10.8, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 10.6, 'forecast_m_d_mw_26_27': 10.5, 'forecast_m_d_mw_27_28': 10.5, 'forecast_m_d_mw_28_29': 10.5, 'forecast_m_d_mw_29_30': 10.7, 'firm_capacity_mw': 14.4, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 25.0, 'functional_location': 'EPN-S0000000H3061', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=120, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Hacheston Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 2.5, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 2.5, 'forecast_m_d_mw_26_27': 2.5, 'forecast_m_d_mw_27_28': 2.5, 'forecast_m_d_mw_28_29': 2.5, 'forecast_m_d_mw_29_30': 2.6, 'firm_capacity_mw': 9.6, 'minimum_load_scaling_factor': '34.2%', 'unutilised_capacity_percent': 73.95833333333333, 'functional_location': 'EPN-S0000000H5017', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=122, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Hadleigh Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 7.1, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 7.3, 'forecast_m_d_mw_26_27': 7.1, 'forecast_m_d_mw_27_28': 7.2, 'forecast_m_d_mw_28_29': 7.4, 'forecast_m_d_mw_29_30': 7.8, 'firm_capacity_mw': 14.6, 'minimum_load_scaling_factor': '28.6%', 'unutilised_capacity_percent': 51.369863013698634, 'functional_location': 'EPN-S0000000H1054', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=133, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Hitcham Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 9.0, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 8.9, 'forecast_m_d_mw_26_27': 8.8, 'forecast_m_d_mw_27_28': 8.7, 'forecast_m_d_mw_28_29': 8.6, 'forecast_m_d_mw_29_30': 8.6, 'firm_capacity_mw': 14.6, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 38.35616438356164, 'functional_location': 'EPN-S0000000H1037', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=134, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Hitcham Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 6.4, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 6.3, 'forecast_m_d_mw_26_27': 6.3, 'forecast_m_d_mw_27_28': 6.2, 'forecast_m_d_mw_28_29': 6.2, 'forecast_m_d_mw_29_30': 6.2, 'firm_capacity_mw': 14.6, 'minimum_load_scaling_factor': '29.7%', 'unutilised_capacity_percent': 56.16438356164384, 'functional_location': 'EPN-S0000000H1037', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=140, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Ilketshall Grid 33kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 16.5, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 16.4, 'forecast_m_d_mw_26_27': 19.0, 'forecast_m_d_mw_27_28': 20.0, 'forecast_m_d_mw_28_29': 21.0, 'forecast_m_d_mw_29_30': 22.0, 'firm_capacity_mw': 57.6, 'minimum_load_scaling_factor': '25.3%', 'unutilised_capacity_percent': 71.35416666666667, 'functional_location': 'EPN-S0000000D5089', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=142, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Ipswich Grid 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 9.5, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 9.6, 'forecast_m_d_mw_26_27': 11.1, 'forecast_m_d_mw_27_28': 11.6, 'forecast_m_d_mw_28_29': 12.2, 'forecast_m_d_mw_29_30': 12.8, 'firm_capacity_mw': 17.3, 'minimum_load_scaling_factor': '29.4%', 'unutilised_capacity_percent': 45.08670520231214, 'functional_location': 'EPN-S0000000H1024', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=144, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Ipswich Grid 33kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 38.6, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 38.6, 'forecast_m_d_mw_26_27': 42.7, 'forecast_m_d_mw_27_28': 44.1, 'forecast_m_d_mw_28_29': 45.7, 'forecast_m_d_mw_29_30': 47.5, 'firm_capacity_mw': 57.6, 'minimum_load_scaling_factor': '24.4%', 'unutilised_capacity_percent': 32.98611111111111, 'functional_location': 'EPN-S0000000D1024', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=146, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Kennett Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 5.6, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 5.4, 'forecast_m_d_mw_26_27': 7.2, 'forecast_m_d_mw_27_28': 7.6, 'forecast_m_d_mw_28_29': 8.1, 'forecast_m_d_mw_29_30': 8.6, 'firm_capacity_mw': 16.6, 'minimum_load_scaling_factor': '17.6%', 'unutilised_capacity_percent': 66.26506024096386, 'functional_location': 'EPN-S0000000H1063', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=148, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Kenninghall Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 9.3, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 9.2, 'forecast_m_d_mw_26_27': 9.1, 'forecast_m_d_mw_27_28': 9.1, 'forecast_m_d_mw_28_29': 9.2, 'forecast_m_d_mw_29_30': 9.3, 'firm_capacity_mw': 11.0, 'minimum_load_scaling_factor': '31.5%', 'unutilised_capacity_percent': 15.454545454545443, 'functional_location': 'EPN-S0000000H1064', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=149, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Kimms Belt Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 12.1, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 12.3, 'forecast_m_d_mw_26_27': 13.5, 'forecast_m_d_mw_27_28': 14.4, 'forecast_m_d_mw_28_29': 15.3, 'forecast_m_d_mw_29_30': 16.0, 'firm_capacity_mw': 14.6, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 17.12328767123288, 'functional_location': 'EPN-S0000000H1025', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=152, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Lakenheath Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 10.1, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 10.0, 'forecast_m_d_mw_26_27': 10.0, 'forecast_m_d_mw_27_28': 9.9, 'forecast_m_d_mw_28_29': 9.9, 'forecast_m_d_mw_29_30': 9.9, 'firm_capacity_mw': 14.0, 'minimum_load_scaling_factor': '38.3%', 'unutilised_capacity_percent': 27.857142857142858, 'functional_location': 'EPN-S0000000H1026', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=154, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Langham Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 4.2, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 4.1, 'forecast_m_d_mw_26_27': 4.8, 'forecast_m_d_mw_27_28': 5.0, 'forecast_m_d_mw_28_29': 5.2, 'forecast_m_d_mw_29_30': 5.3, 'firm_capacity_mw': 11.0, 'minimum_load_scaling_factor': '32.9%', 'unutilised_capacity_percent': 61.81818181818181, 'functional_location': 'EPN-S0000000H3047', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=155, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Langley Av Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 8.9, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 9.0, 'forecast_m_d_mw_26_27': 9.3, 'forecast_m_d_mw_27_28': 9.7, 'forecast_m_d_mw_28_29': 10.2, 'forecast_m_d_mw_29_30': 10.8, 'firm_capacity_mw': 22.1, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 59.72850678733032, 'functional_location': 'EPN-S0000000H1065', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=157, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Lawford Grid 33kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 53.2, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 39.8, 'forecast_m_d_mw_26_27': 46.1, 'forecast_m_d_mw_27_28': 48.3, 'forecast_m_d_mw_28_29': 54.5, 'forecast_m_d_mw_29_30': 59.2, 'firm_capacity_mw': 112.3, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 52.62689225289403, 'functional_location': 'EPN-S0000000D3048', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=158, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Lawford Grid 33kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 32.4, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 23.8, 'forecast_m_d_mw_26_27': 29.9, 'forecast_m_d_mw_27_28': 32.3, 'forecast_m_d_mw_28_29': 38.8, 'forecast_m_d_mw_29_30': 43.8, 'firm_capacity_mw': 86.4, 'minimum_load_scaling_factor': '34.7%', 'unutilised_capacity_percent': 62.5, 'functional_location': 'EPN-S0000000D3048', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=163, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Manor Road Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 8.2, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 8.0, 'forecast_m_d_mw_26_27': 9.0, 'forecast_m_d_mw_27_28': 9.5, 'forecast_m_d_mw_28_29': 10.1, 'forecast_m_d_mw_29_30': 10.7, 'firm_capacity_mw': 14.4, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 43.05555555555556, 'functional_location': 'EPN-S0000000H1017', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=172, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Mildenhall Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 12.8, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 13.0, 'forecast_m_d_mw_26_27': 13.4, 'forecast_m_d_mw_27_28': 13.5, 'forecast_m_d_mw_28_29': 13.8, 'forecast_m_d_mw_29_30': 14.0, 'firm_capacity_mw': 17.3, 'minimum_load_scaling_factor': '23.8%', 'unutilised_capacity_percent': 26.011560693641623, 'functional_location': 'EPN-S0000000H1066', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=175, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Old Rd Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 17.3, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 17.3, 'forecast_m_d_mw_26_27': 17.2, 'forecast_m_d_mw_27_28': 17.2, 'forecast_m_d_mw_28_29': 17.2, 'forecast_m_d_mw_29_30': 17.2, 'firm_capacity_mw': 17.8, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 2.8089887640449396, 'functional_location': 'EPN-S0000000H3063', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=182, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Parsons Heath Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 7.1, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 7.1, 'forecast_m_d_mw_26_27': 8.8, 'forecast_m_d_mw_27_28': 9.6, 'forecast_m_d_mw_28_29': 10.4, 'forecast_m_d_mw_29_30': 11.2, 'firm_capacity_mw': 16.6, 'minimum_load_scaling_factor': '28.7%', 'unutilised_capacity_percent': 57.22891566265061, 'functional_location': 'EPN-S0000000H3020', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=183, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Peasenhall Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 4.6, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 4.6, 'forecast_m_d_mw_26_27': 4.6, 'forecast_m_d_mw_27_28': 4.6, 'forecast_m_d_mw_28_29': 4.7, 'forecast_m_d_mw_29_30': 4.7, 'firm_capacity_mw': 6.2, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 25.806451612903235, 'functional_location': 'EPN-S0000000H5008', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=184, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Peasenhall Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 3.0, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 3.0, 'forecast_m_d_mw_26_27': 2.8, 'forecast_m_d_mw_27_28': 2.8, 'forecast_m_d_mw_28_29': 2.8, 'forecast_m_d_mw_29_30': 2.8, 'firm_capacity_mw': 4.8, 'minimum_load_scaling_factor': '27.6%', 'unutilised_capacity_percent': 37.5, 'functional_location': 'EPN-S0000000H5008', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=186, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Playfield Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 8.8, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 9.4, 'forecast_m_d_mw_26_27': 10.1, 'forecast_m_d_mw_27_28': 10.6, 'forecast_m_d_mw_28_29': 11.2, 'forecast_m_d_mw_29_30': 11.8, 'firm_capacity_mw': 14.4, 'minimum_load_scaling_factor': '24.3%', 'unutilised_capacity_percent': 38.888888888888886, 'functional_location': 'EPN-S0000000H1027', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=191, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Roundwood Rd Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 17.0, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 16.7, 'forecast_m_d_mw_26_27': 17.1, 'forecast_m_d_mw_27_28': 17.2, 'forecast_m_d_mw_28_29': 17.4, 'forecast_m_d_mw_29_30': 17.8, 'firm_capacity_mw': 21.1, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 19.431279620853083, 'functional_location': 'EPN-S0000000H1049', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=193, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Severalls Ln Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 13.4, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 13.4, 'forecast_m_d_mw_26_27': 16.8, 'forecast_m_d_mw_27_28': 18.0, 'forecast_m_d_mw_28_29': 19.2, 'forecast_m_d_mw_29_30': 20.4, 'firm_capacity_mw': 23.1, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 41.99134199134199, 'functional_location': 'EPN-S0000000H3039', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=194, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Severalls Ln Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 9.5, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 9.6, 'forecast_m_d_mw_26_27': 12.7, 'forecast_m_d_mw_27_28': 13.7, 'forecast_m_d_mw_28_29': 14.9, 'forecast_m_d_mw_29_30': 16.0, 'firm_capacity_mw': 17.3, 'minimum_load_scaling_factor': '24.6%', 'unutilised_capacity_percent': 45.08670520231214, 'functional_location': 'EPN-S0000000H3039', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=196, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Shotley Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 2.0, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 2.0, 'forecast_m_d_mw_26_27': 2.5, 'forecast_m_d_mw_27_28': 2.7, 'forecast_m_d_mw_28_29': 2.9, 'forecast_m_d_mw_29_30': 3.2, 'firm_capacity_mw': 17.3, 'minimum_load_scaling_factor': '20.1%', 'unutilised_capacity_percent': 88.43930635838151, 'functional_location': 'EPN-S0000000H1075', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=197, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Snetterton Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 0.0, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 0.0, 'forecast_m_d_mw_26_27': 1.3, 'forecast_m_d_mw_27_28': 9.2, 'forecast_m_d_mw_28_29': 12.5, 'forecast_m_d_mw_29_30': 15.8, 'firm_capacity_mw': 5.8, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 100.0, 'functional_location': 'EPN-S0000000H1189', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=199, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Stanton Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 9.2, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 9.3, 'forecast_m_d_mw_26_27': 10.2, 'forecast_m_d_mw_27_28': 10.6, 'forecast_m_d_mw_28_29': 11.2, 'forecast_m_d_mw_29_30': 11.8, 'firm_capacity_mw': 22.9, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 59.82532751091703, 'functional_location': 'EPN-S0000000H1030', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=207, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Thetford Grid 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 4.2, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 4.2, 'forecast_m_d_mw_26_27': 4.8, 'forecast_m_d_mw_27_28': 5.0, 'forecast_m_d_mw_28_29': 5.2, 'forecast_m_d_mw_29_30': 5.4, 'firm_capacity_mw': 7.2, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 41.666666666666664, 'functional_location': 'EPN-S0000000H1056', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=208, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Thetford Grid 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 3.7, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 3.7, 'forecast_m_d_mw_26_27': 4.2, 'forecast_m_d_mw_27_28': 4.4, 'forecast_m_d_mw_28_29': 4.6, 'forecast_m_d_mw_29_30': 4.8, 'firm_capacity_mw': 7.2, 'minimum_load_scaling_factor': '22.4%', 'unutilised_capacity_percent': 48.61111111111111, 'functional_location': 'EPN-S0000000H1056', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=209, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Thetford Grid 33kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 63.4, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 63.6, 'forecast_m_d_mw_26_27': 66.1, 'forecast_m_d_mw_27_28': 67.7, 'forecast_m_d_mw_28_29': 69.4, 'forecast_m_d_mw_29_30': 71.0, 'firm_capacity_mw': 109.7, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 42.20601640838652, 'functional_location': 'EPN-S0000000D1056', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=214, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Turret Ln Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 8.3, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 8.6, 'forecast_m_d_mw_26_27': 10.8, 'forecast_m_d_mw_27_28': 11.7, 'forecast_m_d_mw_28_29': 12.5, 'forecast_m_d_mw_29_30': 13.3, 'firm_capacity_mw': 16.6, 'minimum_load_scaling_factor': '20.6%', 'unutilised_capacity_percent': 50.0, 'functional_location': 'EPN-S0000000H1008', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=215, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Valleybridge Rd Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 17.1, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 16.9, 'forecast_m_d_mw_26_27': 17.5, 'forecast_m_d_mw_27_28': 17.7, 'forecast_m_d_mw_28_29': 18.0, 'forecast_m_d_mw_29_30': 18.3, 'firm_capacity_mw': 22.1, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 22.62443438914027, 'functional_location': 'EPN-S0000000H3010', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=219, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Water Ln Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 12.2, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 12.4, 'forecast_m_d_mw_26_27': 12.6, 'forecast_m_d_mw_27_28': 12.8, 'forecast_m_d_mw_28_29': 13.0, 'forecast_m_d_mw_29_30': 13.4, 'firm_capacity_mw': 22.1, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 44.79638009049774, 'functional_location': 'EPN-S0000000H1021', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=220, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Water Ln Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 8.9, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 9.2, 'forecast_m_d_mw_26_27': 9.5, 'forecast_m_d_mw_27_28': 9.8, 'forecast_m_d_mw_28_29': 10.1, 'forecast_m_d_mw_29_30': 10.4, 'firm_capacity_mw': 16.6, 'minimum_load_scaling_factor': '-12.8%', 'unutilised_capacity_percent': 46.3855421686747, 'functional_location': 'EPN-S0000000H1021', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=221, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Wickham Market Grid 33kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 44.5, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 44.7, 'forecast_m_d_mw_26_27': 45.0, 'forecast_m_d_mw_27_28': 45.2, 'forecast_m_d_mw_28_29': 45.6, 'forecast_m_d_mw_29_30': 46.3, 'firm_capacity_mw': 74.9, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 40.587449933244336, 'functional_location': 'EPN-S0000000D5073', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=223, timestamp=None, size=None, fields={'gridsupplypoint': 'Bramford', 'substation': 'Wix Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 6.4, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 6.3, 'forecast_m_d_mw_26_27': 7.9, 'forecast_m_d_mw_27_28': 8.3, 'forecast_m_d_mw_28_29': 9.0, 'forecast_m_d_mw_29_30': 9.6, 'firm_capacity_mw': 14.4, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 55.55555555555556, 'functional_location': 'EPN-S0000000H3055', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=225, timestamp=None, size=None, fields={'gridsupplypoint': 'Brimsdown', 'substation': 'Barnet Grid 33kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 72.6, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 72.1, 'forecast_m_d_mw_26_27': 77.8, 'forecast_m_d_mw_27_28': 79.8, 'forecast_m_d_mw_28_29': 82.5, 'forecast_m_d_mw_29_30': 85.5, 'firm_capacity_mw': 109.7, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 33.819507748404746, 'functional_location': 'EPN-S0000000D8068', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=230, timestamp=None, size=None, fields={'gridsupplypoint': 'Brimsdown', 'substation': 'Brimsdown South Grid 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 21.9, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 21.5, 'forecast_m_d_mw_26_27': 24.6, 'forecast_m_d_mw_27_28': 25.9, 'forecast_m_d_mw_28_29': 27.2, 'forecast_m_d_mw_29_30': 28.5, 'firm_capacity_mw': 28.8, 'minimum_load_scaling_factor': '34.3%', 'unutilised_capacity_percent': 23.958333333333336, 'functional_location': 'EPN-S0000000F7026', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=236, timestamp=None, size=None, fields={'gridsupplypoint': 'Brimsdown', 'substation': 'Cuffley Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 8.5, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 8.4, 'forecast_m_d_mw_26_27': 9.1, 'forecast_m_d_mw_27_28': 9.4, 'forecast_m_d_mw_28_29': 9.9, 'forecast_m_d_mw_29_30': 10.5, 'firm_capacity_mw': 14.4, 'minimum_load_scaling_factor': '39.3%', 'unutilised_capacity_percent': 40.97222222222222, 'functional_location': 'EPN-S0000000H7092', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=239, timestamp=None, size=None, fields={'gridsupplypoint': 'Brimsdown', 'substation': 'Elstree Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 19.9, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 19.9, 'forecast_m_d_mw_26_27': 20.2, 'forecast_m_d_mw_27_28': 20.3, 'forecast_m_d_mw_28_29': 20.7, 'forecast_m_d_mw_29_30': 21.1, 'firm_capacity_mw': 37.4, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 46.79144385026738, 'functional_location': 'EPN-S0000000H8155', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=241, timestamp=None, size=None, fields={'gridsupplypoint': 'Brimsdown', 'substation': 'Ladysmith Rd Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 11.5, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 10.4, 'forecast_m_d_mw_26_27': 12.5, 'forecast_m_d_mw_27_28': 13.3, 'forecast_m_d_mw_28_29': 14.1, 'forecast_m_d_mw_29_30': 15.0, 'firm_capacity_mw': 18.7, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 38.50267379679144, 'functional_location': 'EPN-S0000000H8036', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=244, timestamp=None, size=None, fields={'gridsupplypoint': 'Brimsdown', 'substation': 'North Chingford Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 7.9, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 8.2, 'forecast_m_d_mw_26_27': 9.2, 'forecast_m_d_mw_27_28': 9.9, 'forecast_m_d_mw_28_29': 10.6, 'forecast_m_d_mw_29_30': 11.4, 'firm_capacity_mw': 14.4, 'minimum_load_scaling_factor': '22.2%', 'unutilised_capacity_percent': 45.138888888888886, 'functional_location': 'EPN-S0000000H7103', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=250, timestamp=None, size=None, fields={'gridsupplypoint': 'Brimsdown', 'substation': 'Tapster St Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 9.7, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 9.7, 'forecast_m_d_mw_26_27': 11.3, 'forecast_m_d_mw_27_28': 11.9, 'forecast_m_d_mw_28_29': 12.5, 'forecast_m_d_mw_29_30': 13.3, 'firm_capacity_mw': 26.9, 'minimum_load_scaling_factor': '29.9%', 'unutilised_capacity_percent': 63.94052044609666, 'functional_location': 'EPN-S0000000H8020', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=253, timestamp=None, size=None, fields={'gridsupplypoint': 'Brimsdown', 'substation': 'Waltham Abbey Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 16.8, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 16.8, 'forecast_m_d_mw_26_27': 18.3, 'forecast_m_d_mw_27_28': 20.2, 'forecast_m_d_mw_28_29': 21.2, 'forecast_m_d_mw_29_30': 22.4, 'firm_capacity_mw': 21.9, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 23.287671232876704, 'functional_location': 'EPN-S0000000H7158', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=254, timestamp=None, size=None, fields={'gridsupplypoint': 'Brimsdown', 'substation': 'Waltham Abbey Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 10.2, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 10.4, 'forecast_m_d_mw_26_27': 12.0, 'forecast_m_d_mw_27_28': 13.8, 'forecast_m_d_mw_28_29': 14.9, 'forecast_m_d_mw_29_30': 16.2, 'firm_capacity_mw': 16.6, 'minimum_load_scaling_factor': '29.3%', 'unutilised_capacity_percent': 38.55421686746989, 'functional_location': 'EPN-S0000000H7158', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=261, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Aldreth Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 15.3, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 15.0, 'forecast_m_d_mw_26_27': 15.0, 'forecast_m_d_mw_27_28': 15.0, 'forecast_m_d_mw_28_29': 15.2, 'forecast_m_d_mw_29_30': 15.5, 'firm_capacity_mw': 14.6, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': -4.794520547945202, 'functional_location': 'EPN-S0000000H4016', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=262, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Aldreth Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 10.3, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 10.2, 'forecast_m_d_mw_26_27': 10.2, 'forecast_m_d_mw_27_28': 10.3, 'forecast_m_d_mw_28_29': 10.6, 'forecast_m_d_mw_29_30': 11.1, 'firm_capacity_mw': 14.6, 'minimum_load_scaling_factor': '19.1%', 'unutilised_capacity_percent': 29.452054794520542, 'functional_location': 'EPN-S0000000H4016', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=264, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Arbury Grid 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 9.0, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 9.4, 'forecast_m_d_mw_26_27': 7.5, 'forecast_m_d_mw_27_28': 7.6, 'forecast_m_d_mw_28_29': 7.6, 'forecast_m_d_mw_29_30': 7.7, 'firm_capacity_mw': 24.7, 'minimum_load_scaling_factor': '38.2%', 'unutilised_capacity_percent': 63.56275303643725, 'functional_location': 'EPN-S0000000H4001', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=266, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Arbury Grid 33kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 48.2, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 52.2, 'forecast_m_d_mw_26_27': 61.8, 'forecast_m_d_mw_27_28': 66.4, 'forecast_m_d_mw_28_29': 76.9, 'forecast_m_d_mw_29_30': 85.0, 'firm_capacity_mw': 86.4, 'minimum_load_scaling_factor': '36.9%', 'unutilised_capacity_percent': 44.21296296296296, 'functional_location': 'EPN-S0000000D4001', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=271, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Burwell Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 6.8, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 6.7, 'forecast_m_d_mw_26_27': 6.8, 'forecast_m_d_mw_27_28': 6.8, 'forecast_m_d_mw_28_29': 7.0, 'forecast_m_d_mw_29_30': 7.2, 'firm_capacity_mw': 12.5, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 45.599999999999994, 'functional_location': 'EPN-S0000000H4083', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=276, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Exning Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 12.4, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 12.7, 'forecast_m_d_mw_26_27': 12.9, 'forecast_m_d_mw_27_28': 14.0, 'forecast_m_d_mw_28_29': 14.4, 'forecast_m_d_mw_29_30': 14.8, 'firm_capacity_mw': 11.0, 'minimum_load_scaling_factor': '22.9%', 'unutilised_capacity_percent': -12.72727272727272, 'functional_location': 'EPN-S0000000H4028', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=277, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Fulbourn 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 20.4, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 21.0, 'forecast_m_d_mw_26_27': 29.8, 'forecast_m_d_mw_27_28': 35.3, 'forecast_m_d_mw_28_29': 38.6, 'forecast_m_d_mw_29_30': 41.8, 'firm_capacity_mw': 36.6, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 44.26229508196722, 'functional_location': 'EPN-S0000000F4065', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=279, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Fulbourn Grid 33kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 72.6, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 74.3, 'forecast_m_d_mw_26_27': 85.5, 'forecast_m_d_mw_27_28': 60.7, 'forecast_m_d_mw_28_29': 66.8, 'forecast_m_d_mw_29_30': 71.3, 'firm_capacity_mw': 109.7, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 33.819507748404746, 'functional_location': 'EPN-S0000000D4084', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=284, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Histon Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 7.2, 'maximum_demand_24_25_pf': 0.92, 'forecast_m_d_mw_25_26': 7.1, 'forecast_m_d_mw_26_27': 7.1, 'forecast_m_d_mw_27_28': 7.1, 'forecast_m_d_mw_28_29': 7.2, 'forecast_m_d_mw_29_30': 7.4, 'firm_capacity_mw': 15.9, 'minimum_load_scaling_factor': '24.6%', 'unutilised_capacity_percent': 54.71698113207547, 'functional_location': 'EPN-S0000000H4066', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=286, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Landbeach Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 11.4, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 11.4, 'forecast_m_d_mw_26_27': 11.8, 'forecast_m_d_mw_27_28': 12.0, 'forecast_m_d_mw_28_29': 15.0, 'forecast_m_d_mw_29_30': 17.2, 'firm_capacity_mw': 28.8, 'minimum_load_scaling_factor': '12.1%', 'unutilised_capacity_percent': 60.41666666666667, 'functional_location': 'EPN-S0000000H4020', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=288, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Linton Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 7.9, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 8.6, 'forecast_m_d_mw_26_27': 9.7, 'forecast_m_d_mw_27_28': 4.9, 'forecast_m_d_mw_28_29': 5.0, 'forecast_m_d_mw_29_30': 5.1, 'firm_capacity_mw': 11.0, 'minimum_load_scaling_factor': '24.1%', 'unutilised_capacity_percent': 28.181818181818173, 'functional_location': 'EPN-S0000000H4069', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=290, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Longstanton Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 9.1, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 9.9, 'forecast_m_d_mw_26_27': 11.6, 'forecast_m_d_mw_27_28': 12.4, 'forecast_m_d_mw_28_29': 13.2, 'forecast_m_d_mw_29_30': 13.9, 'firm_capacity_mw': 17.3, 'minimum_load_scaling_factor': '29.3%', 'unutilised_capacity_percent': 47.39884393063585, 'functional_location': 'EPN-S0000000H4043', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=292, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Madingley Rd Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 10.2, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 12.0, 'forecast_m_d_mw_26_27': 12.5, 'forecast_m_d_mw_27_28': 13.0, 'forecast_m_d_mw_28_29': 13.5, 'forecast_m_d_mw_29_30': 13.9, 'firm_capacity_mw': 25.0, 'minimum_load_scaling_factor': '50.8%', 'unutilised_capacity_percent': 59.20000000000001, 'functional_location': 'EPN-S0000000H4070', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=297, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Radnor Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 19.8, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 20.3, 'forecast_m_d_mw_26_27': 27.4, 'forecast_m_d_mw_27_28': 29.4, 'forecast_m_d_mw_28_29': 31.6, 'forecast_m_d_mw_29_30': 33.6, 'firm_capacity_mw': 36.5, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 45.75342465753425, 'functional_location': 'EPN-S0000000H4011', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=298, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Radnor Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 16.3, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 16.3, 'forecast_m_d_mw_26_27': 22.9, 'forecast_m_d_mw_27_28': 24.9, 'forecast_m_d_mw_28_29': 27.0, 'forecast_m_d_mw_29_30': 28.8, 'firm_capacity_mw': 27.4, 'minimum_load_scaling_factor': '45.6%', 'unutilised_capacity_percent': 40.51094890510948, 'functional_location': 'EPN-S0000000H4011', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=304, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'Soham Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 8.8, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 8.6, 'forecast_m_d_mw_26_27': 9.7, 'forecast_m_d_mw_27_28': 10.3, 'forecast_m_d_mw_28_29': 10.9, 'forecast_m_d_mw_29_30': 11.7, 'firm_capacity_mw': 17.3, 'minimum_load_scaling_factor': '27.3%', 'unutilised_capacity_percent': 49.13294797687862, 'functional_location': 'EPN-S0000000H4013', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=305, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'St Anthony St Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 17.8, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 17.9, 'forecast_m_d_mw_26_27': 20.1, 'forecast_m_d_mw_27_28': 21.0, 'forecast_m_d_mw_28_29': 21.8, 'forecast_m_d_mw_29_30': 22.6, 'firm_capacity_mw': 21.9, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 18.721461187214604, 'functional_location': 'EPN-S0000000H4088', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=306, timestamp=None, size=None, fields={'gridsupplypoint': 'Burwell', 'substation': 'St Anthony St Primary 11kV', 'season': 'Summer', 'maximum_demand_24_25_mw': 16.0, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 16.2, 'forecast_m_d_mw_26_27': 17.9, 'forecast_m_d_mw_27_28': 18.6, 'forecast_m_d_mw_28_29': 19.3, 'forecast_m_d_mw_29_30': 20.0, 'firm_capacity_mw': 16.6, 'minimum_load_scaling_factor': '38.3%', 'unutilised_capacity_percent': 3.614457831325313, 'functional_location': 'EPN-S0000000H4088', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None), Record(id=313, timestamp=None, size=None, fields={'gridsupplypoint': 'Eaton Socon', 'substation': 'Bourn Primary 11kV', 'season': 'Winter', 'maximum_demand_24_25_mw': 12.1, 'maximum_demand_24_25_pf': 0.96, 'forecast_m_d_mw_25_26': 12.4, 'forecast_m_d_mw_26_27': 16.2, 'forecast_m_d_mw_27_28': 17.6, 'forecast_m_d_mw_28_29': 19.1, 'forecast_m_d_mw_29_30': 20.5, 'firm_capacity_mw': 22.9, 'minimum_load_scaling_factor': None, 'unutilised_capacity_percent': 47.161572052401745, 'functional_location': 'EPN-S0000000H4036', 'licencearea': 'Eastern Power Networks (EPN)'}, record_timestamp=None, links=None)]
gridsupplypoint substation season maximum_demand_24_25_mw \
0 Amersham Coldharbour Farm 11kV Summer 2.9
1 Barking 132kV Chase Cross Primary 11kV Winter 14.6
2 Barking 132kV Crowlands Grid 33kV Winter 54.6
3 Barking 132kV Romford Primary 11kV Winter 28.8
4 Barking 132kV Selinas Ln Primary 11kV Winter 13.5
maximum_demand_24_25_pf forecast_m_d_mw_25_26 forecast_m_d_mw_26_27 \
0 0.96 2.9 2.9
1 0.96 14.8 15.6
2 0.96 54.8 76.1
3 0.96 28.7 30.3
4 0.96 13.6 14.7
forecast_m_d_mw_27_28 forecast_m_d_mw_28_29 forecast_m_d_mw_29_30 \
0 2.9 2.8 2.8
1 15.8 16.2 16.8
2 88.3 100.8 113.5
3 30.8 31.5 32.3
4 15.3 16.0 16.7
firm_capacity_mw minimum_load_scaling_factor unutilised_capacity_percent \
0 11.5 28.8% 74.782609
1 18.5 None 21.081081
2 109.7 None 50.227894
3 42.3 None 31.914894
4 25.0 None 46.000000
functional_location licencearea
0 EPN-S0000000H8009 Eastern Power Networks (EPN)
1 EPN-S0000000H7142 Eastern Power Networks (EPN)
2 EPN-S0000000D7124 Eastern Power Networks (EPN)
3 EPN-S0000000H7150 Eastern Power Networks (EPN)
4 EPN-S0000000H7133 Eastern Power Networks (EPN)
Selected substation: Aldreth Primary 11kV
Candidate substations found: 84
In [18]:
Copied!
table_1 = ltds.get_table_1(licence_area=LICENCE_AREA, limit=100)
table_2a = ltds.get_table_2a(
licence_area=LICENCE_AREA, substation=selected_substation, limit=100
)
table_2b = ltds.get_table_2b(
licence_area=LICENCE_AREA, substation=selected_substation, limit=100
)
df_table_1 = records_to_dataframe(table_1.records)
df_table_2a = records_to_dataframe(table_2a.records)
df_table_2b = records_to_dataframe(table_2b.records)
df_lines = df_table_1[substation_mask(df_table_1, selected_substation)].copy()
df_transformers = pd.concat([df_table_2a, df_table_2b], ignore_index=True)
line_rating_cols = infer_rating_columns(df_lines)
transformer_rating_cols = infer_rating_columns(df_transformers)
print(f"Associated LTDS lines: {len(df_lines)}")
print(f"Associated LTDS transformers: {len(df_transformers)}")
print(f"Line rating columns: {line_rating_cols[:6]}")
print(f"Transformer rating columns: {transformer_rating_cols[:6]}")
table_1 = ltds.get_table_1(licence_area=LICENCE_AREA, limit=100)
table_2a = ltds.get_table_2a(
licence_area=LICENCE_AREA, substation=selected_substation, limit=100
)
table_2b = ltds.get_table_2b(
licence_area=LICENCE_AREA, substation=selected_substation, limit=100
)
df_table_1 = records_to_dataframe(table_1.records)
df_table_2a = records_to_dataframe(table_2a.records)
df_table_2b = records_to_dataframe(table_2b.records)
df_lines = df_table_1[substation_mask(df_table_1, selected_substation)].copy()
df_transformers = pd.concat([df_table_2a, df_table_2b], ignore_index=True)
line_rating_cols = infer_rating_columns(df_lines)
transformer_rating_cols = infer_rating_columns(df_transformers)
print(f"Associated LTDS lines: {len(df_lines)}")
print(f"Associated LTDS transformers: {len(df_transformers)}")
print(f"Line rating columns: {line_rating_cols[:6]}")
print(f"Transformer rating columns: {transformer_rating_cols[:6]}")
Associated LTDS lines: 0 Associated LTDS transformers: 2 Line rating columns: [] Transformer rating columns: ['transformer_rating_mva_winter', 'transformer_rating_mva_summer']
2) Pull monthly powerflow data and find least-redacted month¶
In [20]:
Copied!
pf_132 = records_to_dataframe(
powerflow.get_circuit_timeseries(
voltage="132kv", granularity="monthly", licence_area=LICENCE_AREA, limit=100
).records
)
pf_33 = records_to_dataframe(
powerflow.get_circuit_timeseries(
voltage="33kv", granularity="monthly", licence_area=LICENCE_AREA, limit=100
).records
)
pf_grid = records_to_dataframe(
powerflow.get_transformer_timeseries(
transformer_type="grid",
granularity="monthly",
licence_area=LICENCE_AREA,
limit=100,
).records
)
pf_primary = records_to_dataframe(
powerflow.get_transformer_timeseries(
transformer_type="primary",
granularity="monthly",
licence_area=LICENCE_AREA,
limit=100,
).records
)
datasets = {
"132kv_circuits": pf_132,
"33kv_circuits": pf_33,
"grid_transformers": pf_grid,
"primary_transformers": pf_primary,
}
redaction_tables = []
for dataset_name, df in datasets.items():
fields = [f for f in VALUE_FIELDS if f in df.columns]
if not fields or "timestamp" not in df.columns:
continue
summary = summarize_redaction_by_period(
df,
timestamp_field="timestamp",
value_fields=fields,
markers=REDaction_MARKERS,
include_missing_fallback=True,
)
summary["dataset"] = dataset_name
redaction_tables.append(summary)
if not redaction_tables:
raise RuntimeError(
"No redaction summaries could be produced from fetched powerflow data"
)
redaction_summary = pd.concat(redaction_tables, ignore_index=True)
monthly_redaction = redaction_summary.groupby("period", as_index=False)[
["total_points", "redacted_points"]
].sum()
monthly_redaction["redaction_rate"] = (
monthly_redaction["redacted_points"] / monthly_redaction["total_points"]
)
best_month = monthly_redaction.sort_values("redaction_rate").iloc[0]["period"]
month_start = pd.Timestamp(best_month).normalize()
month_end = month_start + pd.offsets.MonthEnd(0)
print(f"Best month (least redaction): {month_start:%Y-%m}")
monthly_redaction.sort_values("redaction_rate").head()
pf_132 = records_to_dataframe(
powerflow.get_circuit_timeseries(
voltage="132kv", granularity="monthly", licence_area=LICENCE_AREA, limit=100
).records
)
pf_33 = records_to_dataframe(
powerflow.get_circuit_timeseries(
voltage="33kv", granularity="monthly", licence_area=LICENCE_AREA, limit=100
).records
)
pf_grid = records_to_dataframe(
powerflow.get_transformer_timeseries(
transformer_type="grid",
granularity="monthly",
licence_area=LICENCE_AREA,
limit=100,
).records
)
pf_primary = records_to_dataframe(
powerflow.get_transformer_timeseries(
transformer_type="primary",
granularity="monthly",
licence_area=LICENCE_AREA,
limit=100,
).records
)
datasets = {
"132kv_circuits": pf_132,
"33kv_circuits": pf_33,
"grid_transformers": pf_grid,
"primary_transformers": pf_primary,
}
redaction_tables = []
for dataset_name, df in datasets.items():
fields = [f for f in VALUE_FIELDS if f in df.columns]
if not fields or "timestamp" not in df.columns:
continue
summary = summarize_redaction_by_period(
df,
timestamp_field="timestamp",
value_fields=fields,
markers=REDaction_MARKERS,
include_missing_fallback=True,
)
summary["dataset"] = dataset_name
redaction_tables.append(summary)
if not redaction_tables:
raise RuntimeError(
"No redaction summaries could be produced from fetched powerflow data"
)
redaction_summary = pd.concat(redaction_tables, ignore_index=True)
monthly_redaction = redaction_summary.groupby("period", as_index=False)[
["total_points", "redacted_points"]
].sum()
monthly_redaction["redaction_rate"] = (
monthly_redaction["redacted_points"] / monthly_redaction["total_points"]
)
best_month = monthly_redaction.sort_values("redaction_rate").iloc[0]["period"]
month_start = pd.Timestamp(best_month).normalize()
month_end = month_start + pd.offsets.MonthEnd(0)
print(f"Best month (least redaction): {month_start:%Y-%m}")
monthly_redaction.sort_values("redaction_rate").head()
--------------------------------------------------------------------------- RuntimeError Traceback (most recent call last) Cell In[20], line 51 48 redaction_tables.append(summary) 50 if not redaction_tables: ---> 51 raise RuntimeError( 52 "No redaction summaries could be produced from fetched powerflow data" 53 ) 55 redaction_summary = pd.concat(redaction_tables, ignore_index=True) 56 monthly_redaction = redaction_summary.groupby("period", as_index=False)[ 57 ["total_points", "redacted_points"] 58 ].sum() RuntimeError: No redaction summaries could be produced from fetched powerflow data
3) Cross-reference IDs and run QC checks¶
In [ ]:
Copied!
def filter_month(df: pd.DataFrame) -> pd.DataFrame:
if df.empty or "timestamp" not in df.columns:
return df.copy()
tmp = df.copy()
tmp["timestamp"] = pd.to_datetime(tmp["timestamp"], errors="coerce")
return tmp[
(tmp["timestamp"] >= month_start) & (tmp["timestamp"] <= month_end)
].copy()
pf_132_m = filter_month(pf_132)
pf_33_m = filter_month(pf_33)
pf_grid_m = filter_month(pf_grid)
pf_primary_m = filter_month(pf_primary)
line_series_parts = []
for df in [pf_132_m, pf_33_m]:
if {"timestamp", "active_power_mw"}.issubset(df.columns):
s = (
pd.to_numeric(df["active_power_mw"], errors="coerce")
.groupby(pd.to_datetime(df["timestamp"], errors="coerce"))
.sum(min_count=1)
)
line_series_parts.append(s)
transformer_series_parts = []
for df in [pf_grid_m, pf_primary_m]:
if {"timestamp", "active_power_mw"}.issubset(df.columns):
s = (
pd.to_numeric(df["active_power_mw"], errors="coerce")
.groupby(pd.to_datetime(df["timestamp"], errors="coerce"))
.sum(min_count=1)
)
transformer_series_parts.append(s)
if not line_series_parts or not transformer_series_parts:
raise RuntimeError(
"Missing active_power_mw series for line/transformer balance checks"
)
lines_total = pd.concat(line_series_parts, axis=1).sum(axis=1, min_count=1).sort_index()
transformers_total = (
pd.concat(transformer_series_parts, axis=1).sum(axis=1, min_count=1).sort_index()
)
lines_qc = quality_control(lines_total, expected_frequency="1D")
line_gaps = identify_gaps(lines_total, expected_frequency="1D", min_gap_hours=24.0)
lines_filled = fill_gaps(lines_total, method="linear", max_gap_hours=72.0)
line_anomalies = detect_rolling_anomalies(lines_filled, window_size=3, threshold=5.0)
line_steps = detect_step_changes(
lines_filled, threshold=0.1, window_size=2, min_confidence=0.5
)
balance_report = summarize_flow_balance(lines_filled, transformers_total, tolerance=0.2)
print(f"Line QC score: {lines_qc.quality_score:.1f}")
print(f"Line gaps detected: {len(line_gaps)}")
print(f"Line anomalies: {int(line_anomalies.sum())}")
print(f"Step changes: {len(line_steps)}")
balance_report
def filter_month(df: pd.DataFrame) -> pd.DataFrame:
if df.empty or "timestamp" not in df.columns:
return df.copy()
tmp = df.copy()
tmp["timestamp"] = pd.to_datetime(tmp["timestamp"], errors="coerce")
return tmp[
(tmp["timestamp"] >= month_start) & (tmp["timestamp"] <= month_end)
].copy()
pf_132_m = filter_month(pf_132)
pf_33_m = filter_month(pf_33)
pf_grid_m = filter_month(pf_grid)
pf_primary_m = filter_month(pf_primary)
line_series_parts = []
for df in [pf_132_m, pf_33_m]:
if {"timestamp", "active_power_mw"}.issubset(df.columns):
s = (
pd.to_numeric(df["active_power_mw"], errors="coerce")
.groupby(pd.to_datetime(df["timestamp"], errors="coerce"))
.sum(min_count=1)
)
line_series_parts.append(s)
transformer_series_parts = []
for df in [pf_grid_m, pf_primary_m]:
if {"timestamp", "active_power_mw"}.issubset(df.columns):
s = (
pd.to_numeric(df["active_power_mw"], errors="coerce")
.groupby(pd.to_datetime(df["timestamp"], errors="coerce"))
.sum(min_count=1)
)
transformer_series_parts.append(s)
if not line_series_parts or not transformer_series_parts:
raise RuntimeError(
"Missing active_power_mw series for line/transformer balance checks"
)
lines_total = pd.concat(line_series_parts, axis=1).sum(axis=1, min_count=1).sort_index()
transformers_total = (
pd.concat(transformer_series_parts, axis=1).sum(axis=1, min_count=1).sort_index()
)
lines_qc = quality_control(lines_total, expected_frequency="1D")
line_gaps = identify_gaps(lines_total, expected_frequency="1D", min_gap_hours=24.0)
lines_filled = fill_gaps(lines_total, method="linear", max_gap_hours=72.0)
line_anomalies = detect_rolling_anomalies(lines_filled, window_size=3, threshold=5.0)
line_steps = detect_step_changes(
lines_filled, threshold=0.1, window_size=2, min_confidence=0.5
)
balance_report = summarize_flow_balance(lines_filled, transformers_total, tolerance=0.2)
print(f"Line QC score: {lines_qc.quality_score:.1f}")
print(f"Line gaps detected: {len(line_gaps)}")
print(f"Line anomalies: {int(line_anomalies.sum())}")
print(f"Step changes: {len(line_steps)}")
balance_report
In [ ]:
Copied!
line_ratings = df_lines[line_rating_cols].copy() if line_rating_cols else pd.DataFrame()
transformer_ratings = (
df_transformers[transformer_rating_cols].copy()
if transformer_rating_cols
else pd.DataFrame()
)
print("Sample LTDS line ratings:")
display(
line_ratings.head(10)
if not line_ratings.empty
else "No obvious line rating columns detected"
)
print("Sample LTDS transformer ratings:")
display(
transformer_ratings.head(10)
if not transformer_ratings.empty
else "No obvious transformer rating columns detected"
)
line_ratings = df_lines[line_rating_cols].copy() if line_rating_cols else pd.DataFrame()
transformer_ratings = (
df_transformers[transformer_rating_cols].copy()
if transformer_rating_cols
else pd.DataFrame()
)
print("Sample LTDS line ratings:")
display(
line_ratings.head(10)
if not line_ratings.empty
else "No obvious line rating columns detected"
)
print("Sample LTDS transformer ratings:")
display(
transformer_ratings.head(10)
if not transformer_ratings.empty
else "No obvious transformer rating columns detected"
)
4) Visualisations¶
In [ ]:
Copied!
if not HAS_MATPLOTLIB:
print("matplotlib not installed; skipping plots")
else:
fig, axes = plt.subplots(3, 1, figsize=(12, 12))
# Redaction trend by month
axes[0].plot(
monthly_redaction["period"], monthly_redaction["redaction_rate"], marker="o"
)
axes[0].set_title("Monthly redaction rate across powerflow datasets")
axes[0].set_ylabel("Redaction rate")
# Aggregate line vs transformer active power
aligned = pd.concat(
[lines_filled.rename("lines"), transformers_total.rename("transformers")],
axis=1,
).dropna()
axes[1].plot(aligned.index, aligned["lines"], label="Lines total MW")
axes[1].plot(aligned.index, aligned["transformers"], label="Transformers total MW")
axes[1].set_title("Aggregated line vs transformer active power")
axes[1].legend()
# Anomalies and step changes
axes[2].plot(lines_filled.index, lines_filled.values, label="Lines total MW")
anomaly_points = lines_filled[line_anomalies]
if not anomaly_points.empty:
axes[2].scatter(
anomaly_points.index, anomaly_points.values, label="Anomalies", s=30
)
for step in line_steps:
axes[2].axvline(step.timestamp, linestyle="--", alpha=0.5)
axes[2].set_title("Line aggregate with anomalies and step changes")
axes[2].legend()
fig.tight_layout()
plt.show()
if not HAS_MATPLOTLIB:
print("matplotlib not installed; skipping plots")
else:
fig, axes = plt.subplots(3, 1, figsize=(12, 12))
# Redaction trend by month
axes[0].plot(
monthly_redaction["period"], monthly_redaction["redaction_rate"], marker="o"
)
axes[0].set_title("Monthly redaction rate across powerflow datasets")
axes[0].set_ylabel("Redaction rate")
# Aggregate line vs transformer active power
aligned = pd.concat(
[lines_filled.rename("lines"), transformers_total.rename("transformers")],
axis=1,
).dropna()
axes[1].plot(aligned.index, aligned["lines"], label="Lines total MW")
axes[1].plot(aligned.index, aligned["transformers"], label="Transformers total MW")
axes[1].set_title("Aggregated line vs transformer active power")
axes[1].legend()
# Anomalies and step changes
axes[2].plot(lines_filled.index, lines_filled.values, label="Lines total MW")
anomaly_points = lines_filled[line_anomalies]
if not anomaly_points.empty:
axes[2].scatter(
anomaly_points.index, anomaly_points.values, label="Anomalies", s=30
)
for step in line_steps:
axes[2].axvline(step.timestamp, linestyle="--", alpha=0.5)
axes[2].set_title("Line aggregate with anomalies and step changes")
axes[2].legend()
fig.tight_layout()
plt.show()
Summary¶
You now have a reproducible QC pattern that:
- Tracks candidate redaction by explicit markers with missingness fallback
- Selects a lower-redaction month before deeper diagnostics
- Compares aggregate line and transformer power totals
- Runs gap detection/filling, anomaly checks, and step-change checks
For project use, parameterise LICENCE_AREA, marker rules, and flow-balance tolerance for your governance standards.