download_era5_data.py is a Windows-oriented Python application for downloading and post-processing an ERA5 hourly time-series at one user-defined point. It is intended for engineering and metocean workflows that need a compact, repeatable CSV time series containing:
- significant wave height of combined wind waves and swell;
- mean wave period;
- mean wave direction;
- 10 m wind velocity components;
- computed 10 m wind speed;
- computed meteorological 10 m wind direction.
The program uses the Copernicus Climate Data Store dataset:
reanalysis-era5-single-levels-timeseries
This is the CDS ERA5 hourly time-series data on single levels from 1940 to present product, not the older regional GRIB-extraction workflow. The current script performs a single CDS API request for a point location and requests CSV output. It then reads the returned payload, normalises the returned tables, merges the wave and wind variables by timestamp, and writes two CSV files.
The script is GUI-first. When launched without command-line arguments it opens a Tkinter graphical interface. It also supports a simple command-line mode with explicit longitude, latitude and date range.
This README describes the current production script with these defining characteristics:
| Item | Current implementation |
|---|---|
| Main script | download_era5_data.py |
| Build file | download_era5_data.spec |
| CDS dataset | reanalysis-era5-single-levels-timeseries |
| CDS request style | One point request using location and a continuous date interval |
| CDS requested format | data_format = "csv" |
| GUI toolkit | Tkinter / ttk |
| Main table engine | pandas |
| Numerical engine | numpy |
| CDS client | cdsapi |
| CDS credential lookup | .ecmwfapirc and .cdsapirc; searched first in %USERPROFILE%, then in the script/executable directory |
| Optional Excel reader | openpyxl through pandas.read_excel |
| Required output files | era5_data.csv, output.csv, download_era5_data.log, defaults.json |
| Compiled executable mode | One-file Windows GUI executable built with PyInstaller and console=False |
The current script does not use:
- monthly GRIB files;
xarray;cfgrib;ecCodes;pygrib;- local GRIB archive extraction;
- inverse-distance interpolation in the script;
- multiprocessing extraction of GRIB files;
- a
grib/input folder; - a
results/output folder.
Those items belonged to an older design and are intentionally not part of the current dependency or usage model.
ERA5 is the fifth-generation ECMWF atmospheric reanalysis produced for the Copernicus Climate Change Service. Reanalysis combines a numerical weather prediction model with observations from many observing systems to produce a physically consistent reconstruction of past atmospheric, land-surface and ocean-wave conditions.
The core reanalysis principle is data assimilation: every assimilation cycle blends a previous model forecast with newly available observations, taking account of their uncertainties, to produce a new best estimate of the state of the Earth system. This analysed state is then used to initialise the next forecast cycle. Reanalysis applies this principle over a long historical period rather than only for operational forecasting.
For engineering use, ERA5 is valuable because it provides long, homogeneous and globally complete hourly data. It is particularly useful where buoy, anemometer or wave-rider records are short, discontinuous, or absent.
ERA5 is not a measurement record at the exact project coordinate. It is a model-data assimilation product. It assimilates observations, but the resulting values are gridded analyses generated by the ECMWF modelling and assimilation system. For maritime and coastal engineering, ERA5 is generally suitable for:
- screening long-term wave and wind climate;
- preparing offshore reference time series;
- selecting storm events for further modelling;
- supporting preliminary extreme-value analysis;
- generating boundary-condition candidates for nearshore wave transformation;
- contextualising shorter local measurements.
ERA5 should not be treated as a direct replacement for:
- local wave-buoy records;
- harbour agitation modelling;
- nearshore spectral wave transformation;
- site-specific bathymetric refraction and breaking analysis;
- physical model testing;
- final overtopping assessment at a breakwater crest or revetment without transformation to the structure toe.
Recent ERA5 data are initially released as ERA5T, a timely preliminary product. ERA5T is normally available with a latency of about 5 days. Final ERA5 replaces ERA5T later, typically after a delay of about two to three months. For formal engineering reports, it is therefore prudent to record:
- the date of data acquisition;
- the dataset name;
- the CDS request payload;
- the script used;
- whether the requested period included recent ERA5T data.
For bankable design, claims, litigation-sensitive work, or contractual deliverables, recent ERA5T periods should be treated with caution until final ERA5 has replaced them.
ERA5 includes an uncertainty estimate through an underlying reduced-resolution ensemble. The dataset used by this script is a selected time-series subset and this script does not request ensemble mean or spread. The generated CSV therefore contains deterministic hourly values only. It does not contain uncertainty envelopes, ensemble spread, or probabilistic quantiles.
The script requests:
DATASET_NAME = "reanalysis-era5-single-levels-timeseries"The CDS catalogue title is:
ERA5 hourly time-series data on single levels from 1940 to present
The CDS catalogue entry is organised around the usual Overview, Download and Documentation tabs. The Overview tab gives the dataset description, spatial and temporal metadata, licence and related resources. The Download tab is the interactive form that can be used to test the dataset and accept the licence before API use. The Documentation tab links to the Product User Guide and ERA5 technical documentation.
At the time this README was prepared, the catalogue entry identified the dataset as published on 2025-03-17 and updated on 2026-05-13. These dates are catalogue metadata and should not be treated as a substitute for the actual acquisition date recorded in download_era5_data.log.
The dataset is a regridded subset of the full ERA5 single-level product, stored and served for efficient long time-series retrieval at a single point. It is used by the ERA Explorer application to provide rapid interactive time-series responses.
The dataset is described by CDS as follows:
| Property | Description |
|---|---|
| Data type | Time-series |
| Projection | Regular latitude-longitude grid |
| Horizontal coverage | Global |
| Atmospheric horizontal resolution | 0.25° × 0.25° |
| Ocean-wave horizontal resolution | 0.5° × 0.5° |
| Temporal coverage | 1940 to present |
| Temporal resolution | Hourly |
| File formats | NetCDF and CSV |
| Update frequency | Daily |
| Licence | CC-BY |
The ERA5 time-series dataset is generated from ERA5 source GRIB data after applying homogenisation conventions. The processed data are stored in an Analysis Ready Cloud Optimised Zarr archive. CDS then serves point time-series requests from that archive and writes the result to NetCDF or CSV, depending on the request.
This architecture is different from downloading monthly GRIB tiles and decoding them locally. The current script deliberately uses this time-series product to avoid maintaining local GRIB decoding dependencies and to keep the operational workflow lighter.
For this CDS time-series product, the requested location is not interpolated by this script. If the requested longitude and latitude do not coincide exactly with the dataset grid, the CDS time-series service uses the nearest grid point.
This point matters because atmospheric variables and wave variables are on different spatial grids:
- atmospheric variables such as
10m_u_component_of_windand10m_v_component_of_windare on a 0.25° grid; - wave variables such as
mean_wave_direction,mean_wave_periodandsignificant_height_of_combined_wind_waves_and_swellare on a 0.5° grid.
Consequently, for a requested coastal or offshore point, the nearest atmospheric grid point and nearest wave grid point may not be identical. CDS may also return atmospheric and wave parameters in separate table files to avoid conflicts in coordinate definitions. The script is designed to handle that by reading all returned tables and merging them by datetime.
The current script requests exactly five ERA5 variables.
ERA5_VARIABLES = [
"10m_u_component_of_wind",
"10m_v_component_of_wind",
"mean_wave_direction",
"mean_wave_period",
"significant_height_of_combined_wind_waves_and_swell",
]| Short output name | CDS variable name | Unit | Meaning |
|---|---|---|---|
swh |
significant_height_of_combined_wind_waves_and_swell |
m | Significant height of combined wind waves and swell |
mwp |
mean_wave_period |
s | Mean wave period |
mwd |
mean_wave_direction |
degrees | Mean wave direction |
u10 |
10m_u_component_of_wind |
m/s | Eastward 10 m wind component; positive towards east |
v10 |
10m_v_component_of_wind |
m/s | Northward 10 m wind component; positive towards north |
The script does not request wind gust, 100 m wind, pressure, temperature, precipitation, swell partitions, wind-sea partitions, peak wave period, maximum wave height, wave spectra, or ensemble variables.
The script requests wind components and computes wind speed and meteorological wind direction locally. This avoids relying on a separate wind-speed/wind-direction parameter that may belong to the wave-model grid or have a different physical definition. The computed wind fields in output.csv are therefore derived from atmospheric 10 m wind vector components.
The current output uses mwp, the ERA5 mean wave period. It does not request pp1d, the peak wave period. This is an intentional distinction:
mwpis an integrated mean period quantity;pp1dis a peak-period quantity and is not part of the current CDS request.
Downstream design formulas that require peak period should not use mwp as if it were Tp without a justified conversion or a revised request including the appropriate period parameter.
For one run, the request dictionary is structurally equivalent to:
request = {
"variable": [
"10m_u_component_of_wind",
"10m_v_component_of_wind",
"mean_wave_direction",
"mean_wave_period",
"significant_height_of_combined_wind_waves_and_swell",
],
"location": {
"longitude": longitude,
"latitude": latitude,
},
"date": ["YYYY-MM-DD/YYYY-MM-DD"],
"data_format": "csv",
}The script then initialises the CDS client from the configured API-key file and executes the request:
client = initialize_cds_client()
result = client.retrieve(DATASET_NAME, request)
result.download(str(payload_path))The client initialisation is deliberately explicit. The script searches for a CDS API credential file before creating the cdsapi.Client, then passes the parsed url, key and optional verify value directly to the client. This avoids depending on a single fixed credential location.
The temporary payload is written to:
_era5_cds_download_payload.zip
The extension is .zip because CDS often returns a ZIP archive for mixed-grid time-series requests, but the script also supports a plain CSV response and an Office Open XML table response.
All files are written in the application directory.
In normal Python execution, the application directory is the directory containing download_era5_data.py.
In a PyInstaller one-file executable, the application directory is the directory containing download_era5_data.exe, not the temporary _MEI... extraction directory.
| File | Purpose |
|---|---|
defaults.json |
Last-used longitude, latitude, start date and end date |
download_era5_data.log |
Execution log for the latest run |
_era5_cds_download_payload.zip |
Temporary CDS payload, deleted after successful or failed processing where possible |
era5_data.csv |
Merged raw ERA5 table after normalisation to compact columns |
output.csv |
Final engineering table with computed wind speed and wind direction |
The intermediate merged CSV has fixed columns:
datetime,swh,mwp,mwd,u10,v10
| Column | Unit | Description |
|---|---|---|
datetime |
UTC-like timestamp string | Parsed ERA5 valid time, formatted as YYYY-MM-DD HH:MM:SS |
swh |
m | Significant height of combined wind waves and swell |
mwp |
s | Mean wave period |
mwd |
degrees | Mean wave direction |
u10 |
m/s | 10 m U wind component |
v10 |
m/s | 10 m V wind component |
The final processed CSV has fixed columns:
datetime,swh,mwp,mwd,wind,dwi,u10,v10
| Column | Unit | Description |
|---|---|---|
datetime |
UTC-like timestamp string | ERA5 valid time, formatted as YYYY-MM-DD HH:MM:SS |
swh |
m | Significant height of combined wind waves and swell |
mwp |
s | Mean wave period |
mwd |
degrees | Mean wave direction |
wind |
m/s | Computed 10 m wind speed from u10 and v10 |
dwi |
degrees | Computed meteorological wind direction, North = 0°, clockwise positive |
u10 |
m/s | 10 m U wind component |
v10 |
m/s | 10 m V wind component |
The final CSV is sorted by datetime, duplicate timestamps are dropped by keeping the first occurrence, and timestamps are formatted consistently.
The 10 m wind speed is computed from the horizontal components:
wind = sqrt(u10^2 + v10^2)
where:
u10is the eastward component;v10is the northward component;windis the scalar speed.
The script computes dwi as:
dwi = (180 + atan2(u10, v10) * 180 / pi) mod 360
This gives a meteorological direction in degrees:
- 0° means wind from north;
- 90° means wind from east;
- 180° means wind from south;
- 270° means wind from west;
- values are wrapped into the interval
[0, 360).
This is the conventional “direction from which the wind blows” representation. It differs from a mathematical vector direction “towards which the vector points”.
u10 |
v10 |
Wind vector points towards | Meteorological dwi |
|---|---|---|---|
| 0 | -10 | South | 0° |
| -10 | 0 | West | 90° |
| 0 | 10 | North | 180° |
| 10 | 0 | East | 270° |
Although the CDS request asks for CSV, the response can be one of several practical payload types. The script supports:
| Payload type | Handling |
|---|---|
| Plain text CSV | Decoded and parsed directly |
| ZIP archive containing CSV files | Each table member is read and merged |
| ZIP archive containing XLS/XLSX files | Each workbook/sheet is read through pandas.read_excel |
| Single Office Open XML table | Read as Excel if the payload starts with PK but is not a ZIP table archive |
The script rejects payloads that look like unsupported binary formats, including NetCDF/HDF-like content, because the current workflow is intentionally CSV/table based.
The CSV reader is intentionally defensive because CDS table payloads may include metadata lines before the real header. The parser:
- decodes bytes using fallback encodings;
- detects the real table header by searching for a row containing a recognised time field and at least one recognised ERA5 variable;
- detects the delimiter among comma, semicolon and tab;
- filters malformed or metadata lines;
- reads the cleaned text with
pandas.read_csv; - strips quotes and whitespace from column names.
The script maps long CDS variable names and shorter aliases to the compact internal schema.
| Internal column | Accepted source names |
|---|---|
datetime |
datetime, valid_time, time, timestamp, date |
swh |
significant_height_of_combined_wind_waves_and_swell, swh |
mwp |
mean_wave_period, mwp, pp1d |
mwd |
mean_wave_direction, mwd |
u10 |
10m_u_component_of_wind, u10 |
v10 |
10m_v_component_of_wind, v10 |
The pp1d alias is only a defensive legacy alias in the column-mapping stage. The current request does not request peak period.
The script can standardise both:
- wide tables, where variables are already columns;
- long tables, where a
variable/valuepair must be pivoted into columns.
This makes the post-processing robust to small differences in CDS table structure.
When CDS returns separate atmospheric and wave tables, the script:
- standardises each returned table;
- parses and sorts the
datetimefield; - converts recognised variable columns to numeric values;
- drops duplicate timestamps inside each table;
- sets
datetimeas the index; - combines tables using first non-empty values;
- writes one merged
era5_data.csv.
Missing variable columns are created as empty columns during the merge stage, but the final output.csv stage requires non-empty swh, mwp, mwd, u10 and v10. This prevents silently generating an incomplete engineering file.
Before the CDS download starts, the script checks whether the output files can be written. It tests:
- write access to the output directory;
- whether
era5_data.csvcan be opened for appending if it already exists; - whether
output.csvcan be opened for appending if it already exists.
If a CSV is open in Excel, LibreOffice, a text editor, Windows Preview Pane, or another process, the script stops before downloading data and gives a practical message asking the user to close the file.
CSV writing uses a temporary file followed by atomic replacement:
.era5_data.writing.csv -> era5_data.csv
.output.writing.csv -> output.csv
This avoids leaving partially written final outputs after a failed write.
The script stores GUI/CLI defaults in:
defaults.json
The hardcoded defaults are:
| Field | Default |
|---|---|
| Longitude | -9.58166667 |
| Latitude | 41.14833299 |
| Start date | 1940-01-01 |
| End date | current local date minus 5 days |
The minus-5-days default reflects the approximate ERA5 latency and reduces the likelihood of requesting data not yet available.
Dates must be entered as:
YYYY-MM-DD
The script validates that the start date is less than or equal to the end date.
Run without arguments:
python download_era5_data.pyor explicitly:
python download_era5_data.py --guiIn the compiled executable, double-click:
dist\download_era5_data.exe
The GUI contains three tabs:
| Tab | Purpose |
|---|---|
| Run | Enter coordinates and dates, start the workflow, view progress |
| Log | Read the execution log inside the GUI |
| Instructions | Read embedded usage and build notes |
The Run tab contains:
- longitude field;
- latitude field;
- start date field;
- end date field;
- Start button;
- Open Log tab button;
- Quit button;
- progress bar;
- progress text;
- estimated completion time text.
Longitude and latitude must be decimal degrees, with longitude first and latitude second.
The GUI uses fixed minimum dimensions and structured panels for the Run, Log and Instructions tabs. The current main dimensions are defined in the script through constants such as:
DEFAULT_WINDOW_WIDTH = 980
DEFAULT_WINDOW_HEIGHT = 700
DEFAULT_WINDOW_MIN_WIDTH = 940
DEFAULT_WINDOW_MIN_HEIGHT = 660The window is resizable, but the minimum dimensions are chosen so that the main controls remain visible without requiring scrolling during normal use.
The CDS request and processing pipeline run in a worker thread so that the Tkinter main loop remains responsive. Messages are sent back to the GUI through a queue and displayed as log, status and progress events.
The GUI log uses a TkTextWriter adapter exposing write() and flush(). This allows log-style writing into the Tkinter text widget and prevents failures from code paths expecting a file-like writer.
python download_era5_data.py --longitude -9.58166667 --latitude 41.14833299 --start-date 1940-01-01 --end-date 2026-05-08python download_era5_data.py ^
--longitude -9.58166667 ^
--latitude 41.14833299 ^
--start-date 1940-01-01 ^
--end-date 2026-05-08| Option | Meaning |
|---|---|
--gui |
Launch GUI mode explicitly |
--longitude |
Target longitude in decimal degrees |
--latitude |
Target latitude in decimal degrees |
--start-date |
Start date in YYYY-MM-DD format |
--end-date |
End date in YYYY-MM-DD format |
There is no --download, --extract, --data-dir, --results-dir, --output-csv, or --log-file option in the current script.
Use a current standard Windows Python installation from python.org. Tkinter is normally included with standard Windows Python distributions.
Run these commands in Windows cmd from the project folder:
python -m venv venv
venv\Scripts\activate
python -m pip install --upgrade pip
python -m pip install "cdsapi>=0.7.7" numpy pandas openpyxl pyinstallerThe quoted cdsapi>=0.7.7 requirement follows the current CDS recommendation to use the latest available CDS API client. pyinstaller is only needed when building the standalone Windows executable.
If the objective is only to install or update the CDS API client in an existing Python environment, run:
python -m pip install --upgrade "cdsapi>=0.7.7"On Unix/Linux or macOS, the equivalent command is:
python3 -m pip install --upgrade "cdsapi>=0.7.7"| Package | Required | Purpose |
|---|---|---|
cdsapi |
Yes | CDS API client used to submit and download CDS requests |
numpy |
Yes | Wind speed and direction calculations |
pandas |
Yes | CSV/Excel reading, time parsing, table merging and CSV writing |
openpyxl |
Conditional | Reading XLSX payload members if CDS returns Excel tables |
pyinstaller |
Build only | Creating the Windows standalone executable |
tkinter |
GUI mode | GUI; normally included with Windows Python |
Do not install these for the current script unless another tool in the repository needs them:
xarray cfgrib eccodes pygrib
They are not used by this script.
A configured CDS API account is required before download_era5_data.py can retrieve data from the Copernicus Climate Data Store.
Before running the script:
- Register for a Copernicus Climate Data Store account if you do not already have one.
- Log in to the CDS website.
- Open the ERA5 time-series dataset page used by this script.
- Accept the dataset Terms of Use / licence from the dataset download form.
- Open the CDS API setup page and copy the personal API credentials shown for your account.
The dataset Terms of Use must be accepted manually in the browser. Installing cdsapi and creating an API-key file is not sufficient if the dataset licence has not been accepted.
The script supports both of these credential file names:
.ecmwfapirc
.cdsapirc
On Windows, the official CDS API configuration location is normally the user profile folder:
%USERPROFILE%\.cdsapirc
For operational redundancy, the script also accepts .ecmwfapirc and searches the script/executable directory if no usable credential file is found in %USERPROFILE%.
The search order is fixed:
| Priority | Location searched |
|---|---|
| 1 | %USERPROFILE%\.ecmwfapirc |
| 2 | %USERPROFILE%\.cdsapirc |
| 3 | <script-or-exe-directory>\.ecmwfapirc |
| 4 | <script-or-exe-directory>\.cdsapirc |
In normal Python execution, <script-or-exe-directory> is the folder containing download_era5_data.py.
In the PyInstaller executable, <script-or-exe-directory> is the folder containing download_era5_data.exe. It is not the temporary _MEI... extraction folder.
This redundancy allows the program to run even when the user forgets to copy the API-key file to %USERPROFILE%, provided that a valid .ecmwfapirc or .cdsapirc file is placed beside the script or executable.
The usual CDS API two-line format is supported:
url: https://cds.climate.copernicus.eu/api
key: <PERSONAL-ACCESS-TOKEN>
Replace <PERSONAL-ACCESS-TOKEN> with the personal access token displayed in the logged-in CDS account. Do not include angle brackets in the real file.
The script also supports JSON-style ECMWF credential files with at least url and key fields, for example:
{
"url": "https://cds.climate.copernicus.eu/api",
"key": "<PERSONAL-ACCESS-TOKEN>"
}An optional verify entry is also read if present. It may be useful in controlled corporate environments with customised certificate verification settings.
To create the standard CDS credential file in the Windows user profile folder, run from Windows cmd:
notepad %USERPROFILE%\.cdsapircPaste the credentials and save the file.
To use the redundant local fallback instead, place either of these files in the same folder as download_era5_data.py or download_era5_data.exe:
.ecmwfapirc
.cdsapirc
The local fallback is useful when distributing the executable in a working folder or when the operator does not have the API-key file in %USERPROFILE%.
On Unix/Linux or macOS, the conventional CDS API credentials file is:
$HOME/.cdsapirc
Its contents should follow the same structure:
url: https://cds.climate.copernicus.eu/api
key: <PERSONAL-ACCESS-TOKEN>
The script is Windows-oriented, but the same credential-file parser can read .ecmwfapirc or .cdsapirc from the user home directory and from the script directory.
The CDS API client is a Python library and supports Python 3. Install it with pip:
python -m pip install --upgrade "cdsapi>=0.7.7"or, on Unix/Linux/macOS:
python3 -m pip install --upgrade "cdsapi>=0.7.7"For this project, the full dependency installation command is still:
python -m pip install "cdsapi>=0.7.7" numpy pandas openpyxl pyinstallerAfter creating .ecmwfapirc or .cdsapirc, check that Python can import the CDS API client:
python -c "import cdsapi; print('cdsapi import OK')"A successful import confirms that the package is installed. The first real download performed by the script confirms that the credential file, personal access token, CDS endpoint and dataset licence are all valid.
The .ecmwfapirc or .cdsapirc file contains a personal access token. Do not commit it to GitHub, send it by email, include it in screenshots, or package it with a public executable. Each operator should configure CDS credentials in their own user profile or keep a private copy beside the local script/executable.
Before building or distributing the tool, run:
python -m py_compile download_era5_data.pyThis confirms that the script is syntactically valid Python source.
Place these files in the same folder:
download_era5_data.py
download_era5_data.spec
Activate the virtual environment, then run:
python -m PyInstaller --clean --noconfirm download_era5_data.specThe executable is created at:
dist\download_era5_data.exe
The spec file controls how PyInstaller builds the executable. The current GUI executable must be built with:
console=Falseinside the EXE(...) block. This prevents the background command-prompt/MS-DOS window from appearing before the Tkinter GUI window.
The essential EXE(...) configuration is:
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='download_era5_data',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)When a PyInstaller executable is built with console=False, Windows may set sys.stdout, sys.stderr or sys.stdin to None. Some third-party libraries can still attempt to call .write(), .flush() or .isatty() on those streams.
The script therefore includes a startup compatibility function that redirects missing standard streams to os.devnull. This preserves silent GUI behaviour while avoiding errors such as:
'NoneType' object has no attribute 'write'
Double-click:
dist\download_era5_data.exe
The program should open only the graphical window, without a background console window.
In one-file PyInstaller mode, the script itself is extracted into a temporary _MEI... folder. The current script avoids writing outputs there. Instead, it writes all persistent files next to the executable:
folder-containing-exe\defaults.json
folder-containing-exe\download_era5_data.log
folder-containing-exe\era5_data.csv
folder-containing-exe\output.csv
A recommended production workflow is:
- Create and activate the Python virtual environment.
- Install dependencies.
- Configure CDS API credentials in
%USERPROFILE%or beside the script/executable, and accept the dataset licence. - Run
python -m py_compile download_era5_data.py. - Launch the GUI with
python download_era5_data.py. - Run a short date range first to verify CDS access and output format.
- Close any open CSV files before running a long extraction.
- Run the full target period.
- Check
download_era5_data.log. - Inspect
era5_data.csvandoutput.csv. - Archive the README, script, spec file, log file, output files and acquisition date.
For repeated use by non-Python operators:
- Build
download_era5_data.exeusing the spec file. - Place the EXE in a clean working folder.
- Double-click the EXE.
- Run from the GUI.
- Collect outputs from the same folder as the EXE.
Before using output.csv in design calculations, check:
Verify that the first and last timestamps match the requested date range. For a complete hourly record, most days should contain 24 samples.
Check non-empty counts for:
swh,mwp,mwd,u10,v10,wind,dwi
The script logs non-empty counts for the main variables. Any unexpected empty column should be investigated before use.
Confirm that the downstream tool expects:
- wave directions as ERA5 mean wave directions in degrees;
- wind directions as meteorological “from” directions;
- degrees clockwise from true north.
Do not mix “from” and “to” conventions.
For coastal points, remember that the wave grid is coarser than the atmospheric grid. A requested point near land, islands, breakwaters or complex bathymetry may be represented by a grid point that is not suitable for local nearshore design without transformation or validation.
Where buoy, weather-station, hindcast or measured data exist, compare at least:
- overlapping storm peaks;
- seasonal wave-height distribution;
- mean and extreme wind speed;
- directional sectors;
- missing-data periods;
- outliers and unrealistic values.
The script does not compute return periods, joint probability, persistence, storm duration, overtopping, wave transformation, extreme-value fits, or design sea states. Those analyses should be performed in a separate controlled workflow.
Cause: the executable was built as a console application.
Fix: compile with the spec file and make sure the spec contains console=False:
python -m PyInstaller --clean --noconfirm download_era5_data.specCause: a GUI executable built with console=False has no real standard output/error stream, and a third-party package attempted to write to it.
Fix: use the current script, which redirects missing standard streams to os.devnull at startup.
Cause: era5_data.csv or output.csv is open in another program.
Fix: close the file in Excel, LibreOffice, Notepad, Windows Preview Pane, or any program that may hold the file lock, then run again.
This is expected for mixed atmospheric and wave parameters. The script reads all supported CSV/XLS/XLSX members and merges them by timestamp.
The script stops before writing final output.csv if a required column is entirely empty. Check:
- CDS service status;
- requested location;
- requested date range;
- whether the selected location is valid for wave-model output;
- the log file;
- whether the returned payload changed structure.
Check that a valid .ecmwfapirc or .cdsapirc file exists in one of the supported locations:
%USERPROFILE%\.ecmwfapirc
%USERPROFILE%\.cdsapirc
<script-or-exe-directory>\.ecmwfapirc
<script-or-exe-directory>\.cdsapirc
The file must contain valid url and key entries. Also confirm that the dataset licence has been accepted in the CDS website. If CDS changes the API endpoint, update the url value according to the current instructions in the logged-in CDS account page.
The current script writes files beside the executable in compiled mode. Move the EXE to the folder where you want outputs to be created, then run it from there.
The processing runs in a background worker thread. For long date ranges, the CDS request itself may take time. Use the Log tab and download_era5_data.log to check progress.
This tool gives a compact point time-series. It does not perform:
- nearshore wave transformation;
- spectral wave modelling;
- tide/current coupling;
- bathymetric refraction;
- diffraction around port structures;
- harbour agitation modelling;
- wave overtopping analysis;
- run-up calculation;
- extreme-value analysis;
- physical model scaling;
- storm-event clustering;
- directional sector fitting;
- climate-change correction.
For breakwater, harbour, dredging, coastal protection or runway-extension design, the output should normally be treated as an offshore or regional metocean input that may require transformation to the project site.
A minimal folder for source execution is:
project-folder\
├─ download_era5_data.py
├─ download_era5_data.spec
└─ README.md
After a run, the folder may contain:
project-folder\
├─ defaults.json
├─ download_era5_data.log
├─ era5_data.csv
└─ output.csv
After compilation, PyInstaller creates:
project-folder\
├─ build\
├─ dist\
│ └─ download_era5_data.exe
└─ download_era5_data.spec
The build\ folder can be deleted after successful compilation. The dist\download_era5_data.exe file is the standalone executable.
The main execution path is:
main()
-> build_parser()
-> validate_runtime_dependencies()
-> GUI mode or CLI mode
-> execute_pipeline()
-> setup_logging()
-> _preflight_output_files()
-> download_raw_csv()
-> build_output_csv()
| Function | Role |
|---|---|
_ensure_standard_streams() |
Prevents no-console Windows EXE stream errors |
_application_directory() |
Resolves script/EXE output directory |
load_defaults() / save_defaults() |
Handles defaults.json |
validate_runtime_dependencies() |
Checks required imports |
resolve_cds_api_config() |
Finds and parses .ecmwfapirc / .cdsapirc credentials in the supported search order |
initialize_cds_client() |
Creates cdsapi.Client with the parsed url, key and optional verify setting |
_build_cds_request() |
Builds the CDS API request dictionary |
_download_cds_payload() |
Downloads the CDS response payload |
_read_tables_from_cds_payload() |
Detects plain CSV, ZIP or Excel-like payloads |
standardize_dataframe() |
Maps raw table columns to compact names |
_normalize_cds_payload_to_merged_csv() |
Produces era5_data.csv |
build_output_csv() |
Computes wind and dwi, writes output.csv |
Era5DownloaderGUI |
Tkinter GUI controller |
TkTextWriter |
File-like adapter for the GUI log text widget |
To add more variables, modify:
- the
LONG_*constants or add new constants; ERA5_VARIABLES;MERGED_COLUMNSif the variable should be preserved inera5_data.csv;OUTPUT_COLUMNSif the variable should appear inoutput.csv;RAW_TO_SHORT_CANDIDATESfor mapping aliases;build_output_csv()if derived variables are required;- this README.
For additional variables, verify whether they belong to the atmospheric grid or wave grid and whether CDS returns them in separate files.
-
Copernicus Climate Data Store. ERA5 hourly time-series data on single levels from 1940 to present.
https://cds.climate.copernicus.eu/datasets/reanalysis-era5-single-levels-timeseries -
Copernicus Knowledge Base / ECMWF Confluence. ERA5 hourly time-series data on single levels from 1940 to present: Product User Guide (PUG).
https://confluence.ecmwf.int/pages/viewpage.action?pageId=505390919 -
Copernicus Knowledge Base / ECMWF Confluence. ERA5: data documentation.
https://confluence.ecmwf.int/display/CKB/ERA5%3A+data+documentation -
Copernicus Knowledge Base / ECMWF Confluence. How to download ERA5.
https://confluence.ecmwf.int/display/CKB/How+to+download+ERA5 -
Copernicus Knowledge Base / ECMWF Confluence. How to install and use CDS API on Windows.
https://confluence.ecmwf.int/display/CKB/How+to+install+and+use+CDS+API+on+Windows
-
Hersbach, H., Bell, B., Berrisford, P., et al. (2020). The ERA5 global reanalysis. Quarterly Journal of the Royal Meteorological Society, 146, 1999–2049.
https://doi.org/10.1002/qj.3803 -
Bell, B., Hersbach, H., Simmons, A., et al. (2021). The ERA5 global reanalysis: Preliminary extension to 1950. Quarterly Journal of the Royal Meteorological Society, 147, 4186–4227.
https://doi.org/10.1002/qj.4174
-
Python Software Foundation. Python documentation.
https://docs.python.org/ -
PyInstaller. PyInstaller documentation.
https://pyinstaller.org/ -
pandas Development Team. pandas documentation.
https://pandas.pydata.org/docs/ -
NumPy Developers. NumPy documentation.
https://numpy.org/doc/ -
Copernicus Climate Data Store. CDS API package and access instructions.
https://cds.climate.copernicus.eu/how-to-api
When data generated by this script are used in reports, papers, design notes or contractual submissions, cite the relevant Copernicus/ECMWF ERA5 dataset entry and the scientific ERA5 references. Also archive the generated download_era5_data.log, because it records the requested variables, target point, date range and output files.
Suggested report wording:
ERA5 hourly time-series data were retrieved from the Copernicus Climate Data Store using the dataset `reanalysis-era5-single-levels-timeseries`. The selected variables were significant height of combined wind waves and swell, mean wave period, mean wave direction, and the 10 m U and V wind components. Wind speed and meteorological wind direction were computed from the 10 m vector components during post-processing.