A real-time visualisation of the Greenhouse Gas (in terms of CO2 equivalent) footprint of electricity consumption built with d3.js and mapbox GL, maintained by Tomorrow. Try it out at http://www.electricitymap.org, or download the app:
You can contribute in the following ways:
- Add a new region to the map, including contact information for energy agencies, governments, and transmission system operators.
- Correct data sources and capacities.
- Translate the map.
- Fix existing issues.
- Submit ideas, feature requests, or bugs as a new issue.
You can also find a list of missing data displayed as warnings in the developer console, or question marks in the country panel:
Check the contributing section for more details. Join us on Slack if you wish to discuss development or need help to get started.
How do you define real-time data? Real-time data is defined as a data source with an hourly (or better) frequency, delayed by less than 2hrs. It should provide a breakdown by generation type. Often fossil fuel generation (coal/gas/oil) is combined under a single heading like 'thermal' or 'conventional', this is not a problem.
Why do you calculate the carbon intensity of consumption? In short, citizens should not be responsible for the emissions associated with all the products they export, but only for what they consume. Consumption-based accounting (CBA) is a very important aspect of climate policy, and allows to assign responsibility to consumers instead of producers. Furthermore, this method is robust to governments relocating dirty production to neighbouring countries in order to green their image while still importing from it. We published our methodology here.
Why don't you show emissions per capita? A country that has few inhabitants but a lot of factories will appear high on CO2/capita. This means you can "trick" the numbers by moving your factory abroad and import the produced good instead of the electricity itself. That country now has a low CO2/capita number because we only count CO2 for electricity (not for imported/exported goods). The CO2/capita metric, by involving the size of the population, and by not integrating all CO2 emission sources, is thus an incomplete metric. CO2 intensity on the other hand only describes where is the best place to put that factory (and when it is best to use electricity), enabling proper decisions.
CO2 emission factors look high — what do they cover exactly? The carbon intensity of each type of power plant takes into account emissions arising from the whole life cycle of the plant (construction, fuel production, operational emissions, and decommissioning).
Is delayed data useful? While the map relies on having real-time data to work it's still useful to collect data from days/months past. This older data can be used to show past emissions and build up a better dataset. So if there's an hourly data source that lags several days behind you can still build a parser for it.
Can scheduled/assumed generation data be used? The electricityMap doesn't use scheduled generation data or make assumptions about unknown fuel mixes. This is to avoid introducing extra uncertainty into emissions calculations.
Can areas other than countries be shown? Yes providing there is a valid GeoJSON geometry (or another format that can be converted) for the area. As an example we already split several countries into states and grid regions.
How can I get access to historical data or the live API? All this and more can be found here.
The carbon intensity of each country is measured from the perspective of a consumer. It represents the greenhouse gas footprint of 1 kWh consumed inside a given country. The footprint is measured in gCO2eq (grams CO2 equivalent), meaning each greenhouse gas is converted to its CO2 equivalent in terms of global warming potential over 100 year (for instance, 1 gram of methane emitted has the same global warming impact during 100 years as ~34 grams of CO2 over the same period).
The carbon intensity of each type of power plant takes into account emissions arising from the whole life cycle of the plant (construction, fuel production, operational emissions, and decommissioning). Carbon-intensity factors used in the map are detailed in co2eq_parameters.json. These numbers come mostly from the following scientific peer reviewed literature: IPCC (2014) Fifth Assessment Report is used as reference in most instances (see a summary in the wikipedia entry)
Each country has a CO2 mass flow that depends on neighbouring countries. In order to determine the carbon footprint of each country, the set of coupled CO2 mass flow balance equations of each countries must be solved simultaneously. This is done by solving the linear system of equations defining the network of greenhouse gas exchanges. Take a look at this notebook for a deeper explanation. We also published our methodology here.
Real-time electricity data is obtained using parsers.
Click to see the full list of sources
- Åland: Kraftnät Åland
- Argentina: Cammesa
- Armenia: Armenian Energy Power System Operator
- Aruba: WEB Aruba (JSON)
- Australia: AREMI National Map (CSV)
- Australia (Western): AEMO (CSV)
- Australia (distributed solar generation): Australian PV Institute
- Australia (South Battery): Nemwatch
- Austria: ENTSOE
- Bahrain: GCCIA
- Bangladesh: PGCB
- Bosnia and Herzegovina: ENTSOE
- Bolivia: CNDC
- Belgium: ENTSOE
- Brazil: ONS
- Bulgaria: TSO
- Canada (Alberta): AESO
- Canada (New Brunswick): NB Power
- Canada (Nova Scotia): Nova Scotia Power
- Canada (Ontario): IESO
- Canada (Prince Edward Island): Government of PEI
- Canada (Yukon): Yukon Energy
- Chile (SING/SIC): Coordinador
- Czech Republic: ENTSOE
- Costa Rica: ICE
- Croatia (Exchanges): HOPS
- Cyprus: TSO
- Denmark: TSO
- Denmark (Bornholm): PowerlabDK
- Dominican Republic: OC
- El Salvador: Unidad de Transacciones
- Estonia: ENTSOE
- Faroe Islands: SEV
- Finland: ENTSOE
- France: RTE
- Germany: ENTSOE
- Georgia: GSE
- Great Britain: ENTSOE
- Great Britain (Orkney Islands): SSEN
- Greece: ENTSOE
- Guatemala: AMM
- Honduras: ENTE
- Hungary: ENTSOE
- Iceland: LANDSNET
- Ireland: ENTSOE
- Israel: IEC
- Italy: ENTSOE
- India: meritindia
- India (Andhra Pradesh): CORE Dashboard
- India (Chhattisgarh): cspc.co.in
- India (Delhi): delhisldc
- India (Gujarat): sldcguj
- India (Himachal Pradesh): HPSLDC
- India (Maharashtra) mahasldc
- India (Karnataka): kptclsldc.com
- India (Punjab): punjabsldc
- India (Uttar Pradesh): upsldc
- India (Uttarakhand): uksldc
- Iraq: Iraqi Power System
- Japan (Exchanges): OCCTO
- Japan (Chūbu): Chūden
- Japan (Chūgoku): Energia
- Japan (Hokkaidō): Hokuden
- Japan (Hokuriku): Rikuden
- Japan (Kansai): Kepco
- Japan (Kyūshū): Kyūden
- Japan (Kyūshū/Genkai NPP): Kyūden
- Japan (Kyūshū/Sendai NPP): Kyūden
- Japan (Shikoku): Yonden
- Japan (Tōhoku-Niigata): TH-EPCO
- Japan (Tōkyō area): TEPCO
- Kuwait (TSO): Ministry of Electricity & Water
- Kuwait (Power Market): GCCIA
- Latvia: ENTSOE
- Lithuania: ENTSOE
- Malaysia: GSO
- Moldova: MoldElectrica
- Montenegro: ENTSOE
- Namibia: NamPower
- Netherlands:
- New Zealand: Transpower
- Nicaragua: CNDC
- Northern Ireland: SONI
- Norway: ENTSOE
- Oman: GCCIA
- Panama: CND
- Peru: COES
- Poland: ENTSOE
- Portugal: ENTSOE
- Qatar: GCCIA
- Romania: ENTSOE
- Russia: SO-UPS
- Serbia: ENTSOE
- Singapore: EMC
- Singapore (Solar): EMA
- Slovakia: ENTSOE
- Slovenia: ENTSOE
- South Korea (Nuclear): KHNP
- South Korea (Hydro): KHNP
- South Korea (Load): KPX
- Spain: ENTSOE
- Spain (Canary Islands): REE
- Spain (Balearic Islands): REE
- Sweden: SVK
- Saudi Arabia: GCCIA
- Switzerland: ENTSOE
- Taiwan: TAIPOWER
- Turkey: ytbs
- Ukraine: UKRENERGO
- United Arab Emirates: GCCIA
- United States of America
- Bonneville Power Authority: BPA
- California: CAISO
- Hawaii (Oahu Island): Islandpulse
- Idaho Power Company: IPC
- MISO: MISO
- New England: NEISO
- New York: NYISO
- PJM: PJM
- Southwest Power Pool: SPP
- Southwest Variable Energy Resource Initiative: SVERI
- Texas: ERCOT
- Seminole Electric Cooperative (Florida): EIA, SEC
- Uruguay: UTE
Production capacities are centralized in the zones.json file. Values in the capacity
maps are in MW.
When determing the installed capacity for a country, these sources might help you get started. Note that if you end up using one of these sources, it also needs to be listed with the country/region.
- Renewables: IRENA
- Nuclear: IAEA PRIS
- Coal: Global Coal Plant Tracker
- Various:
For many European countries, data is available from ENTSO-E
Click to see the full list of sources
- Albania: IRENA
- Argentina: Cammesa
- Armenia
- Biomass, Hydro, Solar, Wind: IRENA
- Nuclear, Gas: wikipedia.org
- Aruba: WEB Aruba
- Australia OpenNEM
- Austria
- Wind: IGWindKraft
- Other: ENTSO-E
- Bahrain: IRENA
- Belarus: belstat.gov.by, RenEn
- Belgium
- Bolivia: CNDC
- Bosnia and Herzegovina: ENTSO-E
- Brazil: ONS
- Bulgaria: wikipedia.org
- Canada (British Columbia, Manitoba, New Brunswick, Newfoundland and Labrador, Nova Scotia, Prince Edward Island): wikipedia.org
- Canada (Ontario): IESO
- Canada (Québec): Hydro-Québec
- Canada (Saskatchewan): SaskPower
- Canada (Yukon)
- Hydro: YukonEnergy
- Chile (SIC)
- Geothermal, Hydro, Solar, Wind: SIC
- Other: energiaabierta.cl
- Chile (SING)
- Solar/Wind: SGER
- Other: energiaabierta.cl
- Croatia: HOPS
- Costa Rica: ICE
- Cyprus: TSO
- Czech Republic: ENTSO-E
- Denmark (DK1 and DK2): ENTSO-E
- Denmark (Bornholm)
- Wind: stateofgreen.com
- Dominican Republic:
- 2020 Data: OC
- Other: Climatescope
- El Salvador:
- Estonia:
- Faroe Islands: Johan Pauli Magnussen's Thesis, p44
- Finland
- France:
- Germany: Frauenhofer ISE
- Georgia: GSE
- Great Britain: ENTSO-E
- Greece: ENTSO-E
- Guatemala: AMM
- Honduras: ENEE
- Hungary
- Iceland
- Oil: Statistics Iceland
- Geothermal, Wind and Hydro: IRENA
- Ireland
- Israel: Global Power Plant Database
- Italy
- India: mercomindia
- India (Andhra Pradesh): wikipedia.org
- India (Punjab): PUNJABSLDC
- India (Chhattisgarh, Delhi, Gujarat, Karnataka, Punjab, Uttar Pradesh): National Power Portal
- Kuwait
- Latvia: ENTSO-E
- Lithuania: ENTSO-E
- Malaysia: GSO
- Moldova
- Montenegro
- Nagorno-Karabakh: Artsakh HEK
- Namibia
- Coal & Oil: NamPower
- Hydro, solar & wind: African Energy
- Nepal
-List of PowerStations:PowerStations
- GIS Map of Reservoir Projects: GIS_Reservoir
- Netherlands
- Nicaragua: Climatescope
- Norway
- Northern Ireland: ENTSO-E
- Oman: IRENA
- Panama: Secretaría de Energía de Panamá
- Peru: IRENA
- Poland
- Solar: PSE Twitter
- Biomass: URE
- Wind: URE
- Other: ENTSO-E
- Portugal
- Qatar: IRENA
- Romania:
- Nuclear: Nuclearelectrica
- Other: ENTSO-E
- Russia: Minenergo
- Serbia: ENTSO-E
- Singapore
- Solar: Energy Market Authority Statistics
- Other: Energy Market Authority
- Slovakia: SEPS
- Slovenia: ENTSO-E
- South Korea: KHNP
- Spain:
- Spain (Canary Islands)
- Hydro storage: goronadelviento.es
- Wind, Solar: REE
- Spain (Balearic Islands)
- Coal: wikipedia.org
- Wind, Solar: REE
- Sweden
- Renewables: IRENA
- Wind: Svensk Vindenergi
- Solar: Energimyndigheten
- Nuclear: Vattenfall
- Nuclear 2: OKG
- Coal: Stockholm Exergi
- Other: ENTSO-E
- Switzerland
- Taiwan: TAIPOWER
- Turkey:
- Ukraine: UKRENERGO
- United Arab Emirates: IRENA
- United States of America
- Federal: EIA
- States: EIA
- BPA: BPA
- CAISO
- CEC: CEC
- Renewables: CAISO
- Nuclear: wikipedia.org
- MISO: MISO
- NYISO: NYISO Gold Book
- PJM: PJM
- SPP: SPP
- Uruguay: UTE
Cross-border transmission capacities between the zones are centralized in the exchanges.json file. Values in the capacity
maps are in MW.
Click to see the full list of sources
- Åland ⇄ Sweden: "Sverigekabeln": 80 MW
- Åland ⇄ Finland: "Brändö-Gustafs": 9 MW
- Australia (Victoria) ⇄ Australia (Tasmania): "Basslink": 500 MW (regular) or 630 MW (temporarily)
- Denmark (West) ⇄ Norway: "Skaggerak": 1700 MW
- Denmark (East) ⇄ Denmark (West): "Storebælt HVDC": 600 MW
- Denmark (East) ⇄ Germany: "Kontek": 600 MW
- Denmark (West) ⇄ Sweden: "Konti-Skan": 650 MW
- Denmark (West) ⇄ Netherlands: "COBRAcable": 700 MW
- Estonia ⇄ European Russia And Ural 2464 MW
- Estonia ⇄ Finnland: "Estlink 1&2": 1000 MW
- Germany ⇄ Sweden: "Baltic Cable": 600 MW
- Germany ⇄ Norway: "NordLink": 1400MW
- Great Britain ⇄ Belgium: "Nemo Link": 1000 MW
- Great Britain ⇄ North Ireland: "Moyle": 500 MW
- Great Britain ⇄ Ireland: "East-West Interconnector": 500 MW
- Great Britain ⇄ France: "Cross-Channel": 2000 MW
- Great Britain ⇄ Netherlands: "BritNed": 1000 MW
- Greece ⇄ Italy: "GRITA": 500 MW
- Italy Central South ⇄ Italy Sardinia: "SAPEI": 1000 MW
- Japan-Chūbu ⇄ Japan-Tōkyō: 3x HVDC interconnectors between 60Hz/50Hz areas: 1200 MW
- Japan-Hokkaidō ⇄ Japan-Tōhoku: "HVDC Hokkaidō–Honshū": 900 MW
- Latvia ⇄ European Russia And Ural 696 MW
- Lithuania ⇄ Sweden: "NordBalt": 700 MW
- Lithuania ⇄ Poland: "LitPol Link": 500 MW
- Malta ⇄ Italy Sicily: "Malta–Sicily-Interconnector": 200 MW
- Montenegro ⇄ Italy Central South: "MONITA": 600MW
- Norway ⇄ Netherlands: "NorNed": 700 MW
- New Zealand (North Island) ⇄ New Zealand (South Island): "HVDC Inter-Island": 1200 MW
- Russia ⇉ Finland: "Vyborg HVDC scheme": 1400 MW + 2 AC-connections: 160 MW
- Spain ⇄ France: According to "The Spanish electricity system 2019" page 65: 2800 MW
- Spain ⇄ Spain (Balearic Islands): "Cometa": 400 MW
- Sweden ⇄ Poland: "SwePol": 600 MW
- Ukraine ⇄ Belarus, ⇄ Hungary, ⇉ Poland, ⇄ Moldova, ⇄ Slovakia, ⇄ Romania, ⇄ Russia: Ukrenergo
A ⇄ B: bidirectional operation, with power flow either "from A to B" or "from B to A"
A ⇉ B: unidirectional operation, only with power flow "from A to B"
We use the US National Weather Service's Global Forecast System (GFS)'s GFS 0.25 Degree Hourly data. Forecasts are made every 6 hours, with a 1 hour time step. The values extracted are wind speed and direction at 10m altitude, and ground solar irradiance (DSWRF - Downward Short-Wave Radiation Flux), which takes into account cloud coverage. In order to obtain an estimate of those values at current time, an interpolation is made between two forecasts (the one at the beginning of the hour, and the one at the end of the hour).
We use the Natural Earth Data Cultural Vectors country subdivisions (map admin subunits).
Want to help? First of all, thank you for your interest!
Join us on Slack at http://slack.tmrow.co to see what we are working on and to get in touch with other contributors. Also, if you get stuck, you can write a message in our channel #electricitymap.
For different ways to help improve electricityMap, have a look at the overview above. Here is how to get started:
Follow these steps to make your contribution:
- Fork the repository.
- Clone your fork of the repository.
- Download Docker.
- Set up and start your local environment (see steps below).
- Make your code changes and test them in your local environment.
- Push your changes to your fork.
- Submit a pull request to bring your contribution into the production version.
Note: to test parsers, go to testing parsers locally
-
First, you need to compile the frontend. Open a terminal in the root directory and run:
docker-compose build
-
Start the application by running:
docker-compose up
This will watch over source file changes, run nonstop and watch changes you make in the code to recompile the frontend if needed.
-
Go to http://localhost:8000/ and you should now see the map!
Notes:
- These steps only build with the English language (which will be faster as not all languages need to be built). To build all languages, change the
command
of theweb-watch-en
section of docker-compose.yml fromcommand: npm run watch-en
tocommand: npm run watch
. - The backend handles the calculation of carbon emissions. The map data displayed comes from a mock server providing dummy data from the state file.
See Troubleshooting below for common issues and fixes when building the map locally.
If you want to add new or change existing parsers you can use our public logger to see if your parser(s) can fetch data successfully. The logs show warnings and errors for all parsers.
If you want to update or add production capacities for a region, go to the zones file and make changes to the capacity
map. Values are in MW. The zones use ISO 3166-1 codes as identifiers.
As a first step, do a search for the region on our GitHub, as contributors may have explored things before. It is very simple to add a new country. The electricityMap backend runs a list of so-called parsers every 5 minutes. Those parsers are responsible for fetching the generation mix of a given country. See the existing list in the parsers directory, or review work in progress parsers).
Open a new issue for the relevant region and add the relevant individual or organization to contact. Please include email, Twitter and phone number for the contact where available.
This helps us and the community to contact them and make them aware of the electricityMap. Usually, energy agencies, governments, and transmission system operators are good potential sources. If you can't code, this is an amazing way to help us!
A parser is a python3 script that defines the method fetch_production
and returns the production mix at current time, in this format:
def fetch_production(zone_key='FR', session=None, target_datetime=None, logger=None):
return {
'zoneKey': 'FR',
'datetime': '2017-01-01T00:00:00Z',
'production': {
'biomass': 0.0,
'coal': 0.0,
'gas': 0.0,
'hydro': 0.0,
'nuclear': None,
'oil': 0.0,
'solar': 0.0,
'wind': 0.0,
'geothermal': 0.0,
'unknown': 0.0
},
'storage': {
'hydro': -10.0,
},
'source': 'mysource.com'
}
It contains the following objects:
session
: a python request session that you can re-use to make HTTP requests.target_datetime
: used to fetch historical data when available.logger
: alogging.Logger
whose output is publicly available for anyone to monitor correct functioning of the parsers.
The production values should never be negative. Use None
, or omit the key if a specific production mode is not known.
Storage values can be both positive (when storing energy) or negative (when the storage is emptied).
The parser can also return an array of objects if multiple time values can be fetched. The backend will automatically update past values properly.
Once you're done, add your parser to the zones.json and exchanges.json configuration files. Finally update the real-time sources.
Run all of the parser tests with the following command from the root directory:
python -m unittest discover parsers/test/
For more info, check out the example parser or browse existing parsers.
If your changes involve altering the way countries are displayed on the map, a new world.json will need to be generated. Make sure you're in the root directory then run the following command:
docker-compose run --rm web ./topogen.sh
Learn more about how the map is generated.
-
Make sure you have installed the required modules as described in parsers/requirements.txt, and are using python 3.6 (consider using a virtual environment for python). To confirm this, run:
pip install -r parsers/requirements.txt
-
From the root folder, use the
test_parser.py
command line utility:python test_parser.py FR price # get latest price parser for France python test_parser.py FR # defaults to production if no data type is given # test a specific datetime (parser needs to be able to fetch past datetimes) python test_parser.py DE --target_datetime 2018-01-01T08:00
Many of the tests require API keys of the data or web service providers, and therefore fail with an error message like
Exception: No ENTSOE_TOKEN found! Please add it into secrets.env!
In such cases, please browse the website related to the provider and ask for an API key. Once you get hold of the API key, make it an environment variable. This fixes the error.
We've added a testing server locally.
To add a new country to the map, run:
PYTHONPATH=. python mockserver/update_state.py <zone_name>
from the root directory, replacing <zone_name>
by the zone identifier of the parser you want to test. This fetches production, and assigns it a random carbon intensity value. It should appear on the map as you refresh your local browser.
-
ERROR: for X Cannot create container for service X: Invalid bind mount spec "<path>": Invalid volume specification: '<volume spec>'
. If you get this error after runningdocker-compose up
on Windows, you should telldocker-compose
to properly understand Windows paths by setting the environment variableCOMPOSE_CONVERT_WINDOWS_PATHS
to0
by runningsetx COMPOSE_CONVERT_WINDOWS_PATHS 0
. You will also need a recent version ofdocker-compose
. We have successfully seen this fix work with v1.13.0-rc4. More info here: docker/compose#4274. -
No website found at
http://localhost:8000
: This can happen if you're running Docker in a virtual machine. Find out docker's IP usingdocker-machine ip default
, and replacelocalhost
by your Docker IP when connecting.
-
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
. You can configure the memory allocation usingNODE_OPTIONS=--max-old-space-size=4096
in the "build-release" script in package.json, example:export NODE_OPTIONS=--max-old-space-size=4096 NODE_ENV=production && webpack --bail --mode production
. Also update the node version (last working version wasv12.16.3
). -
Expected linebreaks to be 'LF' but found 'CRLF': Configure your IDE to use LF instead of CRLF. If that doesn't fix it, add
"linebreak-style": 0
in "rules" in .estlintrc -
ERROR: for electricitymap-contrib_mockserver_1 Cannot start service mockserver: OCI runtime create failed: container_linux.go:345: starting container process caused "process_linux.go:424: container init caused \"rootfs_linux.go:58: mounting \\\".../server.py\\\" to rootfs \\\"/mnt/sda1/var/lib/docker/overlay2/.../merged\\\" at \\\".../server.py\\\" caused \\\"not a directory\\\"\"": unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type
.- Check that the project is cloned under C:/Users/
-
nodemon not restarting on file changes: try adding the
-L
parameter to use the legacy watch:"server-dev": "nodemon server.js -L"
. See https://www.npmjs.com/package/nodemon#application-isnt-restarting