Skip to content

Commit

Permalink
Merge pull request #228 from openclimatefix/jacob/ecmwf-support
Browse files Browse the repository at this point in the history
Add support for ECMWF
  • Loading branch information
jacobbieker authored Oct 17, 2023
2 parents 517fdee + 7cb17b3 commit ba04f32
Show file tree
Hide file tree
Showing 34 changed files with 446 additions and 27 deletions.
3 changes: 3 additions & 0 deletions ocf_datapipes/load/nwp/nwp.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from torchdata.datapipes import functional_datapipe
from torchdata.datapipes.iter import IterDataPipe

from ocf_datapipes.load.nwp.providers.ecmwf import open_ifs
from ocf_datapipes.load.nwp.providers.icon import open_icon_eu, open_icon_global
from ocf_datapipes.load.nwp.providers.ukv import open_ukv

Expand Down Expand Up @@ -39,6 +40,8 @@ def __init__(
self.open_nwp = open_icon_eu
elif provider == "icon-global":
self.open_nwp = open_icon_global
elif provider == "ecmwf":
self.open_nwp = open_ifs
else:
raise ValueError(f"Unknown provider: {provider}")

Expand Down
40 changes: 40 additions & 0 deletions ocf_datapipes/load/nwp/providers/ecmwf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""ECMWF provider loaders"""
import pandas as pd
import xarray as xr

from ocf_datapipes.load.nwp.providers.utils import open_zarr_paths


def open_ifs(zarr_path) -> xr.DataArray:
"""
Opens the ECMWF IFS NWP data
Args:
zarr_path: Path to the zarr to open
Returns:
Xarray DataArray of the NWP data
"""
# Open the data
nwp = open_zarr_paths(zarr_path)
dataVars = list(nwp.data_vars.keys())
if len(dataVars) > 1:
raise Exception("Too many TLDVs")
else:
dataVar = dataVars[0]
ifs: xr.Dataset = nwp[dataVar]
del nwp
ifs = ifs.transpose("init_time", "step", "variable", "latitude", "longitude")
ifs = ifs.rename(
{
"init_time": "init_time_utc",
"variable": "channel",
"latitude": "latitude",
"longitude": "longitude",
}
)
# Sanity checks.
time = pd.DatetimeIndex(ifs.init_time_utc)
assert time.is_unique
assert time.is_monotonic_increasing
return ifs
49 changes: 22 additions & 27 deletions ocf_datapipes/training/pseudo_irradience.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def _normalize_by_pvlib(pv_system):
)
# Guess want fraction of total irradiance on panel, to get fraction to do with capacity
fraction_clear_sky = total_irradiance["poa_global"] / (
clear_sky["dni"] + clear_sky["dhi"] + clear_sky["ghi"]
clear_sky["dni"] + clear_sky["dhi"] + clear_sky["ghi"]
)
print(fraction_clear_sky)
pv_system /= pv_system.capacity_watt_power
Expand Down Expand Up @@ -380,23 +380,23 @@ def _get_id_from_location(x):


def pseudo_irradiance_datapipe(
configuration_filename: Union[Path, str],
use_sun: bool = True,
use_nwp: bool = True,
use_sat: bool = True,
use_hrv: bool = True,
use_pv: bool = True,
use_topo: bool = True,
use_future: bool = False,
size: int = 256,
size_meters: int = 256_000,
use_meters: bool = False,
start_time: datetime.datetime = datetime.datetime(2014, 1, 1),
end_time: datetime.datetime = datetime.datetime(2023, 1, 1),
batch_size: int = 1,
normalize_by_pvlib: bool = True,
one_d: bool = False,
is_test: bool = False,
configuration_filename: Union[Path, str],
use_sun: bool = True,
use_nwp: bool = True,
use_sat: bool = True,
use_hrv: bool = True,
use_pv: bool = True,
use_topo: bool = True,
use_future: bool = False,
size: int = 256,
size_meters: int = 256_000,
use_meters: bool = False,
start_time: datetime.datetime = datetime.datetime(2014, 1, 1),
end_time: datetime.datetime = datetime.datetime(2023, 1, 1),
batch_size: int = 1,
normalize_by_pvlib: bool = True,
one_d: bool = False,
is_test: bool = False,
) -> IterDataPipe:
"""
Make Pseudo-Irradience Datapipe
Expand All @@ -418,6 +418,10 @@ def pseudo_irradiance_datapipe(
batch_size: Batch size for the datapipe
one_d: Whether to return a 1D array or not, i.e. a single PV site in the center as
opposed to a 2D array of PV sites
size_meters: Size, in meters, of the output image
use_meters: Whether to use meters or pixels
normalize_by_pvlib: Whether to normalize the PV generation by the PVLib generation
is_test: Whether to return the test set or not
Returns: datapipe
"""
Expand All @@ -434,20 +438,16 @@ def pseudo_irradiance_datapipe(
use_gsp=False,
use_pv=use_pv,
)
# print(used_datapipes.keys())
# Load GSP national data
used_datapipes["pv"] = used_datapipes["pv"].select_train_test_time(start_time, end_time)

# Now get overlapping time periods
used_datapipes = get_and_return_overlapping_time_periods_and_t0(
used_datapipes, key_for_t0="pv", return_all_times=True if is_test else False
)
# print(used_datapipes.keys())
# return used_datapipes["pv"].zip_ocf(used_datapipes["nwp"],used_datapipes["pv_t0"],used_datapipes["nwp_t0"])
# And now get time slices
used_datapipes = add_selected_time_slices_from_datapipes(used_datapipes)
# print(used_datapipes.keys())
# return used_datapipes["pv"].zip_ocf(used_datapipes["sat"],used_datapipes["pv_future"])

# Now do the extra processing
pv_history = used_datapipes["pv"].map(
Expand Down Expand Up @@ -492,7 +492,6 @@ def pseudo_irradiance_datapipe(
)
pv_datapipe = pv_datapipe.select_id(pv_one_d_datapipe, data_source_name="pv")
pv_history = pv_history.select_id(pv_one_d_datapipe2, data_source_name="pv")
# return pv_datapipe.zip_ocf(pv_history, pv_loc_datapipe, pv_meta_save, pv_sav_loc, used_datapipes["sat"])

if "nwp" in used_datapipes.keys():
# take nwp time slices
Expand Down Expand Up @@ -596,7 +595,6 @@ def pseudo_irradiance_datapipe(
pv_datapipe, pv_meta = pv_datapipe.fork(2)
pv_meta = pv_meta.map(_get_meta)
pv_datapipe = pv_datapipe.map(_get_values)
# return pv_datapipe.zip_ocf(pv_history, pv_loc_datapipe, pv_meta_save, pv_sav_loc, pv_meta, sat_datapipe)
else:
if "hrv" in used_datapipes.keys():
sat_hrv_datapipe, sat_gsp_datapipe = sat_hrv_datapipe.fork(2)
Expand Down Expand Up @@ -666,7 +664,6 @@ def pseudo_irradiance_datapipe(
elif "sat" in used_datapipes.keys():
sat_datapipe, sun_image_datapipe = sat_datapipe.fork(2)
sun_image_datapipe = sun_image_datapipe.create_sun_image(normalize=True)
# return pv_datapipe.zip_ocf(pv_history, pv_loc_datapipe, pv_meta_save, pv_sav_loc, pv_meta, sat_datapipe)
if "nwp" in used_datapipes.keys():
nwp_datapipe, time_image_datapipe = nwp_datapipe.fork(2, buffer_size=100)
time_image_datapipe = time_image_datapipe.create_time_image(
Expand All @@ -681,7 +678,6 @@ def pseudo_irradiance_datapipe(
time_image_datapipe = time_image_datapipe.create_time_image()
else:
time_image_datapipe = None
# return pv_datapipe.zip_ocf(pv_history, pv_loc_datapipe, pv_meta_save, pv_sav_loc, pv_meta, sat_datapipe, time_image_datapipe)

modalities = []
if not one_d:
Expand All @@ -700,7 +696,6 @@ def pseudo_irradiance_datapipe(
modalities.append(time_image_datapipe)

stacked_xarray_inputs = StackXarray(modalities)
# return pv_datapipe.zip_ocf(pv_history, pv_loc_datapipe, pv_meta_save, pv_sav_loc, pv_meta, stacked_xarray_inputs)
return stacked_xarray_inputs.batch(batch_size).zip_ocf(
pv_meta.batch(batch_size),
pv_datapipe.batch(batch_size),
Expand Down
1 change: 1 addition & 0 deletions tests/data/ifs.zarr/.zattrs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
3 changes: 3 additions & 0 deletions tests/data/ifs.zarr/.zgroup
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"zarr_format": 2
}
188 changes: 188 additions & 0 deletions tests/data/ifs.zarr/.zmetadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
{
"metadata": {
".zattrs": {},
".zgroup": {
"zarr_format": 2
},
"ECMWF_BLAH/.zarray": {
"chunks": [
17,
1,
49,
110,
110
],
"compressor": {
"clevel": 5,
"cname": "zstd",
"id": "blosc2"
},
"dtype": "<f4",
"fill_value": "NaN",
"filters": null,
"order": "C",
"shape": [
2,
1,
2,
221,
221
],
"zarr_format": 2
},
"ECMWF_BLAH/.zattrs": {
"Conventions": "CF-1.7",
"GRIB_centre": "ecmf",
"GRIB_centreDescription": "European Centre for Medium-Range Weather Forecasts",
"GRIB_subCentre": 0,
"_ARRAY_DIMENSIONS": [
"variable",
"init_time",
"step",
"latitude",
"longitude"
],
"institution": "European Centre for Medium-Range Weather Forecasts"
},
"init_time/.zarray": {
"chunks": [
1
],
"compressor": {
"blocksize": 0,
"clevel": 5,
"cname": "lz4",
"id": "blosc",
"shuffle": 1
},
"dtype": "<i8",
"fill_value": null,
"filters": null,
"order": "C",
"shape": [
1
],
"zarr_format": 2
},
"init_time/.zattrs": {
"_ARRAY_DIMENSIONS": [
"init_time"
],
"calendar": "proleptic_gregorian",
"long_name": "initial time of forecast",
"standard_name": "forecast_reference_time",
"units": "nanoseconds since 1970-01-01"
},
"latitude/.zarray": {
"chunks": [
221
],
"compressor": {
"blocksize": 0,
"clevel": 5,
"cname": "lz4",
"id": "blosc",
"shuffle": 1
},
"dtype": "<f8",
"fill_value": "NaN",
"filters": null,
"order": "C",
"shape": [
221
],
"zarr_format": 2
},
"latitude/.zattrs": {
"_ARRAY_DIMENSIONS": [
"latitude"
],
"long_name": "latitude",
"standard_name": "latitude",
"stored_direction": "decreasing",
"units": "degrees_north"
},
"longitude/.zarray": {
"chunks": [
221
],
"compressor": {
"blocksize": 0,
"clevel": 5,
"cname": "lz4",
"id": "blosc",
"shuffle": 1
},
"dtype": "<f8",
"fill_value": "NaN",
"filters": null,
"order": "C",
"shape": [
221
],
"zarr_format": 2
},
"longitude/.zattrs": {
"_ARRAY_DIMENSIONS": [
"longitude"
],
"long_name": "longitude",
"standard_name": "longitude",
"units": "degrees_east"
},
"step/.zarray": {
"chunks": [
49
],
"compressor": {
"blocksize": 0,
"clevel": 5,
"cname": "lz4",
"id": "blosc",
"shuffle": 1
},
"dtype": "<f8",
"fill_value": "NaN",
"filters": null,
"order": "C",
"shape": [
2
],
"zarr_format": 2
},
"step/.zattrs": {
"_ARRAY_DIMENSIONS": [
"step"
],
"long_name": "time since forecast_reference_time",
"standard_name": "forecast_period",
"units": "hours"
},
"variable/.zarray": {
"chunks": [
2
],
"compressor": {
"blocksize": 0,
"clevel": 5,
"cname": "lz4",
"id": "blosc",
"shuffle": 1
},
"dtype": "<U5",
"fill_value": null,
"filters": null,
"order": "C",
"shape": [
2
],
"zarr_format": 2
},
"variable/.zattrs": {
"_ARRAY_DIMENSIONS": [
"variable"
]
}
},
"zarr_consolidated_format": 1
}
Loading

0 comments on commit ba04f32

Please sign in to comment.