.. _working_with_xarray_and_windkit: =============================== Working With Xarray and WindKit =============================== Many data structures in PyWAsP are :doc:`Xarray ` objects, which means they are collections of largely self-describing multidimensional arrays and collections of arrays. Each :py:class:`xarray.Dataset` holds one or several :py:class:`xarray.DataAarray`'s, as well as labels and names for the array-dimensions and coordinates. The advantages of labeled arrays are many. Xarray's :doc:`Quick Overview ` goes through a lot of them, so we will highlight just a few here: - Select data and apply operations by name rather than axis/index - Automatic alingment of coordiantes and broadcasting of dimensions - Attach attributes to data with it's ``.attrs`` attribute In :doc:`WindKit ` and PyWAsP, we leverage these capabilities to a great extend by defining specific object-types as :py:class:`xarray.Dataset`'s with specific names for dimensions and variables (you could call it a schema). For example, PyWAsP recognises a "binned wind climate" object as: - A :py:class:`xarray.Dataset` object - Has variables ``wsfreq`` and ``wdfreq`` for the wind speed and direction frequencies - ``wsfreq`` has (at least, but not limited to) the dimensions ``wsbin`` and ``sector`` - ``wdfreq`` has ``sector`` as a dimension. In this example, ``wsbin`` and ``sector`` are core dimensions and need to be present. These required naming patterns enables us to write Xarray-based code where assumptions can be made about the object, but as long as the expected patterns are there, the objects are allowed to vary in shape and size and, by e.g. having other non-core dimensions. We go into depth with this in the :doc:`WindKit Introduction `, but we will quickly illustrate it here as well. Let's read in a binned wind climate and print out inspect the :py:class:`xarray.Dataset`: .. ipython:: python from pathlib import Path import pywasp as pw import windkit as wk path = Path("../modules/examples/tutorial_4/data") bwc = wk.read_bwc(path / "SerraSantaLuzia.omwc", crs="EPSG:4326") print(bwc) We can see the "binned wind climate" has the pattern described above, and that in this case it has one extra dimension ``point`` with associated geospatial information. To calculate the mean wind speed for this object :py:func:`windkit.wind_climate.mean_windspeed` can be used: .. ipython:: python mean_ws = wk.mean_windspeed(bwc) print(mean_ws) We can see that all the "core" dimensions have been reduced and we obtain the mean wind speed for the single point. If the object has more points or other extra dimensions they would be looped-over and one value per extra dimension returned: .. ipython:: python bwc = bwc.expand_dims(extra_dim=["one", "two", "three"]) mean_ws = wk.mean_windspeed(bwc) print(mean_ws) What is happening "under the hood" can be expressed using just the built-in :doc:`Xarray ` methods as: .. ipython:: python # Multiply wind speeds with frequencies and sum over wind speed and direction bins mean_ws = (bwc["wsbin"] * bwc["wsfreq"] * bwc["wdfreq"]).sum(dim=("wsbin", "sector")) print(mean_ws) Becoming proficient with PyWAsP means, at a minimum, becoming familiar with Xarray, and what it can do. However, we encourage users to spend enough time with Xarray to become comfortable with it. It will make your experience using PyWAsP much easier.