How to run the HSU soiling model for any location and convert irradiance losses into energy losses
Example 1: Execute HSU model for any location worldwide¶
Before running this notebook, make sure you first install pvradar-sdk and request and register your api key. Instructions
from pvradar.sdk import PvradarSite, R, describe, resource_plot, for_resource, convert_to_resource, make_tracker_design, make_fixed_design
Retrieve input data in a single line of code¶
First we need to creat a modeling context - here we use a simple site - that knows the location and interval for which we want to fetch data.
site = PvradarSite(location=(32.642, -114.456), interval='2015..2016') # Yuma, Arizona, USA
# you cal also specify dates, for example: '2025-05-01..2018-01-05'
With that we can simple fetch data - called resources - by calling site.resource
.
In this example, R.rainfall
is the resource descriptor, an object that allows you to specify exactly what you want to have: resource type, unit, frequency, datasource and sometimes additional parameters. Note that data from meteorological stations in the NOAA network are only available in the USA.
Check our Resource DB to see all available options.
rainfall = site.resource(R.rainfall(to_unit='mm', to_freq='D', datasource='noaa'))
As you see, rainfall is simply a pandas Series with a DateTimeindex in local time.
rainfall
2015-01-01 00:00:00-07:00 0.0 2015-01-02 00:00:00-07:00 0.0 2015-01-03 00:00:00-07:00 0.0 2015-01-04 00:00:00-07:00 0.0 2015-01-05 00:00:00-07:00 0.0 ... 2016-12-27 00:00:00-07:00 0.0 2016-12-28 00:00:00-07:00 0.0 2016-12-29 00:00:00-07:00 0.0 2016-12-30 00:00:00-07:00 0.0 2016-12-31 00:00:00-07:00 1.8 Freq: D, Name: rainfall, Length: 731, dtype: float64
Use describe
to get a quick description of a resource, including its unit and datasource.
describe(rainfall)
rainfall: total daily rainfall in mm from noaa 731 data points (2015-01-01 00:00:00-07:00 to 2016-12-31 00:00:00-07:00)
resource_plot
is a convenient function to plot resources from the pvradar python package.
Note that this function uses either matplotlib or plotly to plot, depending on what you have installed.
resource_plot(rainfall)
Getting PM2.5 and PM10 data has never been easier!¶
Now we can get pm2_5 and pm10 data in the same manner.
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'))
Running the HSU model¶
Finally, we can run the HSU model from pvlib
.
from pvlib.soiling import hsu
my_soiling_ratio = hsu(rainfall, 1, 25, pm2_5, pm10)
Let's use resource_plot to generate a nice representation of the results
my_soiling_ratio.attrs['label'] = 'my soiling ratio'
resource_plot(my_soiling_ratio, pm2_5, pm10, rainfall)
Example 2: From Irradiance Losses to Energy Losses¶
To quantify soiling energy losses (at grid connection point) we need to add more information to our simulation context, specifically we need to add a design.
In pvradar, a design, is an object that contains a set of design parameters that describe the modules, the inverter, the array, the structure, the grid, etc.
While it is possible to create very complex and exact representations of a PV Asset, here we use a simple function to generate a (mostly default) design - either for tracker or fixed-tilt.
site.design = make_tracker_design(dc_ac_ratio=1.25, max_tracking_angle=55)
# site.design = make_tracker_design(dc_ac_ratio=1.25, tilt=25) # If you want, see what happens if you use a fixed tilt structure instead of a single-axis tracker
With this we can now call the total daily grid_energy
.
grid_energy_without_soiling = site.resource(R.grid_energy(to_freq='D', to_unit='MWh'))
grid_energy_without_soiling.attrs['label'] = 'grid energy NO SOILING'
resource_plot(grid_energy_without_soiling)
Use flowcharts to vizualize what is actually happening¶
When you call a resource, it triggers the execution of an entire chain of models, where upstream models provide inputs to those downstream.
To visualize the full model chain used to generate a specific resource, simply use display_flowchart
Note that in this example, the final result — effective_poa
— depends on both soiling and snow losses. However, both are currently using placeholder models that assume no losses.
site.profile(R.grid_energy).display_flowchart(show_model_name=True, renderer='kroki_png') # use 'kroki_svg' for higher resolution - open result in separate tab to zoom in and out
# site.profile(R.effective_poa).display_flowchart(show_model_name=True, max_depth=1, renderer='kroki_png') # run this to see a smaller part of the entire flow-chart
Replacing the no-soiling-losses model with the result from HSU¶
PVRADAR allows you to modify the current model chain at any time—either by replacing models with your own or by using (measured) data instead.
On May 22nd there will be a dedicated webinar on this subject: Register here
To achieve what we want in this example, we first need to convert the soiling ratio from the HSU model into a resource—including its unit. Internally, PVRADAR always uses loss factors, so we convert the soiling ratio by subtracting it from 1.
Use R-notation to describe the resource you want to convert it into.
my_soiling_factor = convert_to_resource(1-my_soiling_ratio,R.soiling_loss_factor(set_unit='fraction'))
A hook is a means to tell pvradar to use a specific dataset (or model) whenever a particular resource is being called (direcly or within a model chain).
site.hooks(for_resource(R.soiling_loss_factor).use(my_soiling_factor, label='my_soiling_series'))
<pvradar.sdk.modeling.hooks.HookSelection at 0x138489901d0>
As you can see when you create a new flow chart, effective_poa
now uses the result from HSU instead of the no-losses-model
.
site.profile(R.effective_poa).display_flowchart(show_model_name=True, max_depth=1, renderer='kroki_png')
Calculate grid energy with soiling losses and compare¶
All that is left to do - now that we have added our soiling estimate to the simulatin - is call grid_energy
again and plot.
grid_energy_with_soiling = site.resource(R.grid_energy(to_freq='D', to_unit='MWh'))
grid_energy_with_soiling.attrs['label'] = 'grid energy WITH SOILING'
resource_plot(grid_energy_without_soiling, grid_energy_with_soiling, my_soiling_factor, rainfall)
Comparison of soiling energy loss fraction and soiling loss factor¶
Accoring to our Resource DB, the soiling loss factor is defined as "a dimensionless factor that describes the potential loss of dc power due to soiling."
We can also define an energy loss fraction as the relative difference between the energy fed into the grid with and without the effect of soiling - in other words: the actual soiling energy loss.
energy_loss = grid_energy_without_soiling-grid_energy_with_soiling
energy_loss_fraction = energy_loss/grid_energy_without_soiling
energy_loss_fraction = convert_to_resource(energy_loss_fraction, R.soiling_loss_factor(set_unit='fraction')) # we convert to soiling loss factor so resource_plot plots it together with the other soiling loss factor
resource_plot(grid_energy_without_soiling, grid_energy_with_soiling, my_soiling_factor, energy_loss_fraction)
from IPython.display import display, HTML
display(HTML(f'The average soiling loss factor is <b>{my_soiling_factor.mean() * 100:.2f}%</b>.'))
display(HTML(f'The actual share of grid energy lost due to soiling is <b>{energy_loss.sum() / grid_energy_without_soiling.sum() * 100:.2f}%</b> (including effects of clipping and curtailment).'))
Why PVRADAR?¶
Build digital twins as complex as the real world¶
PVRADAR allows you to model and quantify the impact of any technical or environmental factor—not just soiling—on PV system performance.
- Compare model outputs with real-world data for validation.
- Quantify potential losses or gains in terms of grid yield, Net Present Value (NPV), Levelized Cost of Energy (LCOE), and Performance Ratio (PR).
- Explore what-if scenarios and optimize strategies based on technical and economic trade-offs.
Develop internal modeling tools and web applications¶
With PVRADAR, you can turn your models and workflows into user-friendly, organization-wide tools.
- Build internal web applications that allow non-experts to apply advanced models in just a few clicks.
- Ensure quality and consistency across teams by standardizing modeling workflows.
- Eliminate repetitive tasks through automation, saving time and reducing errors.
What if you could access all your internal data in a single line of python?¶
PVRADAR simplifies working with large, scattered datasets from multiple sources—both external and internal.
- Connect to external data sources (satellites, meteorological stations, operational data).
- Transform and standardize data to ensure compatibility with existing workflows.
- Securely integrate your organization’s proprietary performance and measurement data, either in the cloud or on-premise.
Expert consultancy and support¶
Accelerate your modeling journey with PVRADAR’s expertise.
- Tailor models to your specific challenges, whether in development, operations, or research.
- Validate and optimize models using high-quality reference datasets.
- Gain insights from our industry experience in soiling, snow losses, cleaning optimization, and yield forecasting.