Formula reference Every metric, score and threshold used across the AI Analytics reports, on a single page.
Every formula used across the reports, gathered in one place. Each formula is annotated with the report it belongs to and the context in which it applies. Math is rendered with KaTeX.
Composite scoring — multiplier logic
Combines independent signals as if they were independent probabilities. Used by Metering Bypass (node and fleet).
S composite = 100 ⋅ ( 1 − ∏ i = 1 N ( 1 − p i ) ) S_\text{composite} = 100 \cdot \left(1 - \prod_{i=1}^{N}(1 - p_i)\right) S composite = 100 ⋅ ( 1 − i = 1 ∏ N ( 1 − p i ) )
where p i ∈ [ 0 , 1 ] p_i \in [0, 1] p i ∈ [ 0 , 1 ] is the severity-derived probability of the i i i -th pattern that fired:
p i = { 0.00 severity = info 0.10 severity = low 0.30 severity = medium 0.50 severity = high 0.65 severity = high_plus p_i = \begin{cases}
0.00 & \text{severity}=\text{info} \\
0.10 & \text{severity}=\text{low} \\
0.30 & \text{severity}=\text{medium} \\
0.50 & \text{severity}=\text{high} \\
0.65 & \text{severity}=\text{high\_plus}
\end{cases} p i = ⎩ ⎨ ⎧ 0.00 0.10 0.30 0.50 0.65 severity = info severity = low severity = medium severity = high severity = high_plus
Example. Two high+ patterns give S = 100 ⋅ ( 1 − 0.35 2 ) = 87.75 S = 100 \cdot (1 - 0.35^2) = 87.75 S = 100 ⋅ ( 1 − 0.3 5 2 ) = 87.75 . The score deliberately cannot reach 100 from pattern detection alone — saturating to 100 requires confirmed device events (confidence ceiling = medium without them).
Weighted-sum scoring
Top Problem Nodes (five measurements):
S composite = ∑ k ∈ K w k ⋅ s k , K = { battery , telem , quality , risk , events } S_\text{composite} = \sum_{k \in K} w_k \cdot s_k, \quad K = \{\text{battery}, \text{telem}, \text{quality}, \text{risk}, \text{events}\} S composite = k ∈ K ∑ w k ⋅ s k , K = { battery , telem , quality , risk , events }
Equal weighting, w k = 20 % w_k = 20\% w k = 20% each.
Top Gas Leaks (four sub-scores, unequal weights):
S leak = 0.4 ⋅ s quiet + 0.3 ⋅ s baseline + 0.2 ⋅ s drip + 0.1 ⋅ s drift S_\text{leak} = 0.4 \cdot s_\text{quiet} + 0.3 \cdot s_\text{baseline} + 0.2 \cdot s_\text{drip} + 0.1 \cdot s_\text{drift} S leak = 0.4 ⋅ s quiet + 0.3 ⋅ s baseline + 0.2 ⋅ s drip + 0.1 ⋅ s drift
Pattern detectors — Metering Bypass
Pattern 1 — zero flow at a default pressure (severity = high+, p = 0.65):
trigger = ( Q ˉ ≤ 0.5 m³/h over a window ≥ 6 h ) ∧ ( σ P < 0.1 kPa ) ∧ ( P ∈ D ) \text{trigger} = (\bar Q \leq 0.5\,\text{m³/h over a window} \geq 6\,\text{h}) \land (\sigma_P < 0.1\,\text{kPa}) \land (P \in \mathcal{D}) trigger = ( Q ˉ ≤ 0.5 m³/h over a window ≥ 6 h ) ∧ ( σ P < 0.1 kPa ) ∧ ( P ∈ D )
D = { 100.0 , 101.325 , 103.0 , 105.0 } ± 0.5 ∪ { 0.0 } ± 0.3 \mathcal{D} = \{100.0, 101.325, 103.0, 105.0\}_{\pm 0.5} \cup \{0.0\}_{\pm 0.3} D = { 100.0 , 101.325 , 103.0 , 105.0 } ± 0.5 ∪ { 0.0 } ± 0.3 (kPa). These are the canonical default values a flow computer falls back to when the pressure transducer is disconnected or substituted.
Pattern 2 — zero flow with a stuck pressure (severity = medium, p = 0.30). Violation of the Gay-Lussac law for a sealed gas volume.
trigger = ( Q ˉ ≤ 0.5 m³/h ) ∧ ( Δ T ≥ 1 °C ) ∧ ( σ P < 0.1 kPa ) \text{trigger} = (\bar Q \leq 0.5\,\text{m³/h}) \land (\Delta T \geq 1\text{°C}) \land (\sigma_P < 0.1\,\text{kPa}) trigger = ( Q ˉ ≤ 0.5 m³/h ) ∧ ( Δ T ≥ 1 °C ) ∧ ( σ P < 0.1 kPa )
Expected ΔP per Gay-Lussac (isochoric process):
P 1 T 1 = P 2 T 2 ⟹ Δ P expected = P abs ( 1 ) ⋅ Δ T K T 1 ( K ) \frac{P_1}{T_1} = \frac{P_2}{T_2} \;\Longrightarrow\; \Delta P_\text{expected} = P_\text{abs}^{(1)} \cdot \frac{\Delta T_K}{T_1^{(K)}} T 1 P 1 = T 2 P 2 ⟹ Δ P expected = P abs ( 1 ) ⋅ T 1 ( K ) Δ T K
where:
P abs ( 1 ) = P gauge + 101.325 P_\text{abs}^{(1)} = P_\text{gauge} + 101.325 P abs ( 1 ) = P gauge + 101.325 kPa if P gauge < 50 P_\text{gauge} < 50 P gauge < 50 kPa (gauge sensor); otherwise P abs = P kPa P_\text{abs} = P_\text{kPa} P abs = P kPa
T ( K ) = T ° C + 273.15 T^{(K)} = T_{°C} + 273.15 T ( K ) = T ° C + 273.15
Δ T K = ∣ T 2 ( K ) − T 1 ( K ) ∣ = ∣ T 2 ° C − T 1 ° C ∣ \Delta T_K = |T_2^{(K)} - T_1^{(K)}| = |T_2^{°C} - T_1^{°C}| Δ T K = ∣ T 2 ( K ) − T 1 ( K ) ∣ = ∣ T 2 ° C − T 1 ° C ∣ (Kelvin diff ≡ Celsius diff)
“P is frozen” fires when:
Δ P expected σ P ≥ 3 \frac{\Delta P_\text{expected}}{\sigma_P} \geq 3 σ P Δ P expected ≥ 3
False-positive guard — network node. Gay-Lussac only applies to a closed volume . In a node connected to the gas main, gauge pressure is held by the network regulator, not by gas physics. Before the detector fires:
is_network = ( median ( P gauge ) < 10 kPa ) ∧ ( σ P (window) < 2 kPa ) ∧ ¬ is_p_sensor_broken \text{is\_network} = (\text{median}(P_\text{gauge}) < 10\,\text{kPa}) \land (\sigma_P^\text{(window)} < 2\,\text{kPa}) \land \neg \text{is\_p\_sensor\_broken} is_network = ( median ( P gauge ) < 10 kPa ) ∧ ( σ P (window) < 2 kPa ) ∧ ¬ is_p_sensor_broken
If the node is a network node, all stuck-pressure events are excluded from the score and an informational card is added.
Pattern 3 — recovery after a zero-flow run (severity = high, p = 0.50). Synchronous Q + P jump immediately after a long zero-flow run:
trigger = ∃ t ∈ [ end run , + 2 h ] : Q ( t ) ≥ 10 ∧ ∣ Δ P ∣ ≥ 20 kPa \text{trigger} = \exists\, t \in [\text{end}_\text{run}, +2\text{h}] : Q(t) \geq 10 \land |\Delta P| \geq 20\,\text{kPa} trigger = ∃ t ∈ [ end run , + 2 h ] : Q ( t ) ≥ 10 ∧ ∣Δ P ∣ ≥ 20 kPa
Pattern 4 — gap with clean sessions (severity = medium, p = 0.30). Hours of missing archive while the device was demonstrably reachable:
trigger = ( missing_hours ≥ 24 ) ∧ ( successful_sessions_in_gap ≥ 1 ) \text{trigger} = (\text{missing\_hours} \geq 24) \land (\text{successful\_sessions\_in\_gap} \geq 1) trigger = ( missing_hours ≥ 24 ) ∧ ( successful_sessions_in_gap ≥ 1 )
Pre-filters (false-positive guards)
Signal Threshold Effect P sensor broken P frozen ≥ 168 h at any time in the window all P-based detectors disabled Network-connected median(P_gauge) < 10 kPa AND σ_P < 2 kPa AND not broken stuck-pressure pattern excluded from the score Telemetry spike P > 500 P > 500 P > 500 kPa OR (Q > 20 × median ( Q ) Q > 20 \times \text{median}(Q) Q > 20 × median ( Q ) while Q > 1000 m³/h)row replaced with NULL before tampering logic
Severity cap, applied after all detectors and before the suspicion score:
Composition of events Max allowed level has high+ very high has high high two or more medium high exactly one medium medium only low or nothing medium
Coverage and data quality — Consumption Analytics
cov = H OK + H NULL H expected , unobs % = ( 1 − cov ) ⋅ 100 % \text{cov} = \frac{H_\text{OK} + H_\text{NULL}}{H_\text{expected}}, \quad
\text{unobs}_\% = (1 - \text{cov}) \cdot 100\% cov = H expected H OK + H NULL , unobs % = ( 1 − cov ) ⋅ 100%
Condition Severity tail_h > 168 hcritical unobs_pct > 30%high unobs_pct > 10%medium otherwise low
Estimated unobserved volume (two methods). Mean-flow extrapolation:
V unobs ( mean ) = Q ˉ OK ⋅ H unobs V^{(\text{mean})}_\text{unobs} = \bar Q_\text{OK} \cdot H_\text{unobs} V unobs ( mean ) = Q ˉ OK ⋅ H unobs
Diurnal-profile reconstruction:
V unobs ( profile ) = ∑ h ∈ unobs Q ˉ h V^{(\text{profile})}_\text{unobs} = \sum_{h \in \text{unobs}} \bar Q_h V unobs ( profile ) = h ∈ unobs ∑ Q ˉ h
Operational idle threshold:
∣ { h : Q ( h ) < 0.05 } ∣ H OK > 0.95 ⇒ idle mode (zero consumption is not penalised) \frac{|\{h : Q(h) < 0.05\}|}{H_\text{OK}} > 0.95 \Rightarrow \text{idle mode (zero consumption is not penalised)} H OK ∣ { h : Q ( h ) < 0.05 } ∣ > 0.95 ⇒ idle mode (zero consumption is not penalised)
Q/V reconciliation:
Δ V integral = ∑ h Q ( h ) ⋅ 1 h , Δ V counter = V ( t end ) − V ( t start ) \Delta V_\text{integral} = \sum_h Q(h) \cdot 1\text{h}, \quad \Delta V_\text{counter} = V(t_\text{end}) - V(t_\text{start}) Δ V integral = h ∑ Q ( h ) ⋅ 1 h , Δ V counter = V ( t end ) − V ( t start )
raise Q/V mismatch if ∣ Δ V counter − Δ V integral ∣ Δ V counter > 5 % \text{raise Q/V mismatch if } \frac{|\Delta V_\text{counter} - \Delta V_\text{integral}|}{\Delta V_\text{counter}} > 5\% raise Q/V mismatch if Δ V counter ∣Δ V counter − Δ V integral ∣ > 5%
The 5% tolerance follows OIML R 137 class 1.0 plus an integration round-off allowance.
Sub-scores — Top Problem Nodes
Fast pre-rank (metadata only):
S fast = d pts ( days_since_last_session ) + s pts ( status ) S_\text{fast} = d_\text{pts}(\text{days\_since\_last\_session}) + s_\text{pts}(\text{status}) S fast = d pts ( days_since_last_session ) + s pts ( status )
d pts ( d ) = { 100 d ≥ 60 60 + ( d − 30 ) ⋅ 1.33 30 ≤ d < 60 20 + ( d − 7 ) ⋅ 1.74 7 ≤ d < 30 d ⋅ 2.85 d < 7 d_\text{pts}(d) = \begin{cases}
100 & d \geq 60 \\
60 + (d-30) \cdot 1.33 & 30 \leq d < 60 \\
20 + (d-7) \cdot 1.74 & 7 \leq d < 30 \\
d \cdot 2.85 & d < 7
\end{cases} d pts ( d ) = ⎩ ⎨ ⎧ 100 60 + ( d − 30 ) ⋅ 1.33 20 + ( d − 7 ) ⋅ 1.74 d ⋅ 2.85 d ≥ 60 30 ≤ d < 60 7 ≤ d < 30 d < 7
s pts = 30 s_\text{pts} = 30 s pts = 30 if the device status is not “operational”, otherwise 0.
Battery sub-score (mV):
v pts = { 100 V last < 3000 80 V last < 3200 50 V last < 3400 25 V last < 3600 0 otherwise v_\text{pts} = \begin{cases}
100 & V_\text{last} < 3000 \\
80 & V_\text{last} < 3200 \\
50 & V_\text{last} < 3400 \\
25 & V_\text{last} < 3600 \\
0 & \text{otherwise}
\end{cases} v pts = ⎩ ⎨ ⎧ 100 80 50 25 0 V last < 3000 V last < 3200 V last < 3400 V last < 3600 otherwise
S battery = min ( 100 , v pts + d pts ( drop_pct ) ) S_\text{battery} = \min(100, v_\text{pts} + d_\text{pts}(\text{drop\_pct})) S battery = min ( 100 , v pts + d pts ( drop_pct ))
where d pts = 30 d_\text{pts} = 30 d pts = 30 if drop > 10%, 15 if drop > 5%, otherwise 0.
Risk sub-score:
S risk = 1 1.85 ∑ i min ( cap i , α i ⋅ n i ) S_\text{risk} = \frac{1}{1.85} \sum_i \min(\text{cap}_i, \alpha_i \cdot n_i) S risk = 1.85 1 i ∑ min ( cap i , α i ⋅ n i )
Signal n i n_i n i α i \alpha_i α i cap quiet_n_pct0.8 40 n_plateau4 20 n_neg (binary)25 25 n_live_p8 40 n_pt_resets6 30 n_drop_rec5 30
Events sub-score:
Condition S events S_\text{events} S events physical AND substitution 100 physical only 80 substitution only 60 metrology / system error only 30 no events 0
Battery threshold — Battery Forecast and Fleet Battery Forecast
Per-source score (% or mV):
S metro = clip [ 0 , 100 ] ( V − V crit V fresh − V crit ⋅ 100 ) S_\text{metro} = \text{clip}_{[0,100]}\left(\frac{V - V_\text{crit}}{V_\text{fresh} - V_\text{crit}} \cdot 100\right) S metro = clip [ 0 , 100 ] ( V fresh − V crit V − V crit ⋅ 100 )
Scale V crit V_\text{crit} V crit V fresh V_\text{fresh} V fresh % (metering Li-SOCl₂) 20 90 mV (telemetry Li-pol) 3300 3600
Composite (weakest link):
S battery = min ( S metro , S telem ) S_\text{battery} = \min(S_\text{metro}, S_\text{telem}) S battery = min ( S metro , S telem )
Forecast T crit T_\text{crit} T crit (three scenarios):
T crit ( opt ) = t now + V now − V crit ∣ drop_rate ∣ T_\text{crit}^{(\text{opt})} = t_\text{now} + \frac{V_\text{now} - V_\text{crit}}{|\text{drop\_rate}|} T crit ( opt ) = t now + ∣ drop_rate ∣ V now − V crit
T crit ( real ) = T crit ( opt ) ⋅ ( 1 − α accel ) T_\text{crit}^{(\text{real})} = T_\text{crit}^{(\text{opt})} \cdot (1 - \alpha_\text{accel}) T crit ( real ) = T crit ( opt ) ⋅ ( 1 − α accel )
T crit ( pess ) = T crit ( real ) ⋅ 0.5 T_\text{crit}^{(\text{pess})} = T_\text{crit}^{(\text{real})} \cdot 0.5 T crit ( pess ) = T crit ( real ) ⋅ 0.5
When a replacement event is found in the report window, all linear regressions are restricted to the period after the replacement. Otherwise the voltage jump at replacement (for example, 3225 → 4197 mV) gives a spurious positive slope — physically impossible for a non-rechargeable Li-pol.
slope real = linreg ( { ( t i , v i ) : t i ≥ t replacement } ) \text{slope}_\text{real} = \text{linreg}\big(\{(t_i, v_i) : t_i \geq t_\text{replacement}\}\big) slope real = linreg ( {( t i , v i ) : t i ≥ t replacement } )
Telemetry-block replacement. For devices whose battery is a non-cycling telemetry pack, the “day-to-critical from discharge” forecast does not apply. The replacement decision is taken as the worst of three independent criteria.
Calendar age:
age_status = { ok y age < 0.75 ⋅ y expected plan 0.75 ⋅ y expected ≤ y age < y expected due y age ≥ y expected \text{age\_status} = \begin{cases}
\text{ok} & y_\text{age} < 0.75 \cdot y_\text{expected} \\
\text{plan} & 0.75 \cdot y_\text{expected} \leq y_\text{age} < y_\text{expected} \\
\text{due} & y_\text{age} \geq y_\text{expected}
\end{cases} age_status = ⎩ ⎨ ⎧ ok plan due y age < 0.75 ⋅ y expected 0.75 ⋅ y expected ≤ y age < y expected y age ≥ y expected
where y expected = 3 y_\text{expected} = 3 y expected = 3 years (Li-pol passport life).
Sessions used against the pack budget:
sessions_status = { ok ratio < 0.75 plan 0.75 ≤ ratio < 1.0 due ratio ≥ 1.0 , ratio = sessions_used 2000 \text{sessions\_status} = \begin{cases}
\text{ok} & \text{ratio} < 0.75 \\
\text{plan} & 0.75 \leq \text{ratio} < 1.0 \\
\text{due} & \text{ratio} \geq 1.0
\end{cases}, \quad \text{ratio} = \frac{\text{sessions\_used}}{2000} sessions_status = ⎩ ⎨ ⎧ ok plan due ratio < 0.75 0.75 ≤ ratio < 1.0 ratio ≥ 1.0 , ratio = 2000 sessions_used
The 2000-session budget matches a 2000 mAh pack (≈ 1 mAh per session under TX load).
Degradation under load (last 30 d vs 180–150 d ago):
deg_pct = 100 ⋅ min ( V old ) − min ( V recent ) min ( V old ) \text{deg\_pct} = 100 \cdot \frac{\min(V_\text{old}) - \min(V_\text{recent})}{\min(V_\text{old})} deg_pct = 100 ⋅ min ( V old ) min ( V old ) − min ( V recent )
deg_status = { ok deg_pct < 3 % watch 3 % ≤ deg_pct < 8 % degraded deg_pct ≥ 8 % \text{deg\_status} = \begin{cases}
\text{ok} & \text{deg\_pct} < 3\% \\
\text{watch} & 3\% \leq \text{deg\_pct} < 8\% \\
\text{degraded} & \text{deg\_pct} \geq 8\%
\end{cases} deg_status = ⎩ ⎨ ⎧ ok watch degraded deg_pct < 3% 3% ≤ deg_pct < 8% deg_pct ≥ 8%
Final verdict (worst of three):
overall = { due any of { age, sessions, deg } ∈ { due, degraded } plan else if any ∈ { plan, watch } ok otherwise \text{overall} = \begin{cases}
\text{due} & \text{any of } \{\text{age, sessions, deg}\} \in \{\text{due, degraded}\} \\
\text{plan} & \text{else if any} \in \{\text{plan, watch}\} \\
\text{ok} & \text{otherwise}
\end{cases} overall = ⎩ ⎨ ⎧ due plan ok any of { age, sessions, deg } ∈ { due, degraded } else if any ∈ { plan, watch } otherwise
Battery capacity for signal / consumption models:
Δ V period = V first − V last , Δ C used = Δ V ⋅ C mAh 1200 mV \Delta V_\text{period} = V_\text{first} - V_\text{last}, \quad
\Delta C_\text{used} = \Delta V \cdot \frac{C_\text{mAh}}{1200\text{ mV}} Δ V period = V first − V last , Δ C used = Δ V ⋅ 1200 mV C mAh
where 1200 mV is the Li-pol voltage swing from nominal to fully discharged (3.0 → 4.2 V). Anomalous-drop detection fires when the drop rate over the last 30 days exceeds twice the 90-day baseline.
Leak detection — Top Gas Leaks
Adaptive per-station threshold:
θ leak = max ( 0.05 , P 95 ( Q ) ⋅ 0.05 ) \theta_\text{leak} = \max(0.05, P_{95}(Q) \cdot 0.05) θ leak = max ( 0.05 , P 95 ( Q ) ⋅ 0.05 )
5% of each station’s own p95 — adaptive, so commercial sites are not flagged at the same threshold as residential ones.
Sub-scores:
s quiet = 100 ⋅ min h ∈ [ 2 , 5 ] Q ( h ) θ leak (capped at 100) s_\text{quiet} = 100 \cdot \frac{\min_{h \in [2,5]} Q(h)}{\theta_\text{leak}} \text{ (capped at 100)} s quiet = 100 ⋅ θ leak min h ∈ [ 2 , 5 ] Q ( h ) (capped at 100)
s baseline = 100 ⋅ P 5 ( Q ) θ leak (capped at 100) s_\text{baseline} = 100 \cdot \frac{P_5(Q)}{\theta_\text{leak}} \text{ (capped at 100)} s baseline = 100 ⋅ θ leak P 5 ( Q ) (capped at 100)
s drip = 100 ⋅ ∣ { h : 0.5 θ ≤ Q ( h ) ≤ 2 θ } ∣ ∣ H ∣ s_\text{drip} = 100 \cdot \frac{|\{h : 0.5\theta \leq Q(h) \leq 2\theta\}|}{|H|} s drip = 100 ⋅ ∣ H ∣ ∣ { h : 0.5 θ ≤ Q ( h ) ≤ 2 θ } ∣
s drift = 100 ⋅ tanh ( slope ( P 5 ) θ leak / month ) s_\text{drift} = 100 \cdot \tanh\left(\frac{\text{slope}(P_5)}{\theta_\text{leak} / \text{month}}\right) s drift = 100 ⋅ tanh ( θ leak / month slope ( P 5 ) )
CO₂e calculations — Decarbonization and Emissions and Energy
Methane → CO₂e:
m CH4 = V leak ⋅ ϕ CH4 ⋅ ρ CH4 , ρ CH4 = 0.68 kg/m³ m_\text{CH4} = V_\text{leak} \cdot \phi_\text{CH4} \cdot \rho_\text{CH4}, \quad \rho_\text{CH4} = 0.68 \text{ kg/m³} m CH4 = V leak ⋅ ϕ CH4 ⋅ ρ CH4 , ρ CH4 = 0.68 kg/m³
m CO2e ( GWP100 ) = m CH4 ⋅ 28 , m CO2e ( GWP20 ) = m CH4 ⋅ 84 m_\text{CO2e}^{(\text{GWP100})} = m_\text{CH4} \cdot 28, \quad m_\text{CO2e}^{(\text{GWP20})} = m_\text{CH4} \cdot 84 m CO2e ( GWP100 ) = m CH4 ⋅ 28 , m CO2e ( GWP20 ) = m CH4 ⋅ 84
GWP factors per IPCC AR6 (the 20-year factor reflects the short-term warming impact relevant for near-term mitigation targets).
Direct CO₂ (from burnt gas):
m CO2,direct = V consumed ⋅ EF CO2 , EF CO2 = 1.96 kg/m³ m_\text{CO2,direct} = V_\text{consumed} \cdot \text{EF}_\text{CO2}, \quad \text{EF}_\text{CO2} = 1.96 \text{ kg/m³} m CO2,direct = V consumed ⋅ EF CO2 , EF CO2 = 1.96 kg/m³
Energy:
E GJ = V ⋅ HHV , HHV = 37.0 MJ/m³ E_\text{GJ} = V \cdot \text{HHV}, \quad \text{HHV} = 37.0 \text{ MJ/m³} E GJ = V ⋅ HHV , HHV = 37.0 MJ/m³
E kWh = E GJ ⋅ 1000 3.6 E_\text{kWh} = E_\text{GJ} \cdot \frac{1000}{3.6} E kWh = E GJ ⋅ 3.6 1000
Investment scenarios — Decarbonization and Automation ROI
CAPEX / OPEX (per node):
CAPEX total = N ⋅ capex_per_node , OPEX / year = N ⋅ opex_per_node_per_year \text{CAPEX}_\text{total} = N \cdot \text{capex\_per\_node}, \quad \text{OPEX}/\text{year} = N \cdot \text{opex\_per\_node\_per\_year} CAPEX total = N ⋅ capex_per_node , OPEX / year = N ⋅ opex_per_node_per_year
Value / Payback:
Value / year = ∑ hot spots ( gas + carbon GWP100 ) \text{Value}/\text{year} = \sum_\text{hot spots}(\text{gas} + \text{carbon}_\text{GWP100}) Value / year = hot spots ∑ ( gas + carbon GWP100 )
Payback months = { CAPEX Value − OPEX ⋅ 12 Value > OPEX none otherwise \text{Payback}_\text{months} = \begin{cases}
\dfrac{\text{CAPEX}}{\text{Value} - \text{OPEX}} \cdot 12 & \text{Value} > \text{OPEX} \\
\text{none} & \text{otherwise}
\end{cases} Payback months = ⎩ ⎨ ⎧ Value − OPEX CAPEX ⋅ 12 none Value > OPEX otherwise
ROI / TCO:
ROI = Value/year − OPEX/year CAPEX total ⋅ 100 % \text{ROI} = \frac{\text{Value/year} - \text{OPEX/year}}{\text{CAPEX}_\text{total}} \cdot 100\% ROI = CAPEX total Value/year − OPEX/year ⋅ 100%
TCO 5 = CAPEX total + 5 ⋅ OPEX/year \text{TCO}_5 = \text{CAPEX}_\text{total} + 5 \cdot \text{OPEX/year} TCO 5 = CAPEX total + 5 ⋅ OPEX/year
Demand forecasting — Gas Demand Forecast
Linear model (OLS):
Q ( t ) = β 0 + β 1 t + ∑ k = 1 2 [ α k sin ( 2 π k t / 365 ) + γ k cos ( 2 π k t / 365 ) ] + ∑ j = 1 6 w j 1 dow = j + δ ⋅ HDD ( t ) + ε Q(t) = \beta_0 + \beta_1 t + \sum_{k=1}^{2}[\alpha_k \sin(2\pi k t/365) + \gamma_k \cos(2\pi k t/365)] + \sum_{j=1}^{6} w_j \mathbb{1}_{\text{dow}=j} + \delta \cdot \text{HDD}(t) + \varepsilon Q ( t ) = β 0 + β 1 t + k = 1 ∑ 2 [ α k sin ( 2 π k t /365 ) + γ k cos ( 2 π k t /365 )] + j = 1 ∑ 6 w j 1 dow = j + δ ⋅ HDD ( t ) + ε
Trend + two-harmonic annual seasonality + day-of-week dummies + a heating-degree-day term.
HDD:
HDD ( t ) = max ( 0 , 18 ° C − T ˉ ( t ) ) \text{HDD}(t) = \max(0, 18°C - \bar T(t)) HDD ( t ) = max ( 0 , 18° C − T ˉ ( t ))
95% CI:
Q ^ ( t ) ± 1.96 ⋅ σ ^ ε ⋅ 1 + h ( t ) \hat Q(t) \pm 1.96 \cdot \hat\sigma_\varepsilon \cdot \sqrt{1 + h(t)} Q ^ ( t ) ± 1.96 ⋅ σ ^ ε ⋅ 1 + h ( t )
Backtest:
MAE = 1 N ∑ t ∣ Q ( t ) − Q ^ ( t ) ∣ , MAPE = 1 N ∑ t ∣ Q ( t ) − Q ^ ( t ) ∣ Q ( t ) ⋅ 100 % \text{MAE} = \frac{1}{N} \sum_t |Q(t) - \hat Q(t)|, \quad \text{MAPE} = \frac{1}{N} \sum_t \frac{|Q(t) - \hat Q(t)|}{Q(t)} \cdot 100\% MAE = N 1 t ∑ ∣ Q ( t ) − Q ^ ( t ) ∣ , MAPE = N 1 t ∑ Q ( t ) ∣ Q ( t ) − Q ^ ( t ) ∣ ⋅ 100%
Coverage 95 % = 1 N ∑ t 1 Q ( t ) ∈ [ Q ^ t ± 1.96 σ ^ ] \text{Coverage}_{95\%} = \frac{1}{N} \sum_t \mathbb{1}_{Q(t) \in [\hat Q_t \pm 1.96\hat\sigma]} Coverage 95% = N 1 t ∑ 1 Q ( t ) ∈ [ Q ^ t ± 1.96 σ ^ ]
Healthy fit: coverage ≈ 95%, MAPE < 15%.
Pressure anomalies — Pressure Anomalies
Outage:
outage ( t ) = 1 P ( t ) = null ∨ P ( t ) = 0 \text{outage}(t) = \mathbb{1}_{P(t) = \text{null} \lor P(t) = 0} outage ( t ) = 1 P ( t ) = null ∨ P ( t ) = 0
Sharp drop:
drop ( t ) = 1 P ( t − 1 ) − P ( t ) > 5 kPa/h \text{drop}(t) = \mathbb{1}_{P(t-1) - P(t) > 5 \text{ kPa/h}} drop ( t ) = 1 P ( t − 1 ) − P ( t ) > 5 kPa/h
Baseline drift:
drift 30 d = P 5 ( last 30d ) − P 5 ( first 30d ) P 5 ( first 30d ) ⋅ 100 % \text{drift}_{30d} = \frac{P_5^{(\text{last 30d})} - P_5^{(\text{first 30d})}}{P_5^{(\text{first 30d})}} \cdot 100\% drift 30 d = P 5 ( first 30d ) P 5 ( last 30d ) − P 5 ( first 30d ) ⋅ 100%
Raise a baseline-drift incident if |drift| > 20% over the analyzed period.
Instability (rolling):
instability ( t ) = σ P ( 24 h ) P ˉ ( 24 h ) \text{instability}(t) = \frac{\sigma_P^{(24h)}}{\bar P^{(24h)}} instability ( t ) = P ˉ ( 24 h ) σ P ( 24 h )
Raise an instability incident if the ratio exceeds 0.3 over a window ≥ 6 hours.
Long sessions — IQR detection
Per-station threshold:
θ long = Q 3 + 1.5 ⋅ IQR , IQR = Q 3 − Q 1 \theta_\text{long} = Q_3 + 1.5 \cdot \text{IQR}, \quad \text{IQR} = Q_3 - Q_1 θ long = Q 3 + 1.5 ⋅ IQR , IQR = Q 3 − Q 1
A robust outlier detector — better than z-score for the skewed distribution of polling-session durations.
Severity score:
S = 40 ⋅ long_frac + 30 ⋅ t ˉ anomaly θ long + 30 ⋅ n_incidents_critical S = 40 \cdot \text{long\_frac} + 30 \cdot \frac{\bar t_\text{anomaly}}{\theta_\text{long}} + 30 \cdot \text{n\_incidents\_critical} S = 40 ⋅ long_frac + 30 ⋅ θ long t ˉ anomaly + 30 ⋅ n_incidents_critical
Home energy — Household Report
Breakdown template (single-family house):
Segment Share Space heating 60% Domestic hot water 20% Cooking 10% Other 10%
Savings from insulation:
Δ V insulation = V heating ⋅ 0.15 (typical retrofit) \Delta V_\text{insulation} = V_\text{heating} \cdot 0.15 \text{ (typical retrofit)} Δ V insulation = V heating ⋅ 0.15 (typical retrofit)
Compound interest (savings deposited at rate r):
Reinvest T = Savings ⋅ ( 1 + r ) T − 1 r \text{Reinvest}_T = \text{Savings} \cdot \frac{(1 + r)^T - 1}{r} Reinvest T = Savings ⋅ r ( 1 + r ) T − 1
Severity classification — unified scale
Range Severity Color Context 0–9 OK green composite, top problem nodes 10–29 Low blue composite 30–49 Medium yellow composite 50–69 High orange composite, top problem nodes warning 70–100 Critical red composite, top problem nodes critical
Top Problem Nodes uses thresholds 30 / 60 — more of the green band is treated as the “normal” state.
Confidence framework — Decarbonization and Metering Bypass
Confidence Condition High deep score ≥ 80 with ≥ 6 months of data Medium deep score ≥ 50 or limited data history Low low score / fallback estimation
Field-investigation priority — Metering Bypass
Condition Priority Recent physical event (≤ 7 d) P0 (override)Older physical event (> 7 d) P1 score ≥ 70 with confidence medium or high P0 score ≥ 70 with confidence low P1 score ≥ 50 P1 score ≥ 30 P2 score < 30 P3
Constants reference
Symbol Value Source Used in EF CO2 \text{EF}_\text{CO2} EF CO2 1.96 kg/m³ IPCC AR6 Decarbonization, Emissions and Energy HHV \text{HHV} HHV 37.0 MJ/m³ natural-gas typical (IEA) Emissions and Energy ρ CH4 \rho_\text{CH4} ρ CH4 0.68 kg/m³ standard conditions Decarbonization GWP 100 \text{GWP}_{100} GWP 100 28 IPCC AR6, 100-year Decarbonization, Emissions and Energy GWP 20 \text{GWP}_{20} GWP 20 84 IPCC AR6, 20-year Decarbonization, Emissions and Energy Near-zero flow 0.5 m³/h empirical Metering Bypass Min zero-flow run 6 h empirical Metering Bypass Stuck-pressure σ 0.1 kPa empirical Metering Bypass Min ΔT for Gay-Lussac 1.0 °C empirical Metering Bypass Recovery Q min 10 m³/h empirical Metering Bypass Recovery ΔP min 20 kPa empirical Metering Bypass Physical P max 500 kPa physical limit Metering Bypass pre-filter Q spike multiplier 20× empirical Metering Bypass pre-filter P-sensor-broken stuck time 168 h empirical Metering Bypass sensor health HDD base temperature 18 °C IPCC Gas Demand Forecast Default leak fraction 0.5% IEA fleet average Decarbonization fallback
Methodological references: IPCC AR6 (WG I, Ch. 7) for GWP and emission factors; OIML R 137-1 for flow-meter accuracy classes; ISO 5167 and AGA Report No. 3 for differential-pressure flow calculation; EN 1776 for metering-station design conventions; GHG Protocol Scope 1 for direct-combustion CO₂ accounting.