9 various tidy-ups and loud failing - #430
Conversation
| """ | ||
|
|
||
| @override | ||
| def __getattr__(self, item: str) -> NWP: |
There was a problem hiding this comment.
we don't use this and don't need it
| return iter(self.root) | ||
|
|
||
| def keys(self) -> Iterator[str]: | ||
| def keys(self) -> KeysView[str]: |
There was a problem hiding this comment.
the old type hints were wrong
| if time_periods is not None: | ||
| mask = get_time_periods_mask(valid_t0_times, time_periods) | ||
| if not mask.any(): | ||
| raise ValueError(f"`time_periods` {time_periods} excluded all valid t0 times") |
There was a problem hiding this comment.
We raise this here instead of letting the dataset be empty and raise later further away from the source
| ) | ||
|
|
||
| if len(valid_t0_times) == 0: | ||
| raise ValueError( |
There was a problem hiding this comment.
This catches a separate error where there are some time periods available but none intersect with the t0 resolution. As in we could have a time period 00:10 -> 00:20 but if we have time resolution 30mins then we get no valid t0s
There was a problem hiding this comment.
Was always silent / empty before right? Good one!
| return valid_t0_times | ||
|
|
||
| @staticmethod | ||
| def find_valid_t0_and_location_ids( |
There was a problem hiding this comment.
I just did a bit of refactoring and cleaning up in this function
| valid_t0_per_location["location_id"] = location.id | ||
| valid_t0_and_location_ids.append(valid_t0_per_location) | ||
| if len(valid_t0_times) == 0: | ||
| logger.warning(f"No valid t0 times found for location {location.id}") |
There was a problem hiding this comment.
I think this is good to warn about since the model could silently train without ever seeing this location
There was a problem hiding this comment.
This could have been an error but maybe that's too strict
| ## Documentation | ||
|
|
||
| **ocf-data-sampler** doesn't have external documentation _yet_; you can read a bit about how our torch datasets work in the README [here](ocf_data_sampler/torch_datasets/README.md). | ||
| **ocf-data-sampler** doesn't have external documentation _yet_; you can read a bit about how our torch datasets work in the README [here](src/ocf_data_sampler/datasets/pvnet/README.md). |
| def __setstate__(self, state: dict) -> None: | ||
| """Restore object from pickle, reloading from presaved file if possible.""" | ||
| self.__dict__.update(state) | ||
| if self._pickle_path and os.path.exists(self._pickle_path): |
There was a problem hiding this comment.
There was a chance here that this would fail weirdly if the pickled dataset was deleted or unavailable. So we handle this more explicitly now
| max_staleness=max_staleness, | ||
| ) | ||
|
|
||
| if len(time_periods) == 0: |
There was a problem hiding this comment.
The find_contiguous_t0_periods[_nwp] functions raise their own errors if no periods are found, so we never reach these
There was a problem hiding this comment.
Not reaching these was a bug, but perhaps we want to reach these. But that would require us to define what find_contiguous_t0_periods[_nwp] returns if there are no time periods. Is it just an empty dataframe?
| for start_time, end_time in time_periods: | ||
|
|
||
| start_time = times[0] if start_time is None else np.datetime64(start_time) | ||
| end_time = times[-1] if end_time is None else np.datetime64(end_time) |
There was a problem hiding this comment.
The new version is slightly more robust and general since it doesn't rely on times being sorted and the [-1] indexer working on whatever input type goes in. This is so marginal that I'd wonder if its worth the code churn, so I'm happy to revert if we want.
One change here that we should have had is to be exclusive of the end point. A common pattern would be
train_period=[(None, "2025-01-01 00:00")]
val_period=[("2025-01-01 00:00", None)]
This stops both train and val from containing the "2025-01-01 00:00" t0 time
| "date_cos": np.cos(date_in_radians), | ||
| "time_sin": np.sin(time_in_radians), | ||
| "time_cos": np.cos(time_in_radians), | ||
| "date_sin": np.sin(date_in_radians).astype(np.float32), |
There was a problem hiding this comment.
These were returning float64 which is not what the function signature advertises. We also cast to float32 for the TensorBatch passed to the model
| ("2023-01-01 12:00", "2023-01-01 13:00"), | ||
| ], | ||
| ) | ||
| expected_mask = np.array([False, True, True, True, False, True, True, True]) |
There was a problem hiding this comment.
The end point is now exclusive
Clarified randomness behavior in README regarding dropout and NumPy state.
| return da | ||
|
|
||
|
|
||
| def _assert_steps_uniformly_spaced(steps: NDArray[np.timedelta64], provider: str) -> None: |
There was a problem hiding this comment.
This will cause a hard fail with uneven steps say for MO right?
| mask = get_time_periods_mask(valid_t0_and_location_ids["t0"], time_periods) | ||
| valid_t0_and_location_ids = valid_t0_and_location_ids[mask] | ||
| mask = get_time_periods_mask(valid_t0_and_location_ids["t0"].values, time_periods) | ||
| if not mask.any(): |
|
|
||
| # Each init-time is unusable before init_start_timedelta and after init_end_timedelta. If they | ||
| # are the wrong way round then no t0 can ever use it, and every period below will be empty | ||
| if init_end_timedelta < init_start_timedelta: |
There was a problem hiding this comment.
Solid one, clear flagging
| Returns: | ||
| The selected DataArray-like slice. | ||
| """ | ||
| if len(locations) == 0: |
There was a problem hiding this comment.
For any window inversion errors right?
felix-e-h-p
left a comment
There was a problem hiding this comment.
Thanks for this! Looking great. Think the one thing from me would be if the uniformly spaced steps assertion could reject archives, but all good asides that.
Pull Request
Description
This PR wraps up a lot of small changes mainly aimed at the code failing early and raising helpful error messages
Checklist: