.. _working_with_xarray_and_windkit: =============================== Working With Xarray and WindKit =============================== Many data structures in PyWAsP are :doc:`Xarray ` objects. These objects are collections of largely self-describing multidimensional arrays. Each :py:class:`xarray.Dataset` holds one or more :py:class:`xarray.DataArray` objects, along with labels and names for the array dimensions and coordinates. Labeled arrays have many advantages. Xarray's :doc:`Quick Overview ` covers many of them, but we will highlight a few here: - Select data and apply operations by name rather than by axis or index. - Automatic alignment of coordinates and broadcasting of dimensions. - Attach attributes to data with its ``.attrs`` attribute. In :doc:`WindKit ` and PyWAsP, we leverage these capabilities extensively by defining specific object types as :py:class:`xarray.Dataset` objects with specific names for dimensions and variables (this can be thought of as a schema). For example, PyWAsP recognizes a "binned wind climate" object as: - A :py:class:`xarray.Dataset` object. - It has variables ``wsfreq`` and ``wdfreq`` for the wind speed and direction frequencies. - ``wsfreq`` has dimensions ``wsbin`` and ``sector`` (among others). - ``wdfreq`` has ``sector`` as a dimension. In this example, ``wsbin`` and ``sector`` are core dimensions and must be present. These required naming patterns enable us to write Xarray-based code where assumptions can be made about the object. As long as the expected patterns are present, the objects can vary in shape and size, for example, by having other non-core dimensions. We cover this in more depth in the :doc:`WindKit Introduction `, but we will also illustrate it here. Let's read in a binned wind climate and 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_1/data") bwc = wk.read_bwc(path / "SerraSantaLuzia.omwc", crs="EPSG:4326") print(bwc) We can see that the "binned wind climate" follows the pattern described above. In this case, it also has an extra dimension, ``point``, with associated geospatial information. To calculate the mean wind speed for this object, you can use :py:func:`windkit.mean_wind_speed`: .. ipython:: python mean_ws = wk.mean_wind_speed(bwc) print(mean_ws) We can see that all the core dimensions have been reduced, and we now have the mean wind speed for the single point. If the object had more points or other extra dimensions, they would be looped over, and one value per extra dimension would be returned: .. ipython:: python bwc = bwc.expand_dims(extra_dim=["one", "two", "three"]) mean_ws = wk.mean_wind_speed(bwc) print(mean_ws) What is happening "under the hood" can be expressed using only the built-in :doc:`Xarray ` methods: .. 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 its capabilities. We encourage you to spend enough time with Xarray to become comfortable with it. This will make your experience using PyWAsP much easier.