Repository navigation
Resource resampling - #893
jaredthomas68 wants to merge 21 commits into
Conversation
jaredthomas68
left a comment
There was a problem hiding this comment.
Lots of what I'm seeing looks very similar to what I have, but with an improved interface and excluding the sampling
elenya-grant
left a comment
There was a problem hiding this comment.
Hi Jared! Thanks for making this PR! I left a few small comments but nothing major. My main questions is why have resample_resource_data_to_dt() called in process_final_resource_data() instead of in get_data_for_year() before the return statements? I see a few possible benefits to calling resample_resource_data_to_dt in get_data_for_year() instead:
- If user provided filenames, then the files can have different timesteps. Does your approach work if part of the time index has a timestep of 1 hour and another part has a time index of 30 minutes?
- If a user is running non-consecutive years for a multi-year simulation, then would this still work? Like - what happens with the sampling if the 'year' goes from 2012 to 2011 at hour 8761?
I suppose the downside (pretty big one) is that it couldn't interpolate between years. But - maybe that bit could be done in process_final_resource_data()?
(Also - I'm sorry if this suggestion isn't accurate/makes sense - I'm trying to submit this review by EOD so I haven't taken a deep look at the tests you added yet - but I will later and edit this comment as needed)
I'm going to do a deeper-review shortly but wanted to give you my initial thoughts! thanks for making this PR jared!
|
|
||
| API resource data may have a different native timestep from the simulation, but H2I does not resample it by default. You may explicitly choose a pandas interpolation method for upsampling or a pandas aggregation method for downsampling in the resource's `resource_parameters`. | ||
|
|
||
| Set `upsample_method` or `downsample_method` in `resource_parameters` to explicitly select the pandas operation. If the data timestep and simulation timestep already match, neither setting is needed. When resampling is requested, H2I emits a warning naming the source timestep, target timestep, direction, and method. If a mismatch requires resampling but no corresponding method is set, H2I raises an error. See {py:func}`h2integrate.resource.utilities.time_tools.resample_resource_data_to_dt` for method details. |
There was a problem hiding this comment.
could you add a link to the pandas doc-page for the relevant methods so folks can easily see what sampling methods are available?
| data, start_timestamp, dt_seconds, n, present_time_keys, exclude_leap_day=False | ||
| ): | ||
| """Regenerate time columns as ``n`` steps of ``dt_seconds`` starting at a timestamp. | ||
There was a problem hiding this comment.
can you add the Args and Returns parts to this doc string?
| - **resource_year_setting** (*str*, optional): How resource years are selected for | ||
| API datasets. Options include ``start_year``, ``year_order``, and ``filenames``. |
There was a problem hiding this comment.
remove resource_year_setting (probably left-over from merge)
| dict: resource_data after final processing and checks | ||
| """ | ||
| # NOTE: we could up/downsample here also | ||
| # Remove leap day (if needed) on the native data, resample to the simulation |
There was a problem hiding this comment.
could you update the doctoring for process_final_resource_data to include the resample step?
| """ | ||
| # NOTE: we could up/downsample here also | ||
| # Remove leap day (if needed) on the native data, resample to the simulation | ||
| # timestep, then clip to the number of timesteps requested by the simulation. |
There was a problem hiding this comment.
if you leave this inline comment, can you move "then clip to the number of timesteps requested by the simulation." to the line above clip_data_to_n_timesteps() instead?
There was a problem hiding this comment.
I just removed the comment. It is redundant with the doc string
| return data | ||
|
|
||
|
|
||
| def resample_resource_data_to_dt( |
There was a problem hiding this comment.
I'm curious how this works for TMY datasets?
There was a problem hiding this comment.
idk how it works or if it works as intended but it doesnt raise any errors when I tested it...
There was a problem hiding this comment.
This works through the existing exclude_leap_day = spans_leap_year and not has_feb29 check. A TMY whose months come from leap years but has no Feb 29 is treated as "leap day removed", so the regenerated calendar skips it. Year column: for mixed-year TMY (e.g. Jan 2005, Feb 2012, …), the regenerated year column becomes the first sample's year for the whole series. The original per-month years are lost. Anything that relies on the original year labels will no longer see them. I don't think any additional tests are needed.
There was a problem hiding this comment.
I also don't think the loss of the per-month years is a problem since we are not using that information anywhere.
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
5 open findings
With resampling now able to produce coarse timesteps (e.g., multi-daydt),… · New Usinground(...)to computetarget_ncan round down when the ratio is not an integer (or due to… · Newresource_filenameis widened to... | listbut the list element type is unspecified, which… · Newresource_filenameis widened to... | listbut the list element type is unspecified, which… · New_make_timeseriesis a test helper (not a collected test), but it is marked with… · New
What changed in this PR
This PR adds opt-in resource data resampling so resource timeseries can be upsampled/downsampled to the simulation timestep using pandas interpolation/aggregation, including leap-day-aware timestamp regeneration.
Changes:
- Add
resample_resource_data_to_dtutility (with warnings + required explicit method selection) and integrate it into resource final-processing. - Update configs/tests/docs to support explicit
upsample_method/downsample_method, and expand wind API config to accept filename lists. - Minor validation/doc/changelog updates related to timestep handling and resampling behavior.
| File | Description |
|---|---|
| h2integrate/resource/wind/nlr_developer_wtk_api_models.py | Allow resource_filename to be a list for multi-year wind inputs. |
| h2integrate/resource/utilities/time_tools.py | Implement resampling helper + leap-aware time-column regeneration and warnings. |
| h2integrate/resource/utilities/test/test_time_tools.py | Add unit tests for resampling behavior, leap-day handling, warnings, and error paths. |
| h2integrate/resource/test/test_resource_api_baseclass.py | Adjust test configs to explicitly set resampling methods; fix synthetic timestamp minutes. |
| h2integrate/resource/test/conftest.py | Ensure integration-test configs explicitly set resampling methods. |
| h2integrate/resource/resource_baseclass.py | Wire resampling into process_final_resource_data before clipping and validation. |
| h2integrate/core/inputs/validation.py | Replace magic number with formatted seconds-per-year constant. |
| docs/resource/resource_index.md | Document explicit resampling configuration and warning/error behavior. |
| CHANGELOG.md | Add unreleased entry describing resampling capability. |
🧠 Review effort: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…ntain and use ceiling instead of round for determing the number of timesteps required
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
3 open findings
5 resolved since last review
With resampling now able to produce coarse timesteps (e.g., multi-daydt),…resource_filenameis widened to... | listbut the list element type is unspecified, which…resource_filenameis widened to... | listbut the list element type is unspecified, which… Usinground(...)to computetarget_ncan round down when the ratio is not an integer (or due to…_make_timeseriesis a test helper (not a collected test), but it is marked with…
🧠 Review effort: Lite
| # Native timestep is taken from the first two samples so a calendar gap (such as a | ||
| # removed leap day) does not distort it. | ||
| native_dt = (calendar_index[1] - calendar_index[0]).total_seconds() |
| resource_type: str = field(default="none", init=False) | ||
| resource_data: dict | object = field(default={}) | ||
| resource_filename: Path | str | list = field(default="") | ||
| resource_filename: Path | str | list[Path | str] = field(default="") |
| periods = n_timesteps | ||
| new_index = pd.date_range(start=start_timestamp, periods=periods, freq=freq) | ||
| new_index = new_index[~((new_index.month == 2) & (new_index.day == 29))] | ||
| while len(new_index) < n_timesteps: | ||
| periods += (n_timesteps - len(new_index)) + 1 | ||
| new_index = pd.date_range(start=start_timestamp, periods=periods, freq=freq) |



Resource-resampling compatible with non-annual resource handling
The work in this PR is also included in #887. This PR splits out the resource-specific changes in #887 that are not already addressed in #897.
This PR contains changes up-sampling and down-sampling data to desired time step (using pandas methods)
Section 1: Type of Contribution
Section 2: Draft PR Checklist
TODO:
Type of Reviewer Feedback Requested (on Draft PR)
Structural feedback:
Implementation feedback:
Other feedback:
Section 3: General PR Checklist
docs/files are up-to-date, or added when necessaryCHANGELOG.md"A complete thought. [PR XYZ]((https://github.com/NatLabRockies/H2Integrate/pull/XYZ)", where
XYZshould be replaced with the actual number.Section 4: Related Issues
Resolves #651
Section 5: Impacted Areas of the Software
Section 5.1: New Files
Section 5.2: Modified Files
resource_index.mdvalidation.pyresource_baseclass.pyconftest.pytest_resource_api_baseclass.pytest_time_tools.pytime_tools.pynlr_developer_wtk_api_models.pySection 6: Additional Supporting Information
Section 7: Test Results, if applicable
Section 8 (Optional): New Model Checklist
docs/developer_guide/coding_guidelines.mdattrsclass to define theConfigto load in attributes for the modelBaseConfigorCostModelBaseConfiginitialize()method,setup()method,compute()methodCostModelBaseClass__init__.pyfile to ensure it is properly imported and used insupported_models.pysupported_models.pycreate_financial_modelinh2integrate_model.pytest_all_examples.pydocs/user_guide/model_overview.mddocs/section<model_name>.mdis added to the_toc.ymlgenerate_class_hierarchy.pyto update the class hierarchy diagram indocs/developer_guide/class_structure.md