Skip to main content

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. Install it with your preferred Python package manager:

uv

uv add rencal

pip

python -m pip install rencal

From source (contributors)

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

See the 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:

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

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

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:

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.

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:

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:

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/.

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

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

Support

Use GitHub 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.

Metadata

Release files for rencal 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rencal 0.2.1
File Size Uploaded
rencal-0.2.1.tar.gz 51.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for rencal 0.2.1
File Interpreter ABI Platform
rencal-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 112.2 kB

Release files / rencal-0.2.1.tar.gz

Download URL rencal-0.2.1.tar.gz
Size 51.5 kB
Tags Source
SHA-256 checksum
How to use checksums
8cabdf4f342bb92766a3914a1812a873d8aca6a591e55241bb05e2c1df172325
BLAKE2b-256 checksum
How to use checksums
8244ecf2136b7935e260644e0fa73d03f1a88373ea08269a77aeba1261ff1583
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Release files / rencal-0.2.1-py3-none-any.whl

Download URL rencal-0.2.1-py3-none-any.whl
Size 60.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b82c0177c40a514b6ae4a0b3f0b907c23916ed01fbe8f45eb68dc6f4b4bd8f5e
BLAKE2b-256 checksum
How to use checksums
2f2726f8f7fa4ec7ef510476ff5d7fa9804ee676081922dd16c02d5a6bf4b9dc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page