From 160207ca814ea58e8c8e69501bad1b0b00eb04b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mikkel=20Friis-M=C3=B8ller?= <mikf@dtu.dk>
Date: Wed, 13 Oct 2021 08:34:53 +0000
Subject: [PATCH] updated xrsite to export yml

---
 py_wake/site/xrsite.py                | 51 +++++++++++++++++++++++++++
 py_wake/tests/test_sites/test_site.py | 33 ++++++++++++++---
 py_wake/utils/ieawind37_utils.py      |  8 +++++
 3 files changed, 88 insertions(+), 4 deletions(-)
 create mode 100644 py_wake/utils/ieawind37_utils.py

diff --git a/py_wake/site/xrsite.py b/py_wake/site/xrsite.py
index 458a2c7f0..214714f81 100644
--- a/py_wake/site/xrsite.py
+++ b/py_wake/site/xrsite.py
@@ -2,9 +2,13 @@ import numpy as np
 from numpy import newaxis as na
 import xarray as xr
 from requests import get
+import yaml
+import os
+from pathlib import Path
 from py_wake.site._site import Site
 from py_wake.site.distance import StraightDistance
 from py_wake.utils import weibull
+from py_wake.utils.ieawind37_utils import iea37_names
 from py_wake.utils.grid_interpolator import GridInterpolator, EqDistRegGrid2DInterpolator
 
 
@@ -251,6 +255,53 @@ class XRSite(Site):
                 lw['P'] = p_wd * self.weibull_weight(lw, A, k)
         return lw
 
+    def to_ieawind37_ontology(self, name='Wind Resource', filename='WindResource.yaml', data_in_netcdf=False):
+        name_map = {k: v for k, v in iea37_names()}
+        ds = self.ds.sel(wd=self.ds.wd[:-1])
+        ds_keys = list(ds.keys()) + list(ds.coords)
+        map_dict = {key: name_map[key] for key in ds_keys if key in name_map}
+        ds = ds.rename(map_dict)
+
+        def fmt(v):
+            if isinstance(v, dict):
+                return {k: fmt(v) for k, v in v.items() if fmt(v) != {}}
+            elif isinstance(v, tuple):
+                return list(v)
+            else:
+                return v
+        data_dict = fmt(ds.to_dict())
+
+        if not data_in_netcdf:
+            # yaml with all
+            yml = yaml.dump({'name': name, 'wind_resource': {**{k: v['data'] for k, v in data_dict['coords'].items()},
+                                                             **data_dict['data_vars']}})
+            Path(filename).write_text(yml)
+
+        else:
+            # yaml with data in netcdf
+            ds.to_netcdf(filename.replace('.yaml', '.nc'))
+            yml_nc = yaml.dump({'name': name, 'wind_resource': "!include %s" % os.path.basename(filename).replace('.yaml', '.nc')}).replace("'", "")
+            Path(filename).write_text(yml_nc)
+
+    def from_iea37_ontology_yml(filename, data_in_netcdf=False):
+        name_map = {v: k for k, v in iea37_names()}
+        if not data_in_netcdf:
+            with open(filename) as fid:
+                yml_dict = yaml.safe_load(fid)['wind_resource']
+                for k, v in yml_dict.items():
+                    if not isinstance(v, dict):  # its a coord
+                        yml_dict[k] = {'dims': [k], 'data': v}
+                ds = xr.Dataset.from_dict(yml_dict)
+                map_dict = {key: name_map[key] for key in list(ds.keys()) + list(ds.coords)}
+                ds = ds.rename(map_dict)
+                xr_site = XRSite(ds)
+        else:
+            with xr.open_dataset(filename.replace(".yaml", '.nc')).load() as ds:
+                map_dict = {key: name_map[key] for key in list(ds.keys()) + list(ds.coords)}
+                ds = ds.rename(map_dict)
+                xr_site = XRSite(ds)
+        return xr_site
+
 
 class UniformSite(XRSite):
     """Site with uniform (same wind over all, i.e. flat uniform terrain) and
diff --git a/py_wake/tests/test_sites/test_site.py b/py_wake/tests/test_sites/test_site.py
index 7c41ffd0c..08208bef4 100644
--- a/py_wake/tests/test_sites/test_site.py
+++ b/py_wake/tests/test_sites/test_site.py
@@ -1,11 +1,13 @@
-from py_wake.site._site import UniformWeibullSite, UniformSite
+import os
+import pytest
 import numpy as np
+import matplotlib.pyplot as plt
 from py_wake.tests import npt
-import pytest
+from py_wake.site._site import UniformWeibullSite, UniformSite
 from py_wake.site.shear import PowerShear
-import matplotlib.pyplot as plt
-from py_wake.examples.data.iea37._iea37 import IEA37Site
 from py_wake.site.xrsite import XRSite
+from py_wake.tests.test_files import tfp
+from py_wake.examples.data.iea37._iea37 import IEA37Site
 
 f = [0.035972, 0.039487, 0.051674, 0.070002, 0.083645, 0.064348,
      0.086432, 0.117705, 0.151576, 0.147379, 0.10012, 0.05166]
@@ -238,3 +240,26 @@ def test_uniform_site_probability():
     site = UniformSite(p_wd, ti=1)
     lw = site.local_wind(0, 0, 0, wd=np.linspace(0, 360, p_wd.size, endpoint=False), ws=12)
     npt.assert_array_almost_equal(lw.P, p_wd)
+
+
+def test_ieawind37_ontology_yaml_export(site):
+    dirname = 'test_export_temp'
+    filename = 'WindResource.yaml'
+    os.makedirs(os.path.join(tfp, dirname), exist_ok=True)
+    site.to_ieawind37_ontology(filename=os.path.join(tfp, dirname, filename), data_in_netcdf=False)
+    yml_site = XRSite.from_iea37_ontology_yml(filename=os.path.join(tfp, dirname, filename), data_in_netcdf=False)
+    os.remove(os.path.join(tfp, dirname, filename))
+    os.rmdir(os.path.join(tfp, dirname))
+    assert yml_site.ds.equals(site.ds)
+
+
+def test_ieawind37_ontology_netcdf_export(site):
+    dirname = 'test_export_temp'
+    filenames = ['WindResource.yaml', 'WindResource.nc']
+    os.makedirs(os.path.join(tfp, dirname), exist_ok=True)
+    site.to_ieawind37_ontology(filename=os.path.join(tfp, dirname, filenames[0]), data_in_netcdf=True)
+    yml_site = XRSite.from_iea37_ontology_yml(os.path.join(tfp, dirname, filenames[0]), data_in_netcdf=True)
+    for f in filenames:
+        os.remove(os.path.join(tfp, dirname, f))
+    os.rmdir(os.path.join(tfp, dirname))
+    assert yml_site.ds.equals(site.ds)
diff --git a/py_wake/utils/ieawind37_utils.py b/py_wake/utils/ieawind37_utils.py
new file mode 100644
index 000000000..9cef99bf0
--- /dev/null
+++ b/py_wake/utils/ieawind37_utils.py
@@ -0,0 +1,8 @@
+def iea37_names():
+    return [('P', 'probability'),
+            ('TI', 'turbulence_intensity'),
+            ('wd', 'wind_direction'),
+            ('ws', 'wind_speed'),
+            ('Sector_frequency', 'sector_probability'),
+            ('Weibull_A', 'weibull_a'),
+            ('Weibull_k', 'weibull_k')]
-- 
GitLab