pywrb 0.1.3
Wind Resource binary reader and writer

# Whiffle App

The pywrb library for reading and writing WRB files.

## Features

* Read and write WRB files

## Requirements

* Python 3.12+
* NumPy

Optional:
* Xarray

## Installation

To install the pywrb, follow these steps:

1. Clone the repository: `git clone https://gitlab.com/whiffle/common/pywrb.git` and change directory `cd pywrb`
2. Create a virtual environment `python3 -m venv .venv`
2. Install the dependencies: `pip install -r requirements.txt`
3. Run the tests `pip install -e .[dev]` and `pytest tests`

## Usage

### Xarray interface

For almost all use cases we recommend using the xarray interface. This can be installed using:

`pip install pywrb[xarray]`

You can then open an existing WRB directly from xarray

```python
import pywrb

ds = xarray.open_dataset(filename="tests/fixtures/real_world.wrb", engine="pywrb")

ds["elevation"].plot.imshow()
```

Or writing a WRB can be done using

```python
    import xarray as xr
    import numpy as np
    import pywrb

    n_x, n_y, n_directions, n_wind_speed, n_heights = 128, 128, 12, 10, 3

    ds = xr.Dataset(
        data_vars=dict(
            weibull_scale=(["x", "y", "directions", "heights"], np.random.randn(n_x, n_y, n_directions, n_heights)),
            weibull_shape=(["x", "y", "directions", "heights"], np.random.randn(n_x, n_y, n_directions, n_heights)),
            wind_shear_exponent=(["x", "y", "directions"], np.random.randn(n_x, n_y, n_directions)),
            inflow_angle=(["x", "y", "directions", "heights"], np.random.randn(n_x, n_y, n_directions, n_heights)),
            turbulence_intensity=(
                ["x", "y", "directions", "wind_speeds", "heights"],
                np.random.randn(n_x, n_y, n_directions, n_wind_speed, n_heights),
            ),
            elevation=(["x", "y"], np.ones((n_x, n_y))),
            roughness_length=(["x", "y"], np.ones((n_x, n_y))),
            probability=(
                ["x", "y", "directions", "wind_speeds", "heights"],
                (lambda a: a / np.linalg.norm(a))(np.random.rand(n_x, n_y, n_directions, n_wind_speed, n_heights)),
            ),
        ),
        coords=dict(
            x=(["x"], np.arange(n_x)),
            y=(["y"], np.arange(n_y)),
            directions=(["directions"], np.linspace(0, 360, n_directions, endpoint=False)),
            wind_speeds=(["wind_speeds"], np.linspace(6, 15, n_wind_speed)),
            heights=(["heights"], [100, 150, 200]),
        ),
    )
    # WRB's require a coordinate system
    ds = ds.rio.write_crs("epsg:4326")
    ds.pywrb.to.to_wrb("my-new.wrb")

```

### Low-level interface
With the low level interface you can specifically add blocks to the WRB for specific quantities. This is mostly intended for incorporating more exotic data in the WRB that can't be done through the xarray interface.

To open an existing WRB file you can:

```python
import pywrb
import matplotlib.pyplot as plt
data = numpy.ones(10, 10)

with pywrb.open(filename="existing.wrb", mode="r") as wrb:
    elevation = None
    for block, data in wrb.items:
        if block["meaning"] == pywrb.WRB_BLOCK_MEANING.ELEVATION:
            plt.imshow(data)
```


To generate a new WRB file you can
```python
import pywrb
data = numpy.ones(10, 10)

with pywrb.open(
    filename="test.wrb",
    mode="w",
    crs="EPSG:25832",
    minx=0,
    miny=0,
    maxx=900,
    maxy=900,
    resolutionx=100,
    resolutiony=100,
    heights=[100],
    directions=0,
    wind_speeds=[]
) as wrb:
    wrb.add_block('elevation', data=data, unit=pywrb.WRB_UNIT.METER)
    wrb.add_block('mean_wind_speed', data=data+1, height=100, unit=pywrb.WRB_UNIT.METER_PER_SECOND)
    wrb.write()
```

## Contributing

Contributions to `pywrb` are welcome! If you'd like to contribute, please fork the repository and submit a pull request.

## License

`pywrb` is licensed under the [MIT License](https://opensource.org/licenses/MIT).