Fix WeatherDataset boundary checks for analysis indexing and forecast forcing horizon (Fixes #311, Closes #319)#312
Conversation
|
Ready for review. Happy to make any requested adjustments. |
Co-developed the forcing-bounds equation using @Jayant-kernel's detailed breakdown in issue 319!
Co-developed the forcing-bounds equation using @Jayant-kernel's detailed breakdown in issue 319!
Updated the changelog to clarify fixes in WeatherDataset and other issues.
|
Update: I’ve integrated the related forecast-boundary validation from #319 into this PR, so This PR now includes:
@sadamov @Jayant-kernel please let me know if you’d prefer this split, otherwise this PR should close both #311 and #319 on merge. |
|
@sadamov @leifdenby can someone pls review the PR :) thanks |
|
@sadamov Hey sir :), was just pinging to request u to review when you have time. Have regression tests done. If you need me to perform any cleanups or any another changes let me know :) thanks |
|
@sadamov Please if you get time, do review 😸 |
sadamov
left a comment
There was a problem hiding this comment.
@kshirajahere Thanks alot, this has indeed been a bug. And the fact that datasets were silently truncated is certainly not great. I agree with your suggested fixes and only request a reduction on lines of code, because we know that forcing and state share temporal dimensions.
Because this fix has some importance and you introduced 3 new tests I am asking for a second review as well. I prefer a third pair of eyes before merging a bugfix of this size.
| # If forcing data is present, also validate that the complete | ||
| # forcing window can be constructed for each autoregressive target | ||
| # step without truncation. | ||
| if self.da_forcing is not None: | ||
| required_forcing_steps = ( | ||
| max(2, self.num_past_forcing_steps) | ||
| + self.ar_steps | ||
| + self.num_future_forcing_steps | ||
| ) | ||
| n_forcing_forecast_steps = ( | ||
| self.da_forcing.elapsed_forecast_duration.size | ||
| ) | ||
| if n_forcing_forecast_steps < required_forcing_steps: | ||
| raise ValueError( | ||
| "The number of forcing forecast steps available " | ||
| f"({n_forcing_forecast_steps}) is less than the " | ||
| f"required {required_forcing_steps} " | ||
| f"(max(2, num_past_forcing_steps={self.num_past_forcing_steps})" | ||
| f" + ar_steps={self.ar_steps} + " | ||
| f"num_future_forcing_steps={self.num_future_forcing_steps}) " | ||
| "for constructing forcing windows." | ||
| ) |
There was a problem hiding this comment.
Both da_state and da_forcing are always built from the same datastore time coordinates, so their sizes are guaranteed to be equal and a separate shape check is not needed. The single forecast-mode check is still necessary, but only because the required minimum size is larger when forcing is present (+ num_future_forcing_steps), not because the arrays could ever differ in size.
The no-forcing path can remain unchanged in behaviour; the with-forcing path should skip the redundant state check and goes straight to the stricter (and sufficient) forcing constraint.
There was a problem hiding this comment.
I removed the redundant separate forcing-size check and now use the shared forecast horizon once:
- no-forcing path keeps the original
2 + ar_stepsbehavior - with-forcing path applies the stricter minimum needed for the full forcing window
Re-ran:
- pytest -q tests/test_datasets.py -k "dataset_length or out_of_bounds or forecast_len"
- ruff check neural_lam/weather_dataset.py tests/test_datasets.py
| # Match Python sequence semantics for negative indexing. | ||
| if idx < 0: | ||
| idx += dataset_len | ||
| if idx < 0 or idx >= dataset_len: | ||
| raise IndexError( | ||
| f"Index {idx} is out of bounds for dataset of size " | ||
| f"{dataset_len}" | ||
| ) | ||
|
|
There was a problem hiding this comment.
I was at first conflicted about this change, because it only affects the analysis type data, and only if accessed programmatically e.g. from a test. And I thought that it might rather be separate issue.
But, after consideration, I think this fits well within this PR. And knowing that there is more flexibility and robustness needed when we introduce #138 boundary datastores, this is good. Nothing to change here, just some context.
|
Hey @sadamov Can u rereview. I have reduced the forecast-mode validation. |
sadamov
left a comment
There was a problem hiding this comment.
Looks good now! Just waiting for @joeloskarsson review and then we can merge
|
@joeloskarsson pinging for review :) |
|
Was going thru the code after pinging @joeloskarsson for the review on slack 😅 and found some gaps (fixed them) |
|
@joeloskarsson i request you to please review my PR :) |
sadamov
left a comment
There was a problem hiding this comment.
your latest commits did not break anything since my last review. thanks for notifying me
|
Thanks @sadamov, just waiting for @joeloskarsson review so i can make those changes and we can merge this 🚀 |
Route pull_request GPU matrix jobs to ubuntu-latest so they no longer wait 24 hours for an unavailable Cirun runner. Keep Cirun on push and workflow_dispatch, and only use the NVMe-specific pip GPU setup on the self-hosted path.
This reverts commit e554aa8.
|
Heads-up: the two GPU checks are stuck in queue again (Cirun runner availability). Everything else is green. Could a maintainer re-run checks once the Cirun pool is free? If you prefer, I can re-run them too once the runner frees up. |
Describe your changes
WeatherDataset.__len__(off-by-one correction).WeatherDataset.__getitem__:IndexErrorfor out-of-range indices.WeatherDataset.__len__so forcing windows cannot overrun available forecast steps.## [unreleased] -> ### Fixed.Issue Link
Fixes #311
Closes #319
Type of change
Checklist before requesting a review
pullwith--rebaseoption if possible).Checklist for reviewers
Each PR comes with its own improvements and flaws. The reviewer should check the following:
Author checklist after completed review
reflecting type of change (add section where missing):
Checklist for assignee