|
from dataclasses import dataclass |
|
from enum import Enum |
|
|
|
import pandas as pd |
|
|
|
from ecologits.impacts.modeling import Impacts, Energy, GWP, ADPe, PE |
|
from ecologits.tracers.utils import llm_impacts, _avg |
|
from pint import UnitRegistry, Quantity |
|
|
|
|
|
u = UnitRegistry() |
|
u.define('Wh = watt_hour') |
|
u.define('kWh = kilowatt_hour') |
|
u.define('MWh = megawatt_hour') |
|
u.define('GWh = gigawatt_hour') |
|
u.define('TWh = terawatt_hour') |
|
u.define('gCO2eq = gram') |
|
u.define('kgCO2eq = kilogram') |
|
u.define('tCO2eq = metricton') |
|
u.define('kgSbeq = kilogram') |
|
u.define('kJ = kilojoule') |
|
u.define('MJ = megajoule') |
|
u.define('m = meter') |
|
u.define('km = kilometer') |
|
u.define('s = second') |
|
u.define('min = minute') |
|
u.define('h = hour') |
|
q = u.Quantity |
|
|
|
|
|
@dataclass |
|
class QImpacts: |
|
energy: Quantity |
|
gwp: Quantity |
|
adpe: Quantity |
|
pe: Quantity |
|
|
|
|
|
class PhysicalActivity(str, Enum): |
|
RUNNING = "running" |
|
WALKING = "walking" |
|
|
|
|
|
class EnergyProduction(str, Enum): |
|
NUCLEAR = "nuclear" |
|
WIND = "wind" |
|
|
|
|
|
COUNTRIES = [ |
|
("cook_islands", 38.81, 9_556), |
|
("tonga", 51.15, 104_490), |
|
("comoros", 100, 821_632), |
|
("samoa", 100, 821_632), |
|
] |
|
|
|
def df_elec_mix_for_plot(): |
|
return pd.DataFrame({ |
|
'country': ['Sweden', 'France', 'Canada', 'USA', 'China', 'Australia', 'India'], |
|
'electricity_mix': [46, 81, 238, 679, 1057, 1123, 1583] |
|
}) |
|
|
|
|
|
RUNNING_ENERGY_EQ = q("294 kJ / km") |
|
WALKING_ENERGY_EQ = q("196 kJ / km") |
|
|
|
|
|
|
|
EV_ENERGY_EQ = q("0.17 kWh / km") |
|
|
|
|
|
STREAMING_GWP_EQ = q("15.6 h / kgCO2eq") |
|
|
|
|
|
ONE_PERCENT_WORLD_POPULATION = 80_000_000 |
|
|
|
DAYS_IN_YEAR = 365 |
|
|
|
|
|
|
|
YEARLY_NUCLEAR_ENERGY_EQ = q("6 TWh") |
|
|
|
|
|
|
|
YEARLY_WIND_ENERGY_EQ = q("4.2 GWh") |
|
|
|
|
|
|
|
YEARLY_IRELAND_ELECTRICITY_CONSUMPTION = q("33 TWh") |
|
IRELAND_POPULATION_MILLION = 5 |
|
|
|
|
|
AIRPLANE_PARIS_NYC_GWP_EQ = q("177000 kgCO2eq") |
|
|
|
|
|
def format_energy(energy: Energy) -> Quantity: |
|
val = q(energy.value, energy.unit) |
|
if val < q("1 kWh"): |
|
val = val.to("Wh") |
|
return val |
|
|
|
|
|
def format_gwp(gwp: GWP) -> Quantity: |
|
val = q(gwp.value, gwp.unit) |
|
if val < q("1 kgCO2eq"): |
|
val = val.to("gCO2eq") |
|
return val |
|
|
|
|
|
def format_adpe(adpe: ADPe) -> Quantity: |
|
return q(adpe.value, adpe.unit) |
|
|
|
|
|
def format_pe(pe: PE) -> Quantity: |
|
val = q(pe.value, pe.unit) |
|
if val < q("1 MJ"): |
|
val = val.to("kJ") |
|
return val |
|
|
|
def format_impacts(impacts: Impacts) -> QImpacts: |
|
try: |
|
impacts.energy.value = (impacts.energy.value.max + impacts.energy.value.min)/2 |
|
impacts.gwp.value = (impacts.gwp.value.max + impacts.gwp.value.min)/2 |
|
impacts.adpe.value = (impacts.adpe.value.max + impacts.adpe.value.min)/2 |
|
impacts.pe.value = (impacts.pe.value.max + impacts.pe.value.min)/2 |
|
return QImpacts( |
|
energy=format_energy(impacts.energy), |
|
gwp=format_gwp(impacts.gwp), |
|
adpe=format_adpe(impacts.adpe), |
|
pe=format_pe(impacts.pe) |
|
) |
|
except: |
|
return QImpacts( |
|
energy=format_energy(impacts.energy), |
|
gwp=format_gwp(impacts.gwp), |
|
adpe=format_adpe(impacts.adpe), |
|
pe=format_pe(impacts.pe) |
|
) |
|
|
|
def format_impacts_expert(impacts: Impacts) -> QImpacts: |
|
return QImpacts( |
|
energy=format_energy(impacts.energy), |
|
gwp=format_gwp(impacts.gwp), |
|
adpe=format_adpe(impacts.adpe), |
|
pe=format_pe(impacts.pe) |
|
|
|
), impacts.usage, impacts.embodied |
|
|
|
|
|
def format_energy_eq_physical_activity(energy: Quantity) -> tuple[PhysicalActivity, Quantity]: |
|
energy = energy.to("kJ") |
|
running_eq = energy / RUNNING_ENERGY_EQ |
|
if running_eq > q("1 km"): |
|
return PhysicalActivity.RUNNING, running_eq |
|
|
|
walking_eq = energy / WALKING_ENERGY_EQ |
|
if walking_eq < q("1 km"): |
|
walking_eq = walking_eq.to("meter") |
|
return PhysicalActivity.WALKING, walking_eq |
|
|
|
|
|
def format_energy_eq_electric_vehicle(energy: Quantity) -> Quantity: |
|
energy = energy.to("kWh") |
|
ev_eq = energy / EV_ENERGY_EQ |
|
if ev_eq < q("1 km"): |
|
ev_eq = ev_eq.to("meter") |
|
return ev_eq |
|
|
|
|
|
def format_gwp_eq_streaming(gwp: Quantity) -> Quantity: |
|
gwp = gwp.to("kgCO2eq") |
|
streaming_eq = gwp * STREAMING_GWP_EQ |
|
if streaming_eq < q("1 h"): |
|
streaming_eq = streaming_eq.to("min") |
|
if streaming_eq < q("1 min"): |
|
streaming_eq = streaming_eq.to("s") |
|
return streaming_eq |
|
|
|
|
|
def format_energy_eq_electricity_production(energy: Quantity) -> tuple[EnergyProduction, Quantity]: |
|
electricity_eq = energy * ONE_PERCENT_WORLD_POPULATION * DAYS_IN_YEAR |
|
electricity_eq = electricity_eq.to("TWh") |
|
if electricity_eq > YEARLY_NUCLEAR_ENERGY_EQ: |
|
return EnergyProduction.NUCLEAR, electricity_eq / YEARLY_NUCLEAR_ENERGY_EQ |
|
electricity_eq = electricity_eq.to("GWh") |
|
return EnergyProduction.WIND, electricity_eq / YEARLY_WIND_ENERGY_EQ |
|
|
|
|
|
def format_energy_eq_electricity_consumption_ireland(energy: Quantity) -> Quantity: |
|
electricity_eq = energy * ONE_PERCENT_WORLD_POPULATION * DAYS_IN_YEAR |
|
electricity_eq = electricity_eq.to("TWh") |
|
return electricity_eq / YEARLY_IRELAND_ELECTRICITY_CONSUMPTION |
|
|
|
|
|
def format_gwp_eq_airplane_paris_nyc(gwp: Quantity) -> Quantity: |
|
gwp_eq = gwp * ONE_PERCENT_WORLD_POPULATION * DAYS_IN_YEAR |
|
gwp_eq = gwp_eq.to("kgCO2eq") |
|
return gwp_eq / AIRPLANE_PARIS_NYC_GWP_EQ |
|
|