Metadata-Version: 2.4
Name: rencal
Version: 0.2.0
Summary: Weather-to-power calibration and Monte Carlo load factor simulation for renewable energy applications
Keywords: weather,forecasting,renewable energy,wind power,solar power,era5,monte carlo,calibration,climate
Author: Low Carbon Contracts Company Ltd
Author-email: Low Carbon Contracts Company Ltd <analytics@lowcarboncontracts.uk>
License-Expression: MIT
License-File: LICENSE
Classifier: Intended Audience :: Science/Research
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
Classifier: Topic :: Utilities
Requires-Dist: numpy>=1.20.0
Requires-Dist: pandas>=1.3.0
Requires-Dist: scipy>=1.7.0
Requires-Dist: matplotlib>=3.4.0
Requires-Dist: seaborn>=0.12.0
Requires-Dist: scikit-learn>=1.0.0
Requires-Dist: netcdf4>=1.5.0
Requires-Dist: xarray>=0.19.0
Requires-Dist: pytz>=2021.1
Requires-Dist: requests>=2.25.0
Requires-Dist: polars>=1.8.2
Requires-Dist: pydantic>=2.10.6
Requires-Dist: pyodbc>=4.0.0
Requires-Dist: cdsapi>=0.6.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: openpyxl>=3.1.0
Requires-Dist: zarr>=2.16.1
Requires-Dist: tqdm>=4.62.0
Requires-Dist: pyarrow>=22.0.0
Maintainer: Low Carbon Contracts Company Ltd
Maintainer-email: Low Carbon Contracts Company Ltd <analytics@lowcarboncontracts.uk>
Requires-Python: >=3.12, <3.13
Project-URL: Homepage, https://github.com/LCCC-Tech/rencal
Project-URL: Repository, https://github.com/LCCC-Tech/rencal.git
Project-URL: Bug Tracker, https://github.com/LCCC-Tech/rencal/issues
Project-URL: Changelog, https://github.com/LCCC-Tech/rencal/blob/main/CHANGELOG.md
Description-Content-Type: text/markdown

# RenCal

RenCal (Renewable Calibration) is a Python library for calibrating renewable
energy power curves and generating probabilistic load-factor time series for
wind and solar plants.

It supports Monte Carlo-based forecasting using weather, generation, and plant
characteristic data. RenCal is intended for energy analysts, researchers, and
developers working on renewable-energy modelling.

## Status

RenCal is an experimental pre-1.0 public package. The API and modelling
approach may change as the project develops. It is not currently a guarantee of
production suitability or a substitute for independent validation.

## Installation

RenCal is available on [PyPI](https://pypi.org/project/rencal/). Install it
with your preferred Python package manager:

### uv

```bash
uv add rencal
```

### pip

```bash
python -m pip install rencal
```

### From source (contributors)

```bash
git clone https://github.com/LCCC-Tech/rencal.git
cd rencal
uv sync --group dev
```

See the [development setup](CONTRIBUTING.md#development-setup) for the full
contributor workflow.

## Quick start

### Download sample inputs automatically

The following example downloads the inputs, calibrates wind streams, and
generates a random sample using RenCal's default data directory. Downloads use
the Copernicus Climate Data Store (CDS), so you need your own CDS credentials,
network access, and permission to access the requested data.

Set the API key in your environment before running the script:

```bash
export CDS_API_KEY="your-cds-api-key"
```

Alternatively, pass the key directly to `DownloadManager`. Never commit API
keys to source control.

```python
import datetime
import random

import numpy as np

from rencal.calibration.wind.wind_calibrator import WindCalibrator
from rencal.core.data_loader import LocalDataLoader
from rencal.core.data_downloader import DownloadManager
from rencal.simulation.weather_data import HistoricalMetadata, WeatherData


def main():
    # Uses CDS_API_KEY from the environment. Alternatively:
    # downloader = DownloadManager(cds_api_key="your-cds-api-key")
    downloader = DownloadManager()
    downloader.download_all()

    loader = LocalDataLoader()
    plants = loader.load_plant_data()
    generation = loader.load_generation_data()

    print(f"Loaded {len(plants.data)} plants")
    print(f"Loaded {len(generation.data)} generation records")

    calibrator = WindCalibrator(
        output_path="wind-calibration",
        visual_output=True,
        stream_npy_output=True,
    )
    calibrator.calibrate()

    manifest = loader.check_historical_weather()
    metadata = HistoricalMetadata.from_manifest(
        manifest,
        loader.path_resolver_weather_data,
    )
    wind_sampler = WeatherData(
        metadata=metadata,
        prefix_histograms=loader.get_prefix_histograms(),
        historical_data=loader.get_historical_weather(),
    )
    sample = wind_sampler.random_sample(
        datetime.datetime(2027, 1, 1),
        datetime.datetime(2027, 1, 7),
        python_rng=random.Random(4),
        numpy_rng=np.random.default_rng(32),
    )
    print(sample)


if __name__ == "__main__":
    main()
```

`download_all()` downloads the CfD, generation, and ERA5 inputs. If you already
have the plant and generation data, use `download_era5()` to download only the
weather data:

```python
downloader = DownloadManager()  # Uses CDS_API_KEY from the environment
downloader.download_era5()
```

### Use your own data

The primary modelling workflow can instead use data supplied by you. RenCal
does not distribute operational ERA5, generation, or plant datasets.

```python
from pathlib import Path

from rencal.core.data_loader import LocalDataLoader

loader = LocalDataLoader(data_path=Path("data"))
plants = loader.load_plant_data()
generation = loader.load_generation_data()

print(f"Loaded {len(plants.data)} plants")
print(f"Loaded {len(generation.data)} generation records")
```

For the full wind-calibration workflow, provide the expected input structure:

```text
data/
├── plant/plant_data.csv
├── generation/generation_data.parquet
└── era5/*.nc
```

The ERA5 loader expects suitable NetCDF weather data. Users are responsible for
obtaining data, checking its provenance and licence, and preparing it for the
documented schema.

### Calibrate wind power curves

With the plant, generation, and ERA5 inputs in place, run the wind calibration
workflow and write its outputs to a separate directory:

```python
from pathlib import Path

from rencal.calibration.wind.wind_calibrator import WindCalibrator

calibrator = WindCalibrator(
    data_path="data",
    output_path=Path("outputs/wind-calibration"),
    visual_output=True,
    stream_npy_output=True,
)
calibrator.calibrate()
```

The workflow writes the calibration summary, Weibull parameters, extracted wind
speeds, calibrated wind streams, and optional power-curve plots to the output
directory. With `stream_npy_output=True`, the generated `Wind Streams.npy` can
also be used by the weather sampler after its manifest and optional histogram
artefacts have been prepared.

### Sample calibrated wind streams

`WeatherData` samples future hourly paths from calibrated historical streams
while preserving the configured time-bucket structure. The local loader expects
the calibrated NPY file and its manifest under `data/calibrated/`.

```python
import datetime
import random

import numpy as np

from rencal.core.data_loader import LocalDataLoader
from rencal.simulation.weather_data import HistoricalMetadata, WeatherData

loader = LocalDataLoader(data_path="data")
manifest = loader.check_historical_weather()
metadata = HistoricalMetadata.from_manifest(
    manifest,
    loader.path_resolver_weather_data,
)

wind_sampler = WeatherData(
    metadata=metadata,
    prefix_histograms=loader.get_prefix_histograms(),
    historical_data=loader.get_historical_weather(),
)

sample = wind_sampler.random_sample(
    datetime.datetime(2027, 1, 1),
    datetime.datetime(2027, 1, 7),
    python_rng=random.Random(4),
    numpy_rng=np.random.default_rng(32),
)
```

Pass `desired_averages` to `WeatherData` when inverse-distribution resampling is
required; this also requires historical data or precomputed prefix histograms.

## Main capabilities

- Wind and solar power-curve calibration foundations
- Probabilistic load-factor forecasting
- Weather and generation data loading and validation
- Time-bucketed sampling with geographical correlation support
- Extensible interfaces for local and external data sources

## Documentation

- [Wind calibration tutorial](docs/tutorials/wind_calibration_tutorial.ipynb)
- [Contributing](CONTRIBUTING.md)
- [Code of Conduct](CODE_OF_CONDUCT.md)
- [Issue tracker](https://github.com/LCCC-Tech/rencal/issues)

Hosted documentation and versioned examples will be linked here once the public
documentation site is verified.

## Support

Use [GitHub Issues](https://github.com/LCCC-Tech/rencal/issues) for public,
reproducible bugs and feature requests. Please do not include credentials,
internal data, or confidential information in issues.

## Licence

RenCal is released under the [MIT Licence](LICENSE).
