Skip to content

pvfactors limited implementation for bifacial calculations #635

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 29 commits into from
Jan 22, 2019

Conversation

anomam
Copy link
Contributor

@anomam anomam commented Dec 14, 2018

pvlib python pull request guidelines

Thank you for your contribution to pvlib python! You may delete all of these instructions except for the list below.

You may submit a pull request with your code at any stage of completion.

The following items must be addressed before the code can be merged. Please don't hesitate to ask for help if you're unsure of how to accomplish any of the items below:

  • Closes bifacial PV system modeling #421
  • I am familiar with the contributing guidelines.
  • Fully tested. Added and/or modified tests to ensure correct behavior for all reasonable inputs. Tests (usually) must pass on the TravisCI and Appveyor testing services.
  • Updates entries to docs/sphinx/source/api.rst for API changes.
  • Adds description and name entries in the appropriate docs/sphinx/source/whatsnew file for all changes.
  • Code quality and style is sufficient. Passes LGTM and SticklerCI checks.
  • New code is fully documented. Includes sphinx/numpydoc compliant docstrings and comments in the code where necessary.
  • Pull request is nearly complete and ready for detailed review.

Brief description of the problem and proposed solution (if not already fully described in the issue linked to above):
Implementation of a bifacial model using open-source pvfactors package.

@anomam
Copy link
Contributor Author

anomam commented Dec 14, 2018

I just realized that my IDE's autopep8 made a lot of automated changes... 😮 don't hesitate to let me know if that's an issue


Parameters
----------
solar_azimuth: numpy array of numeric
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rest of pvlib generally uses pandas.Series or pandas.Dataframes. If pvfactors must have np.array as input, can you do some type conversion in this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @cwhanse , I forgot about that convention. So I created a decorating function that does this (with a test for it) in order to separate the modeling logic from the inputs/outputs conversion logic. Let me know if that approach is okay with you

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does pvfactors fail with a Series or DataFrame?

In general, I like the decorator approach if we can make it robust enough to be used throughout pvlib. (Applying the decorator throughout pvlib should be done in a separate PR.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pvfactors has been tested with numpy arrays so far. But I can try to see if it would work with Series and DataFrames, with some luck duck-typing might work...

Understood; I did implement a test for the decorating function which checks multiple cases. But I can bring the type conversion into the pvfactors function if you prefer. Let me know


Returns
-------
front_poa_irradiance: numpy array of numeric
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output convention could be np.array if inputs are np.array, but pandas.Series if inputs are themselves pandas objects.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @cwhanse , as mentioned above, the decorating function should handle this request as well. Let me know what you think

@cwhanse
Copy link
Member

cwhanse commented Dec 14, 2018

@anomam Thanks for this!

I just realized that my IDE's autopep8 made a lot of automated changes... 😮 don't hesitate to let me know if that's an issue

Yes it is a bit of an issue, although most the changes are improvements. Including them makes it hard to review the scope of the PR when unrelated formatting changes are included. OK to address the formatting in a separate issue/PR with formatting as its scope.

@anomam
Copy link
Contributor Author

anomam commented Dec 17, 2018

Hi @cwhanse , thanks again for the initial feedback! I implemented some changes as requested and I think that this PR is getting closer to completion. If possible, I would appreciate some guidance on how to solve the stickler-ci and coverage check failures...

pvlib/tools.py Outdated
new_args.append(new_arg)
elif isinstance(arg, pd.DataFrame):
is_return_type_pandas = True
new_arg = arg.values.ravel() # make sure that 1D
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's better to raise an exception than allow a DataFrame --> 1D array --> Series pattern.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I removed the decorator function and implemented checks in the pvfactors function

Copy link
Member

@wholmgren wholmgren left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @anomam for considering our suggestions. This mostly looks good to me. I like the simplicity.


# Select the calculated outputs from the pvrow to observe
ipoa_front = df_outputs.loc[:, idx_slice[index_observed_pvrow,
'front', 'qinc']].values
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps only a question because I'm not familiar enough with pvfactors, but why extract .values instead of returning the Series?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just believed that having a 1D numpy array was simpler for these results, but I can adjust it to pvlib's needs, just let me know!

@cwhanse
Copy link
Member

cwhanse commented Dec 19, 2018

@anomam let me know when you are done with cleanup changes.

One issue is still open in my mind: does bifacial.pvfactors_timeseries return a pandas object (when inputs are pandas) or always return an array (the latter, I think)?

@anomam
Copy link
Contributor Author

anomam commented Dec 20, 2018

Thank you so much for the time you spent on this @cwhanse @wholmgren

@cwhanse, from @wholmgren comments above I got the sense that returning 1D arrays was good, but please don't hesitate to let me know if you prefer pandas series (when the inputs are also pandas series)

I'll take a look again tomorrow (Japan time) to check for any necessary clean up or adjustments

@wholmgren
Copy link
Member

@cwhanse, from @wholmgren comments above I got the sense that returning 1D arrays was good, but please don't hesitate to let me know if you prefer pandas series (when the inputs are also pandas series)

Sorry, I didn't fully understand the inputs/outputs and discussions (still might not). After looking more carefully, I suggest that the outputs always be pandas Series and DataFrames. My rationale is that

  • the function is specifically meant for timeseries analysis
  • the function requires input datetime information (optionally as a DatetimeIndex)
  • the function always returns a DataFrame for one of its outputs
  • the returned DataFrame always contains a timeseries column (at least that's my understanding)

Unlike other functions in pvlib that are more flexible, here we require users to handle at least one pandas object (the DataFrame) and we know the timestamps that each row corresponds to. So, I suggest that we always return the two Series with the appropriate DatetimeIndex. My understanding is that the DataFrame would need MultiIndex with (row, timestamp). I think this works: df_registries.set_index(['pvrow', 'timestamp']).

@requires_pvfactors
def test_pvfactors_timeseries_pandas_inputs():
""" Test that pvfactors is functional, using the TLDR section inputs of the
package github repo README.md file, but converted to pandas Series"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

link to this would be helpful

horizon_band_angle=horizon_band_angle,
run_parallel_calculations=False, n_workers_for_parallel_calcs=None)

np.testing.assert_allclose(ipoa_front, expected_ipoa_front,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should use the pandas test functions if we adopt the always return a Series approach


Inputs
------
solar_azimuth: numeric (list, numpy array, or pandas Series)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to only document the input type as numeric (no (list...)). Like it or not, it's consistent with the rest of pvlib.

@wholmgren
Copy link
Member

I'd like see the PR finished early next week or pushed to 0.6.2. I think we're pretty close, but we need to get 0.6.1 out and this (understandably) has not been touched in awhile.

@anomam
Copy link
Contributor Author

anomam commented Jan 19, 2019

Hi @wholmgren , sorry for the long delay, I'm still on my way back from a lot of travel but I will wrap it up early next week. When is the 0.6.1 release?

@anomam
Copy link
Contributor Author

anomam commented Jan 21, 2019

Hi @wholmgren , I updated the function to return pandas Series and I fixed the docstrings as requested. Let me know if it doesn't look like what you expected. Thanks again for your time

@cwhanse
Copy link
Member

cwhanse commented Jan 21, 2019

LGTM. @wholmgren ?

Copy link
Member

@wholmgren wholmgren left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @anomam. I think we only need to make a minor change to the whatsnew.

@@ -82,6 +84,7 @@ Testing
~~~~~~~
* Add test for :func:`~pvlib.solarposition.hour_angle` (:issue:`597`)
* Update tests to be compatible with pytest 4.0. (:issue:`623`)
* Add tests for :py:func:`pvlib.bifacial.pvfactors_timeseries` implementation and :py:func:`pvlib.tools.enforce_numpy_arrays` decorator function (:issue:`421`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The enforce_numpy_arrays section is outdated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, done in 55dd3a6

@wholmgren wholmgren merged commit 0486c3b into pvlib:master Jan 22, 2019
@wholmgren
Copy link
Member

Great to see bifacial modeling in pvlib - thanks @anomam!

@anomam
Copy link
Contributor Author

anomam commented Jan 22, 2019

Thank you so much for your help and time spent on this @wholmgren @cwhanse !
I hope to see more bifacial models getting pvlib'ed as well ☀️

@wholmgren wholmgren added this to the 0.6.1 milestone Jan 22, 2019
Comment on lines +13 to +14
rho_front_pvrow=0.03, rho_back_pvrow=0.05,
horizon_band_angle=15.,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anomam do you happen to remember why you chose this particular default value for horizon_band_angle? From what I can tell in the git history, the analogous default on the pvfactors side was 6.5 (both at the time of this PR and today) rather than 15. I know this PR is ancient history at this point so I'm not expecting much, just curious :)

There are now some small differences between this wrapper and pvfactors itself in the rho_* parameters as well, but I think those were only introduced later on after this PR was merged.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey @kanderso-nrel ! It was a long time ago so I'm not entirely sure anymore, but what I remember is that these values might have needed a bit of tuning to match the measurements depending on the sites etc. I think for the horizon band it might be safe to check what the Perez paper says about what value to use.
For the reflectivity parameter values, it's something I actually never really had time to study in depth. I think the default values for the PV rows were low enough to not have much impact, but that's probably not accurate in all cases...
Sorry if my answers are vague, I think getting better ones would require more work/studies/experience...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants