PVRADAR is a framework for modelling without limits - flexible, transparent and seamless.
Back to Homepage https://pvradar.com/
Getting Started
Core Concepts
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.
models
A 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.
context
A 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.resources
A 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