Skip to content

Conversation

@zhsain
Copy link

@zhsain zhsain commented Sep 11, 2025

New example notebook

PR Checklist

  • RELEASE.md has been updated to describe the changes made in this PR
  • Documentation
    • Docstrings are up-to-date
    • Related docs/ files are up-to-date, or added when necessary
    • Documentation has been rebuilt successfully
    • Examples have been updated
  • Tests pass (If not, and this is expected, please elaborate in the tests section)
  • PR description thoroughly describes the new feature, bug fix, etc.

Related issues

Impacted areas of the software

  • examples/12-worldwide-multi-location-example.ipynb
    • method1: Run HOPP for multiple locations sequentially while maintaining the same hybrid plant configuration.
    • method2: Easy import of solar data through NREL API.
    • method3: Easy import of wind data through Open-Meteo API. This enables HOPP to be used for any location around the worlds since the Open-Meteo dataset has global coverage compared to the limited coverage of the NREL Wind Resource Database (WRDB).
    • method4: Conversion of Open-Meteo wind data to a HOPP-friendly format that is similar to the one provided by the NREL Wind Resource Database (WRDB).
  • examples/inputs/west_africa_coordinates.xlsx
    • method1: An excel file containing coordinates for 50 locations in west Africa. This area of the world is not covered by the NREL WRDB, so these locations make the example more pertinent.

Additional supporting information

The main contribution of this new example is to expand HOPP's geographic reach.

Test results, if applicable

No changes were made to HOPP's code.

@review-notebook-app
Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@zhsain zhsain changed the title Develop New example to expand HOPP's geographic reach Sep 11, 2025
@@ -0,0 +1,602 @@
{
Copy link
Collaborator

@elenya-grant elenya-grant Sep 29, 2025

Choose a reason for hiding this comment

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

The api setting method could be replaced with the method that's used in other examples:

from hopp.utilities.keys import set_nrel_key_dot_env
# Set API key using the .env
set_nrel_key_dot_env()


Reply via ReviewNB

@@ -0,0 +1,602 @@
{
Copy link
Collaborator

@elenya-grant elenya-grant Sep 29, 2025

Choose a reason for hiding this comment

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

Line #5.    def nrel_query(lat, lon, name, solar_output_dir):

suggestion to add a variable to the input that specifies what tmy they want, then check that its one of the following valid options: ['tmy', 'tmy-2014', 'tmy-2022'] (see below)

def nrel_query(lat, lon, name, solar_output_dir, year:str):
if year not in ['tmy','tmy-2014','tmy-2022']:
  raise ValueError(f"{year} is not valid TMY year for this resource set. Please set year as either 'tmy','tmy-2014', or 'tmy-2022'")
    

Reply via ReviewNB

@@ -0,0 +1,602 @@
{
Copy link
Collaborator

@elenya-grant elenya-grant Sep 29, 2025

Choose a reason for hiding this comment

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

Line #8.        NSRDB_URL = f"https://developer.nrel.gov/api/nsrdb/v2/solar/nsrdb-msg-v1-0-0-tmy-download.csv?api_key={api_key}&wkt=POINT({lat} {lon})&names=tmy-2022&utc=false&leap_day=false&interval=60&email={email_address}"

You don't have to specify each attribute, it will by default download all of them. You could do this instead^

And if you make 'year' an input, this could be modified to be:

NSRDB_URL = f"https://developer.nrel.gov/api/nsrdb/v2/solar/nsrdb-msg-v1-0-0-tmy-download.csv?api_key={api_key}&wkt=POINT({lat} {lon})&names={year}&utc=false&leap_day=false&interval=60&email={email_address}"

Another suggestion is to use HOPP's built in method of setting API keys:

from hopp.utilities.keys import set_nrel_key_dot_env
from hopp.utilities.keys import get_developer_nrel_gov_key, get_developer_nrel_gov_email

# at the start of the script, set the API key
set_nrel_key_dot_env()

# to make the URL, you can instead use:
email_address = get_developer_nrel_gov_email()
api_key = get_developer_nrel_gov_key()


NSRDB_URL = f"https://developer.nrel.gov/api/nsrdb/v2/solar/nsrdb-msg-v1-0-0-tmy-download.csv?api_key={api_key}&wkt=POINT({lat} {lon})&names={year}&utc=false&leap_day=false&interval=60&email={email_address}"


Reply via ReviewNB

Copy link
Author

Choose a reason for hiding this comment

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

I added a 'year' variable for each of the wind and solar datasets, and edited the NREL API set-up to use the built-in method

@@ -0,0 +1,602 @@
{
Copy link
Collaborator

@elenya-grant elenya-grant Sep 29, 2025

Choose a reason for hiding this comment

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

Line #7.    def openmeteo_query(lat, lon, name, wind_output_dir):

this is a super cool and useful function! Great way to expand wind resource to other locations!


Reply via ReviewNB

Copy link
Author

Choose a reason for hiding this comment

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

Thank you!

@@ -0,0 +1,602 @@
{
Copy link
Collaborator

@elenya-grant elenya-grant Sep 29, 2025

Choose a reason for hiding this comment

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

Line #2.    def convert_to_srw(input_filepath, output_dir):

this method looks super helpful! I could see this going into a "tools" file within hopp/simulation/technologies/resource


Reply via ReviewNB

@@ -0,0 +1,602 @@
{
Copy link
Collaborator

@elenya-grant elenya-grant Sep 29, 2025

Choose a reason for hiding this comment

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

Line #3.    def yaml_modifier(file_path, new_lat, new_lon, solar_file, wind_file):

this also looks like a useful function! I wonder if there's a way to generalize this method to handle a variety of inputs to change and then the generalized version could live in hopp/utilities/utilities.py . Does this functionality only exist with ruamel.yaml or can it be done with the normal yaml package?


Reply via ReviewNB

Copy link
Author

Choose a reason for hiding this comment

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

I used both ruamel.yaml and yaml, and I found the former a little bit easier to use. But that's just my own preference, both could work.

@elenya-grant elenya-grant self-requested a review September 29, 2025 19:56
Copy link
Collaborator

@elenya-grant elenya-grant left a comment

Choose a reason for hiding this comment

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

This example includes so much (very cool) added functionality! I think that a lot of this should be incorporated into HOPP outside of just this example. I'd love to see some of this functionality incorporated into the core functionality of HOPP if possible! Thank you so much for this awesome example! This adds a lot of value to HOPP as a tool!

Some overall thoughts:

  • west_africa_coordinates.xlsx: could this be converted to a .csv instead? Just so it's easier to see in a text editor?
  • nrel_query(): this could be added as a new solar resource class, very similar to SolarResource in hopp/simulation/technologies/resource/solar_resource.py with a modified BASE_URL and year input.
  • openmeteo_query(): this could be added as a new wind resource class, perhaps it may be somewhat similar (besides the download code and url stuff) as hopp/simulation/technologies/resource/bchrrr_wind.py
  • convert_to_srw(): I wonder if any methods that exist in hopp/tools/resource/pysam_wind_tools.py would be useful for converting the openmeteo data to the .srw format (like the csv_to_srw() method).
  • yaml_modifier(): is there any reason to make a new .yaml file for each site? An alternative could be to just update a dictionary within the loop in hopp_simulation():
from hopp.utilities import load_yaml
def hopp_simulation(coord_file, default_yaml_file, solar_dir, wind_dir, hopp_dir):
hopp_config = load_yaml(default_yaml_file)
   for idx in RANGE:
      hopp_config["site"]["data"]["lat"] = LAT
      hopp_config["site"]["data"]["lon"] = LON
      hopp_config['site']['solar_resource_file'] = SOLAR_FILE
      hopp_config['site']['wind_resource_file'] = CONVERTED_WIND_FILE

@zhsain zhsain marked this pull request as ready for review November 13, 2025 21:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants