PVRADAR is a framework for modelling without limits - flexible, transparent and seamless.
Back to Homepage https://pvradar.com/
Getting Started
Core Concepts
Timestamp alignment & resampling
Docs under construction
Satellite Databases and Meteo Stations
Table of Contents
<aside> đź’ˇ
The first core idea behind the PVRADAR Python package is simple: focus on your model logic, not on fetching and formatting input data.
</aside>
Let’s say you’ve defined a custom soiling model like this:
def my_soiling_model(rainfall, pm2_5, pm10, cleaning_threshold, ...):
...
Using PVRADAR, running ANY model requires just one line:
site.run(my_soiling_model)
The magic here is that site — the modeling context — **** automatically binds the required inputs to your function, meaning it retrieves the right data, applies unit conversions and aggregations, all according to user-defined preferences. You don’t need to worry about how the data gets from the satellite database or measurement station into your model. PVRADAR handles it.
<aside> đź’ˇ
The second core idea behind the PVRADAR Python package is to allow users to build flexible modeling workflows and digital twins — by seamlessly chaining together custom and prebuilt models (e.g., from pvlib) and embedding them in broader energy simulation contexts.
</aside>
You can rely on existing models where they make sense and intervene with your own custom logic where needed.
âś… Absolute Control. âś… Maximum Flexibility. âś… Full Transparency.
modelsA model is a Python function that calculates results from a set of parameters. These parameters can be:
Example: a soiling model might calculate soiling loss based on rainfall, dust concentration and a cleaning threshold.
contextA context is an object that holds data (called resources) and metadata to be used by one or more models.
Examples:
site includes location and simulation interval, and potentially a simplified design.project includes a full description of design parameters for yield estimation.resourcesA resource is any data (e.g., time-series) registered in a context to serve as input to a model.
Each resource is linked to a specific resource type, which defines the physical meaning (e.g., rainfall) independently of unit, frequency, or source.
By adding a resource to a modeling context once, you ensure consistency across all models that use it.
Let’s walk through a concrete example — running the HSU model from pvlib for a random location in the USA.
First, define a PvradarSite, which stores the location and modeling interval.
from pvradar.sdk import PvradarSite
site = PvradarSite(location=(33.074, -112.243), interval='2015..2016')
In this example the modeling context is a site in Arizona and any modeling will be done for the time between the first hour of 2015 and the last hour of 2016, in local time.
➡️ More on Modeling Contexts
Now that the context is defined, fetching relevant data is very simple - in a single line of code!
rainfall = site.resource(R.rainfall) # returns total hourly rainfall in mm
pm2_5 = site.resource(R.pm2_5_volume_concentration) # mean hourly pm2.5 volume concentration in Kg/m^3
pm10 = site.resource(R.pm10_volume_concentration) # mean hourly pm10 volume concentration in Kg/m^3
Each R.xxx() is a resource descriptor, allowing you to “describe” what exactly you need:
merra2, era5)cm, g/m^3)D for daily, H for hourly)sum, mean, etc.)Example with custom descriptors:
rainfall = site.resource(R.rainfall(data_source='merra2', to_unit='cm', to_freq='D'))
pm2_5 = site.resource(R.pm2_5_volume_concentration(to_unit='g/m^3', to_freq='D'))
pm10 = site.resource(R.pm10_volume_concentration(to_unit='g/m^3', to_freq='D'
Not sure what data exactly you are looking at? Use describe to print a short description.
from pvradar.sdk import describe
describe(rainfall)
rainfall: total daily rainfall in cm from merra2 731 data points (2015-01-01 00:00:00-05:00 to 2016-12-31 00:00:00-05:00)
➡️ More on Resources & R-Notation
➡️ See the list of available data sources for each resource type in
Finally, run the HSU soiling model from pvlib:
from pvlib.soiling import hsu
soiling_hsu = hsu(rainfall, 1, 25, pm2_5, pm10) # cleaning threshold = 1 mm, tilt = 25 deg
Done! You now have soiling loss factors from the HSU model for your location and interval.
But there’s a better way...
Let’s say we want to use the HSU model as one part of a larger model network to estimate energy delivered to the grid — both with and without soiling losses.
The first thing we need to do is bring the model into a from that is compatible with PVRADAR. This means:
resource types so PVRADAR can fetch and bind them automatically with Annotated[...].@resource_type()@resource_type(R.soiling_loss_factor(set_unit='fraction'))
def my_soiling_model_based_on_hsu(
*,
pm2_5: Annotated[pd.Series, R.pm2_5_volume_concentration(to_unit='g/m^3')],
pm10: Annotated[pd.Series, R.pm10_volume_concentration(to_unit='g/m^3')],
rainfall: Annotated[pd.Series, R.rainfall(to_unit='mm')],
cleaning_threshold: float = 1,
tilt: float,
) -> pd.Series:
soiling_ratio = hsu(
rainfall=rainfall,
cleaning_threshold=cleaning_threshold,
surface_tilt=tilt,
pm2_5=pm2_5,
pm10=pm10,
)
return 1 - soiling_ratio