Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion codecarbon/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "3.1.0"
__version__ = "3.1.1"
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,37 @@
from codecarbon.core.units import EmissionsPerKWh, Energy
from codecarbon.external.geography import GeoMetadata

URL: str = "https://api.co2signal.com/v1/latest"
CO2_SIGNAL_API_TIMEOUT: int = 30
URL: str = "https://api.electricitymaps.com/v3/carbon-intensity/latest"
ELECTRICITYMAPS_API_TIMEOUT: int = 30


def get_emissions(
energy: Energy, geo: GeoMetadata, co2_signal_api_token: str = ""
energy: Energy, geo: GeoMetadata, electricitymaps_api_token: str = ""
) -> float:
"""
Calculate the CO2 emissions based on energy consumption and geographic location.

This function retrieves the carbon intensity (in grams of CO2 per kWh) from the CO2
Signal API based on the geographic location provided. It then calculates the total
CO2 emissions for a given amount of energy consumption.
This function retrieves the carbon intensity (in grams of CO2 per kWh) from the
Electricity Maps API (formerly CO2 Signal) based on the geographic location provided.
It then calculates the total CO2 emissions for a given amount of energy consumption.

Args:
energy (Energy):
An object representing the energy consumption in kilowatt-hours (kWh).
geo (GeoMetadata):
Geographic metadata, including either latitude/longitude
or a country code.
co2_signal_api_token (str, optional):
The API token for authenticating with the CO2 Signal API (default is an empty string).
electricitymaps_api_token (str, optional):
The API token for authenticating with the Electricity Maps API (default is an empty string).

Returns:
float:
The total CO2 emissions in kilograms based on the provided energy consumption and
carbon intensity of the specified geographic location.

Raises:
CO2SignalAPIError:
If the CO2 Signal API request fails or returns an error.
ElectricityMapsAPIError:
If the Electricity Maps API request fails or returns an error.
"""
params: Dict[str, Any]
if geo.latitude:
Expand All @@ -45,18 +45,25 @@ def get_emissions(
resp = requests.get(
URL,
params=params,
headers={"auth-token": co2_signal_api_token},
timeout=CO2_SIGNAL_API_TIMEOUT,
headers={"auth-token": electricitymaps_api_token},
timeout=ELECTRICITYMAPS_API_TIMEOUT,
)
if resp.status_code != 200:
message = resp.json().get("error") or resp.json().get("message")
raise CO2SignalAPIError(message)
carbon_intensity_g_per_kWh = resp.json()["data"]["carbonIntensity"]
raise ElectricityMapsAPIError(message)

# API v3 response structure: carbonIntensity is at the root level
response_data = resp.json()
carbon_intensity_g_per_kWh = response_data.get("carbonIntensity")

if carbon_intensity_g_per_kWh is None:
raise ElectricityMapsAPIError("No carbonIntensity data in response")

emissions_per_kWh: EmissionsPerKWh = EmissionsPerKWh.from_g_per_kWh(
carbon_intensity_g_per_kWh
)
return emissions_per_kWh.kgs_per_kWh * energy.kWh


class CO2SignalAPIError(Exception):
class ElectricityMapsAPIError(Exception):
pass
34 changes: 28 additions & 6 deletions codecarbon/core/emissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

import pandas as pd

from codecarbon.core import co2_signal
from codecarbon.core import electricitymaps_api
from codecarbon.core.units import EmissionsPerKWh, Energy
from codecarbon.external.geography import CloudMetadata, GeoMetadata
from codecarbon.external.logger import logger
Expand All @@ -19,10 +19,25 @@

class Emissions:
def __init__(
self, data_source: DataSource, co2_signal_api_token: Optional[str] = None
self,
data_source: DataSource,
electricitymaps_api_token: Optional[str] = None,
co2_signal_api_token: Optional[
str
] = None, # Deprecated, for backward compatibility
):
self._data_source = data_source
self._co2_signal_api_token = co2_signal_api_token

# Handle backward compatibility
if co2_signal_api_token is not None:
logger.warning(
"Parameter 'co2_signal_api_token' is deprecated and will be removed in a future version. "
"Please use 'electricitymaps_api_token' instead."
)
if electricitymaps_api_token is None:
electricitymaps_api_token = co2_signal_api_token

self._electricitymaps_api_token = electricitymaps_api_token

def get_cloud_emissions(
self, energy: Energy, cloud: CloudMetadata, geo: GeoMetadata = None
Expand Down Expand Up @@ -123,12 +138,19 @@ def get_private_infra_emissions(self, energy: Energy, geo: GeoMetadata) -> float
:param geo: Country and region metadata
:return: CO2 emissions in kg
"""
if self._co2_signal_api_token:
if self._electricitymaps_api_token:
try:
return co2_signal.get_emissions(energy, geo, self._co2_signal_api_token)
emissions = electricitymaps_api.get_emissions(
energy, geo, self._electricitymaps_api_token
)
logger.debug(
"electricitymaps_api.get_emissions: "
+ f"Retrieved emissions for {geo.country_name} using Electricity Maps API :{emissions * 1000} g CO2eq"
)
return emissions
except Exception as e:
logger.error(
"co2_signal.get_emissions: "
"electricitymaps_api.get_emissions: "
+ str(e)
+ " >>> Using CodeCarbon's data."
)
Expand Down
67 changes: 55 additions & 12 deletions codecarbon/emissions_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,10 @@ def __init__(
emissions_endpoint: Optional[str] = _sentinel,
experiment_id: Optional[str] = _sentinel,
experiment_name: Optional[str] = _sentinel,
co2_signal_api_token: Optional[str] = _sentinel,
electricitymaps_api_token: Optional[str] = _sentinel,
co2_signal_api_token: Optional[
str
] = _sentinel, # Deprecated, use electricitymaps_api_token
tracking_mode: Optional[str] = _sentinel,
log_level: Optional[Union[int, str]] = _sentinel,
on_csv_write: Optional[str] = _sentinel,
Expand Down Expand Up @@ -221,8 +224,9 @@ def __init__(
data.
:param experiment_id: Id of the experiment.
:param experiment_name: Label of the experiment
:param co2_signal_api_token: API token for co2signal.com (requires sign-up for
free beta)
:param electricitymaps_api_token: API token for electricitymaps.com (formerly co2signal.com)
:param co2_signal_api_token: [DEPRECATED] Use electricitymaps_api_token instead.
Old parameter name for backward compatibility.
:param tracking_mode: One of "process" or "machine" in order to measure the
power consumption due to the entire machine or to try and
isolate the tracked processe's in isolation.
Expand Down Expand Up @@ -268,7 +272,31 @@ def __init__(
self._set_from_conf(api_call_interval, "api_call_interval", 8, int)
self._set_from_conf(api_endpoint, "api_endpoint", "https://api.codecarbon.io")
self._set_from_conf(api_key, "api_key", "api_key")
self._set_from_conf(co2_signal_api_token, "co2_signal_api_token")

# Handle backward compatibility for co2_signal_api_token
if co2_signal_api_token is not _sentinel:
logger.warning(
"Parameter 'co2_signal_api_token' is deprecated and will be removed in a future version. "
"Please use 'electricitymaps_api_token' instead."
)
if electricitymaps_api_token is _sentinel:
electricitymaps_api_token = co2_signal_api_token

self._set_from_conf(electricitymaps_api_token, "electricitymaps_api_token")
# Also check for old config name for backward compatibility
if (
not hasattr(self, "_electricitymaps_api_token")
or self._electricitymaps_api_token is None
):
self._set_from_conf(_sentinel, "co2_signal_api_token", prevent_setter=True)
old_token = self._external_conf.get("co2_signal_api_token")
if old_token:
logger.warning(
"Configuration parameter 'co2_signal_api_token' is deprecated. "
"Please update your config to use 'electricitymaps_api_token' instead."
)
self._electricitymaps_api_token = old_token

self._set_from_conf(emissions_endpoint, "emissions_endpoint")
self._set_from_conf(experiment_name, "experiment_name", "base")
self._set_from_conf(gpu_ids, "gpu_ids")
Expand Down Expand Up @@ -378,7 +406,7 @@ def __init__(
self._conf["provider"] = cloud.provider

self._emissions: Emissions = Emissions(
self._data_source, self._co2_signal_api_token
self._data_source, self._electricitymaps_api_token
)
self._init_output_methods(api_key=self._api_key)

Expand Down Expand Up @@ -956,7 +984,7 @@ def __init__(
See https://github.com/mlco2/codecarbon/
blob/master/codecarbon/data/cloud/impact.csv
for a list of cloud regions.
:param country_2letter_iso_code: For use with the CO2Signal emissions API.
:param country_2letter_iso_code: For use with the Electricity Maps emissions API.
See http://api.electricitymap.org/v3/zones for
a list of codes and their corresponding
locations.
Expand Down Expand Up @@ -1095,7 +1123,10 @@ def track_emissions(
emissions_endpoint: Optional[str] = _sentinel,
experiment_id: Optional[str] = _sentinel,
experiment_name: Optional[str] = _sentinel,
co2_signal_api_token: Optional[str] = _sentinel,
electricitymaps_api_token: Optional[str] = _sentinel,
co2_signal_api_token: Optional[
str
] = _sentinel, # Deprecated, use electricitymaps_api_token
tracking_mode: Optional[str] = _sentinel,
log_level: Optional[Union[int, str]] = _sentinel,
on_csv_write: Optional[str] = _sentinel,
Expand Down Expand Up @@ -1150,8 +1181,9 @@ def track_emissions(
data.
:param experiment_id: Id of the experiment.
:param experiment_name: Label of the experiment
:param co2_signal_api_token: API token for co2signal.com (requires sign-up for
free beta)
:param electricitymaps_api_token: API token for electricitymaps.com (formerly co2signal.com)
:param co2_signal_api_token: [DEPRECATED] Use electricitymaps_api_token instead.
Old parameter name for backward compatibility.
:param tracking_mode: One of "process" or "machine" in order to measure the
power consumption due to the entire machine or to try and
isolate the tracked processe's in isolation.
Expand Down Expand Up @@ -1180,7 +1212,7 @@ def track_emissions(
See https://github.com/mlco2/codecarbon/
blob/master/codecarbon/data/cloud/impact.csv
for a list of cloud regions.
:param country_2letter_iso_code: For use with the CO2Signal emissions API.
:param country_2letter_iso_code: For use with the Electricity Maps emissions API.
See http://api.electricitymap.org/v3/zones for
a list of codes and their corresponding
locations.
Expand All @@ -1199,6 +1231,17 @@ def _decorate(fn: Callable):
@wraps(fn)
def wrapped_fn(*args, **kwargs):
fn_result = None

# Handle backward compatibility for co2_signal_api_token
_electricitymaps_token = electricitymaps_api_token
if co2_signal_api_token is not _sentinel:
logger.warning(
"Parameter 'co2_signal_api_token' is deprecated and will be removed in a future version. "
"Please use 'electricitymaps_api_token' instead."
)
if electricitymaps_api_token is _sentinel:
_electricitymaps_token = co2_signal_api_token

if offline and offline is not _sentinel:
if (country_iso_code is None or country_iso_code is _sentinel) and (
cloud_provider is None or cloud_provider is _sentinel
Expand All @@ -1217,7 +1260,7 @@ def wrapped_fn(*args, **kwargs):
prometheus_url=prometheus_url,
output_handlers=output_handlers,
gpu_ids=gpu_ids,
co2_signal_api_token=co2_signal_api_token,
electricitymaps_api_token=_electricitymaps_token,
tracking_mode=tracking_mode,
log_level=log_level,
on_csv_write=on_csv_write,
Expand Down Expand Up @@ -1256,7 +1299,7 @@ def wrapped_fn(*args, **kwargs):
emissions_endpoint=emissions_endpoint,
experiment_id=experiment_id,
experiment_name=experiment_name,
co2_signal_api_token=co2_signal_api_token,
electricitymaps_api_token=_electricitymaps_token,
tracking_mode=tracking_mode,
log_level=log_level,
on_csv_write=on_csv_write,
Expand Down
2 changes: 1 addition & 1 deletion docs/.buildinfo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file records the configuration used when building these files. When it is not found, a full rebuild will be done.
config: 5444747ce17d7942890303a4e6aa98ce
config: 1179cfac2a69f75fdb97976cfa9a706e
tags: 645f666f9bcd5a90fca523b33c5a78b7
4 changes: 2 additions & 2 deletions docs/_sources/parameters.rst.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ Input Parameters
* - log_level
- | Global codecarbon log level (by order of verbosity): "debug", "info" (default),
| "warning", "error", or "critical"
* - co2_signal_api_token
- | API token for co2signal.com (requires sign-up for free beta)
* - electricitymaps_api_token
- | API token for electricitymaps.com (formerly co2signal.com)
* - pue
- | PUE (Power Usage Effectiveness) of the data center
| where the experiment is being run.
Expand Down
6 changes: 3 additions & 3 deletions docs/_sources/usage.rst.txt
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ For instance:
[codecarbon]
save_to_file = true
output_dir = /Users/victor/emissions
co2_signal_api_token=script-overwrite
electricitymaps_api_token=script-overwrite
experiment_id = 235b1da5-aaaa-aaaa-aaaa-893681599d2c
log_level = DEBUG
tracking_mode = process
Expand All @@ -235,7 +235,7 @@ For instance:
EmissionsTracker(
api_call_interval=4,
save_to_api=True,
co2_signal_api_token="some-token")
electricitymaps_api_token="some-token")

Yields attributes:

Expand All @@ -251,7 +251,7 @@ Yields attributes:
"tracking_mode": "process", # from ./.codecarbon.config
"emissions_endpoint": "localhost:7777", # from ~/.codecarbon.config
"output_dir": "/Users/victor/emissions", # from ./.codecarbon.config
"co2_signal_api_token": "some-token", # from script (override ./.codecarbon.config)
"electricitymaps_api_token": "some-token", # from script (override ./.codecarbon.config)
"gpu_ids": [0, 1], # from environment variable
}

Expand Down
2 changes: 1 addition & 1 deletion docs/_static/documentation_options.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const DOCUMENTATION_OPTIONS = {
VERSION: '3.1.0',
VERSION: '3.1.1',
LANGUAGE: 'en',
COLLAPSE_INDEX: false,
BUILDER: 'html',
Expand Down
4 changes: 2 additions & 2 deletions docs/advanced_installation.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Advanced Installation &mdash; CodeCarbon 3.1.0 documentation</title>
<title>Advanced Installation &mdash; CodeCarbon 3.1.1 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=03e43079" />
<link rel="stylesheet" type="text/css" href="_static/css/theme.css?v=e59714d7" />


<script src="_static/jquery.js?v=5d32c60e"></script>
<script src="_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
<script src="_static/documentation_options.js?v=dd1205ac"></script>
<script src="_static/documentation_options.js?v=796a81b5"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/js/theme.js"></script>
Expand Down
4 changes: 2 additions & 2 deletions docs/api.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CodeCarbon API &mdash; CodeCarbon 3.1.0 documentation</title>
<title>CodeCarbon API &mdash; CodeCarbon 3.1.1 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=03e43079" />
<link rel="stylesheet" type="text/css" href="_static/css/theme.css?v=e59714d7" />


<script src="_static/jquery.js?v=5d32c60e"></script>
<script src="_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
<script src="_static/documentation_options.js?v=dd1205ac"></script>
<script src="_static/documentation_options.js?v=796a81b5"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/js/theme.js"></script>
Expand Down
4 changes: 2 additions & 2 deletions docs/comet.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Comet Integration &mdash; CodeCarbon 3.1.0 documentation</title>
<title>Comet Integration &mdash; CodeCarbon 3.1.1 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=03e43079" />
<link rel="stylesheet" type="text/css" href="_static/css/theme.css?v=e59714d7" />


<script src="_static/jquery.js?v=5d32c60e"></script>
<script src="_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
<script src="_static/documentation_options.js?v=dd1205ac"></script>
<script src="_static/documentation_options.js?v=796a81b5"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/js/theme.js"></script>
Expand Down
2 changes: 1 addition & 1 deletion docs/edit/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

# The full version, including alpha/beta/rc tags

release = "3.1.0"
release = "3.1.1"

# -- General configuration ---------------------------------------------------

Expand Down
Loading
Loading