Exemplo n.º 1
0
    def _energy_mix_to_emissions_rate(energy_mix: Dict) -> EmissionsPerKwh:
        """
        Convert a mix of energy sources into emissions per kWh
        https://github.com/responsibleproblemsolving/energy-usage#calculating-co2-emissions
        :param energy_mix: A dictionary that breaks down the energy produced into sources, with a total value.
            Format will vary, but must have keys for "coal", "petroleum" and "naturalGas" and "total"
        :return: an EmissionsPerKwh object representing the average emissions rate
        """
        # source: https://github.com/responsibleproblemsolving/energy-usage#conversion-to-co2
        emissions_by_source: Dict[str, EmissionsPerKwh] = {
            "coal": EmissionsPerKwh.from_kgs_per_kwh(0.995725971),
            "petroleum": EmissionsPerKwh.from_kgs_per_kwh(0.8166885263),
            "naturalGas": EmissionsPerKwh.from_kgs_per_kwh(0.7438415916),
        }

        emissions_percentage: Dict[str, float] = {}
        for energy_type in energy_mix.keys():
            if energy_type not in ["total", "isoCode", "countryName"]:
                emissions_percentage[energy_type] = (energy_mix[energy_type] /
                                                     energy_mix["total"])

        #  Weighted sum of emissions by % of contributions
        # `emissions_percentage`: coal: 0.5, petroleum: 0.25, naturalGas: 0.25
        # `emission_value`: coal: 0.995725971, petroleum: 0.8166885263, naturalGas: 0.7438415916
        # `emissions_per_kwh`: (0.5 * 0.995725971) + (0.25 * 0.8166885263) * (0.25 * 0.7438415916)
        #  >> 0.5358309 kg/kwh

        emissions_per_kwh = EmissionsPerKwh.from_kgs_per_kwh(
            sum([
                emissions_percentage[source] *
                value.kgs_per_kwh  # % (0.x)  # kgs / kwh
                for source, value in emissions_by_source.items()
            ]))

        return emissions_per_kwh
Exemplo n.º 2
0
    def get_region_emissions(self, energy: Energy, geo: GeoMetadata) -> float:
        """
        Computes emissions for a region on private infra.
        Given an quantity of power consumed, use regional data
         on emissions per unit power consumed or the mix of energy sources.
        https://github.com/responsibleproblemsolving/energy-usage#calculating-co2-emissions
        :param energy: Mean power consumption of the process (kWh)
        :param geo: Country and region metadata.
        :return: CO2 emissions in kg
        """
        try:
            country_emissions_data = self._data_source.get_country_emissions_data(
                geo.country_iso_code.lower()
            )

            if geo.region not in country_emissions_data:
                # TODO: Deal with missing data, default to something
                raise ValueError(
                    f"Region: {geo.region} not found for Country with ISO CODE : {geo.country_iso_code}"
                )

            emissions_per_kwh: EmissionsPerKwh = EmissionsPerKwh.from_lbs_per_mwh(
                country_emissions_data[geo.region]["emissions"]
            )
        except DataSourceException:  # This country has regional data at the energy mix level, not the emissions level
            country_energy_mix_data = self._data_source.get_country_energy_mix_data(
                geo.country_iso_code.lower()
            )
            region_energy_mix_data = country_energy_mix_data[geo.region]
            emissions_per_kwh: EmissionsPerKwh = self._energy_mix_to_emissions_rate(
                region_energy_mix_data
            )

        return emissions_per_kwh.kgs_per_kwh * energy.kwh  # kgs
Exemplo n.º 3
0
    def get_country_emissions(self, energy: Energy, geo: GeoMetadata) -> float:
        """
        Computes emissions for a country on private infra,
        given emissions per unit power consumed at a country level
        https://github.com/responsibleproblemsolving/energy-usage#calculating-co2-emissions
        :param energy: Mean power consumption of the process (kWh)
        :param geo: Country and region metadata
        :return: CO2 emissions in kg
        """

        # source: https://github.com/responsibleproblemsolving/energy-usage#conversion-to-co2
        emissions_by_source: Dict[str, EmissionsPerKwh] = {
            "coal": EmissionsPerKwh.from_kgs_per_kwh(0.995725971),
            "petroleum": EmissionsPerKwh.from_kgs_per_kwh(0.8166885263),
            "naturalGas": EmissionsPerKwh.from_kgs_per_kwh(0.7438415916),
        }

        energy_mix = self._data_source.get_global_energy_mix_data()

        if geo.country_iso_code not in energy_mix:
            # TODO: Deal with missing data, default to something
            raise Exception()

        country_energy_mix: Dict = energy_mix[geo.country_iso_code]

        emissions_percentage: Dict[str, float] = {}
        for energy_type in country_energy_mix.keys():
            if energy_type not in ["total", "isoCode", "countryName"]:
                emissions_percentage[energy_type] = (
                    country_energy_mix[energy_type] /
                    country_energy_mix["total"])

        #  Weighted sum of emissions by % of contributions
        # `emissions_percentage`: coal: 0.5, petroleum: 0.25, naturalGas: 0.25
        # `emission_value`: coal: 0.995725971, petroleum: 0.8166885263, naturalGas: 0.7438415916
        # `emissions_per_kwh`: (0.5 * 0.995725971) + (0.25 * 0.8166885263) * (0.25 * 0.7438415916)
        #  >> 0.5358309 kg/kwh
        emissions_per_kwh = EmissionsPerKwh.from_kgs_per_kwh(
            sum([
                emissions_percentage[source] *
                value.kgs_per_kwh  # % (0.x)  # kgs / kwh
                for source, value in emissions_by_source.items()
            ]))

        return emissions_per_kwh.kgs_per_kwh * energy.kwh  # kgs
Exemplo n.º 4
0
    def get_cloud_emissions(self, energy: Energy,
                            cloud: CloudMetadata) -> float:
        """
        Computes emissions for cloud infra
        :param energy: Mean power consumption of the process (kWh)
        :param cloud: Region of compute
        :return: CO2 emissions in kg
        """

        df: pd.DataFrame = self._data_source.get_cloud_emissions_data()

        emissions_per_kwh: EmissionsPerKwh = EmissionsPerKwh.from_g_per_kwh(
            df.loc[(df["provider"] == cloud.provider)
                   & (df["region"] == cloud.region)]["impact"].item())

        return emissions_per_kwh.kgs_per_kwh * energy.kwh  # kgs
Exemplo n.º 5
0
def get_emissions(energy: Energy, geo: GeoMetadata, timeout=60):
    if geo.latitude:
        params = {"lat": geo.latitude, "lon": geo.longitude}
    else:
        params = {"countryCode": geo.country_2letter_iso_code}
    resp = requests.get(
        URL,
        params=params,
        headers={"auth-token": CO2_SIGNAL_API_TOKEN},
        timeout=timeout,
    )
    if resp.status_code != 200:
        raise CO2SignalAPIError(resp.json()["error"])
    carbon_intensity_g_per_kWh = resp.json()["data"]["carbonIntensity"]
    emissions_per_kwh: EmissionsPerKwh = EmissionsPerKwh.from_g_per_kwh(
        carbon_intensity_g_per_kWh
    )
    return emissions_per_kwh.kgs_per_kwh * energy.kwh
Exemplo n.º 6
0
    def get_cloud_emissions_barchart_data(
        self,
        net_energy_consumed: float,
        on_cloud: str,
        cloud_provider: str,
        cloud_region: str,
    ) -> Tuple[str, pd.DataFrame]:
        if on_cloud == "N":
            return (
                "",
                pd.DataFrame(data={
                    "region": [],
                    "emissions": [],
                    "countryName": []
                }),
            )
        cloud_emissions = self._data_source.get_cloud_emissions_data()
        cloud_emissions = cloud_emissions[[
            "provider", "providerName", "region", "impact", "countryName"
        ]]

        from codecarbon.core.units import EmissionsPerKwh

        cloud_emissions["emissions"] = cloud_emissions.apply(
            lambda row: EmissionsPerKwh.from_g_per_kwh(row.impact).kgs_per_kwh
            * net_energy_consumed,
            axis=1,
        )

        cloud_emissions_project_region = cloud_emissions[cloud_emissions.region
                                                         == cloud_region]
        cloud_emissions = cloud_emissions[
            (cloud_emissions.provider == cloud_provider)
            & (cloud_emissions.region != cloud_region)].sort_values(
                by="emissions")

        return (
            cloud_emissions_project_region.iloc[0, :].providerName,
            pd.concat([cloud_emissions_project_region, cloud_emissions]),
        )
Exemplo n.º 7
0
    def get_region_emissions(self, energy: Energy, geo: GeoMetadata) -> float:
        """
        Computes emissions for a country on private infra,
        given emissions per unit power consumed at a regional level
        https://github.com/responsibleproblemsolving/energy-usage#calculating-co2-emissions
        :param energy: Mean power consumption of the process (kWh)
        :param geo: Country and region metadata.
        :return: CO2 emissions in kg
        """

        country_emissions_data = self._data_source.get_country_emissions_data(
            geo.country_iso_code.lower())

        if geo.region not in country_emissions_data:
            # TODO: Deal with missing data, default to something
            raise Exception(
                f"Region: {geo.region} not found for Country with ISO CODE : {geo.country_iso_code}"
            )

        emissions_per_kwh: EmissionsPerKwh = EmissionsPerKwh.from_lbs_per_mwh(
            country_emissions_data[geo.region]["emissions"])

        return emissions_per_kwh.kgs_per_kwh * energy.kwh