-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Making the irradiation and weather DataFrame of the ModelChain more flexible #239
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 32 commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
9f97e50
try to use weather DataFrame for irradiance if irradiance DataFrame i…
uvchik d99ee18
try to determine missing columns of the irradiance DataFrame
uvchik 0c83199
remove prepare_irradiance call from run_model
uvchik 9ffa138
replace irradiance DF with weather DF without breaking the API
uvchik 2aae90c
add future warning
uvchik 326dc11
add error if irradiation data is incomplete
uvchik f1e17ee
rename method
uvchik 933e57b
replace non existing function with set set comparison
uvchik 00e0e72
fix assigned attributes in the docstring
uvchik 0abdde4
fix self.weather assignment
uvchik ec5ed5f
fix layout
uvchik ecf6c6d
Merge branch 'master' of https://github.com/pvlib/pvlib-python
uvchik 9e54af7
Merge branch 'master' of https://github.com/pvlib/pvlib-python
uvchik 4d8feaf
change existing tests to new API
uvchik c572a07
add new tests
uvchik 9dac5cf
add columns or update columns of existing weather data
uvchik 7fda218
add attributes to class
uvchik 7e0b626
adapt docstrings
uvchik 300678c
make time an optional argument if self.times is already set
uvchik c74f977
complete temporary version (beta) of "complete_irradiance"
uvchik ef5520e
remove duplicate import
uvchik dfe04b1
update docstring
uvchik b691358
fix typo
5f8ce92
add deprecated parameter to docstring
1bff19f
set default self.weather to None instead of empty DataFrame
721743d
fix typos, layout changes
6a1a61d
avoid mutation of input data (irradiance)
f702c73
overwrite self.weather completly with its parameter instead of column…
82a4366
add more IDE config files to gitignore
34166c8
add whatsnew entry
9ff9fe4
copy doctstring changes to run_model method
76d89c3
make parameters optional if attributes are already set
a63a48f
add example to docstring (not working and excluded from doctest)
uvchik 6097d75
return self and describe it in the docstring
uvchik da8076d
add bug fix to whatsnew
uvchik d4ff364
add empty DataFrame directly to avoid if clauses
uvchik bfb2350
make error message clearer
uvchik File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
.. _whatsnew_0420: | ||
|
||
v0.4.2 () | ||
------------------------ | ||
|
||
This is a minor release from 0.4.0. .... | ||
|
||
|
||
API Changes | ||
~~~~~~~~~~~ | ||
|
||
* The run_model method of the ModelChain will use the weather parameter of all weather data instead of splitting it to irradiation and weather. The irradiation parameter still works but will be removed soon.(:issue:`239`) | ||
|
||
|
||
Enhancements | ||
~~~~~~~~~~~~ | ||
|
||
* Adding a complete_irradiance method to the ModelChain to make it possible to calculate missing irradiation data from the existing columns [beta] (:issue:`239`) | ||
|
||
|
||
Code Contributors | ||
~~~~~~~~~~~~~~~~~ | ||
|
||
* Uwe Krien |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,10 +7,11 @@ | |
""" | ||
|
||
from functools import partial | ||
|
||
import logging | ||
import warnings | ||
import pandas as pd | ||
|
||
from pvlib import solarposition, pvsystem, clearsky, atmosphere | ||
from pvlib import (solarposition, pvsystem, clearsky, atmosphere, tools) | ||
from pvlib.tracking import SingleAxisTracker | ||
import pvlib.irradiance # avoid name conflict with full import | ||
|
||
|
@@ -316,9 +317,13 @@ def __init__(self, system, location, | |
self.losses_model = losses_model | ||
self.orientation_strategy = orientation_strategy | ||
|
||
self.weather = None | ||
self.times = None | ||
self.solar_position = None | ||
|
||
def __repr__(self): | ||
return ('ModelChain for: ' + str(self.system) + | ||
' orientation_startegy: ' + str(self.orientation_strategy) + | ||
' orientation_strategy: ' + str(self.orientation_strategy) + | ||
' clearsky_model: ' + str(self.clearsky_model) + | ||
' transposition_model: ' + str(self.transposition_model) + | ||
' solar_position_method: ' + str(self.solar_position_method) + | ||
|
@@ -602,32 +607,106 @@ def effective_irradiance_model(self): | |
fd*self.total_irrad['poa_diffuse']) | ||
return self | ||
|
||
def prepare_inputs(self, times, irradiance=None, weather=None): | ||
def complete_irradiance(self, times=None, weather=None): | ||
""" | ||
Determine the missing irradiation columns. Only two of the following | ||
data columns (dni, ghi, dhi) are needed to calculate the missing data. | ||
|
||
This function is not safe at the moment. Results can be too high or | ||
negative. Please contribute and help to improve this function on | ||
https://github.com/pvlib/pvlib-python | ||
|
||
Parameters | ||
---------- | ||
times : DatetimeIndex | ||
Times at which to evaluate the model. Can be None if attribute | ||
`times` is already set. | ||
weather : pandas.DataFrame | ||
Table with at least two columns containing one of the following data | ||
sets: dni, dhi, ghi. Can be None if attribute `weather` is already | ||
set. | ||
|
||
Returns | ||
------- | ||
pandas.DataFrame | ||
Containing the missing column of the data sets passed with the | ||
weather DataFrame. | ||
""" | ||
if weather is not None: | ||
self.weather = weather | ||
if times is not None: | ||
self.times = times | ||
self.solar_position = self.location.get_solarposition(self.times) | ||
icolumns = set(self.weather.columns) | ||
wrn_txt = ("This function is not safe at the moment.\n" + | ||
"Results can be too high or negative.\n" + | ||
"Help to improve this function on github:\n" + | ||
"https://github.com/pvlib/pvlib-python \n") | ||
warnings.warn(wrn_txt, UserWarning) | ||
if {'ghi', 'dhi'} <= icolumns and 'dni' not in icolumns: | ||
logging.debug('Estimate dni from ghi and dhi') | ||
self.weather.loc[:, 'dni'] = ( | ||
(self.weather.loc[:, 'ghi'] - self.weather.loc[:, 'dhi']) / | ||
tools.cosd(self.solar_position.loc[:, 'zenith'])) | ||
elif {'dni', 'dhi'} <= icolumns and 'ghi' not in icolumns: | ||
logging.debug('Estimate ghi from dni and dhi') | ||
self.weather.loc[:, 'ghi'] = ( | ||
self.weather.dni * tools.cosd(self.solar_position.zenith) + | ||
self.weather.dhi) | ||
elif {'dni', 'ghi'} <= icolumns and 'dhi' not in icolumns: | ||
logging.debug('Estimate dhi from dni and ghi') | ||
self.weather.loc[:, 'dhi'] = ( | ||
self.weather.ghi - self.weather.dni * | ||
tools.cosd(self.solar_position.zenith)) | ||
|
||
def prepare_inputs(self, times=None, irradiance=None, weather=None): | ||
""" | ||
Prepare the solar position, irradiance, and weather inputs to | ||
the model. | ||
|
||
Parameters | ||
---------- | ||
times : DatetimeIndex | ||
Times at which to evaluate the model. | ||
Times at which to evaluate the model. Can be None if attribute | ||
`times` is already set. | ||
irradiance : None or DataFrame | ||
If None, calculates clear sky data. | ||
Columns must be 'dni', 'ghi', 'dhi'. | ||
This parameter is deprecated. Please use `weather` instead. | ||
weather : None or DataFrame | ||
If None, assumes air temperature is 20 C and | ||
wind speed is 0 m/s. | ||
Columns must be 'wind_speed', 'temp_air'. | ||
If None, the weather attribute is used. If the weather attribute is | ||
also None assumes air temperature is 20 C, wind speed is 0 m/s and | ||
irradiation calculated from clear sky data. | ||
Column names must be 'wind_speed', 'temp_air', 'dni', 'ghi', 'dhi'. | ||
Do not pass incomplete irradiation data. | ||
Use method | ||
:py:meth:`~pvlib.modelchain.ModelChain.complete_irradiance` | ||
instead. | ||
|
||
Returns | ||
------- | ||
self | ||
|
||
Assigns attributes: times, solar_position, airmass, irradiance, | ||
total_irrad, weather, aoi | ||
Assigns attributes: times, solar_position, airmass, total_irrad, aoi | ||
""" | ||
|
||
self.times = times | ||
# Add columns that does not exist and overwrite existing columns | ||
# Maybe there is a more elegant way to do this. Any ideas? | ||
if weather is not None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be best for pvlib to only use a simple assignment. Users can do this in their own code before passing the parameter or making the assignment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
self.weather = weather | ||
|
||
# The following part could be removed together with the irradiance | ||
# parameter at version v0.5 or v0.6. | ||
# **** Begin **** | ||
wrn_txt = ("The irradiance parameter will be removed soon.\n" + | ||
"Please use the weather parameter to pass a DataFrame " + | ||
"with irradiance (ghi, dni, dhi), wind speed and " + | ||
"temp_air.\n") | ||
if irradiance is not None: | ||
warnings.warn(wrn_txt, FutureWarning) | ||
for column in irradiance.columns: | ||
self.weather[column] = irradiance[column] | ||
# **** End **** | ||
|
||
if times is not None: | ||
self.times = times | ||
|
||
self.solar_position = self.location.get_solarposition(self.times) | ||
|
||
|
@@ -637,12 +716,23 @@ def prepare_inputs(self, times, irradiance=None, weather=None): | |
self.aoi = self.system.get_aoi(self.solar_position['apparent_zenith'], | ||
self.solar_position['azimuth']) | ||
|
||
if irradiance is None: | ||
irradiance = self.location.get_clearsky( | ||
use_clearsky = False | ||
if self.weather is None: | ||
use_clearsky = True | ||
self.weather = pd.DataFrame() | ||
else: | ||
if not any([x in ['ghi', 'dni', 'dhi'] for x in self.weather.columns]): | ||
use_clearsky = True | ||
|
||
if use_clearsky: | ||
self.weather[['ghi', 'dni', 'dhi']] = self.location.get_clearsky( | ||
self.solar_position.index, self.clearsky_model, | ||
zenith_data=self.solar_position['apparent_zenith'], | ||
airmass_data=self.airmass['airmass_absolute']) | ||
self.irradiance = irradiance | ||
|
||
if not {'ghi', 'dni', 'dhi'} <= set(self.weather.columns): | ||
ValueError( | ||
"Uncompleted irradiance data set. Please check you input data") | ||
|
||
# PVSystem.get_irradiance and SingleAxisTracker.get_irradiance | ||
# have different method signatures, so use partial to handle | ||
|
@@ -670,35 +760,37 @@ def prepare_inputs(self, times, irradiance=None, weather=None): | |
self.solar_position['azimuth']) | ||
|
||
self.total_irrad = get_irradiance( | ||
self.irradiance['dni'], | ||
self.irradiance['ghi'], | ||
self.irradiance['dhi'], | ||
self.weather['dni'], | ||
self.weather['ghi'], | ||
self.weather['dhi'], | ||
airmass=self.airmass['airmass_relative'], | ||
model=self.transposition_model) | ||
|
||
if weather is None: | ||
weather = {'wind_speed': 0, 'temp_air': 20} | ||
self.weather = weather | ||
|
||
if self.weather.get('wind_speed') is None: | ||
self.weather['wind_speed'] = 0 | ||
if self.weather.get('temp_air') is None: | ||
self.weather['temp_air'] = 20 | ||
return self | ||
|
||
def run_model(self, times, irradiance=None, weather=None): | ||
def run_model(self, times=None, irradiance=None, weather=None): | ||
""" | ||
Run the model. | ||
|
||
Parameters | ||
---------- | ||
times : DatetimeIndex | ||
Times at which to evaluate the model. | ||
|
||
Times at which to evaluate the model. Can be None if attribute | ||
`times` is already set. | ||
irradiance : None or DataFrame | ||
If None, calculates clear sky data. | ||
Columns must be 'dni', 'ghi', 'dhi'. | ||
|
||
This parameter is deprecated. Please use `weather` instead. | ||
weather : None or DataFrame | ||
If None, assumes air temperature is 20 C and | ||
wind speed is 0 m/s. | ||
Columns must be 'wind_speed', 'temp_air'. | ||
If None, assumes air temperature is 20 C, wind speed is 0 m/s and | ||
irradiation calculated from clear sky data. | ||
Column names must be 'wind_speed', 'temp_air', 'dni', 'ghi', 'dhi'. | ||
Do not pass incomplete irradiation data. | ||
Use method | ||
:py:meth:`~pvlib.modelchain.ModelChain.complete_irradiance` | ||
instead. | ||
|
||
Returns | ||
------- | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for finding and fixing the typo in the ModelChain repr. You could add a note for that here, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was not clean to fix it within this PR but I was too lazy to do it separately. So I added this fix linking it to its commit. I guess there is no commit-role in your sphinx documentation similar to your issue-role, so it will not be a real link afterwards.