-
Notifications
You must be signed in to change notification settings - Fork 12
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
Fix add_bounds()
breaking when time coords are cftime
objects
#241
Conversation
- Remove `dataset` param from `TemporalAccessor.center_times()` to allow for standalone usage - Update names of tests for private functions in `test_dataset.py`
xcdat/bounds.py
Outdated
# Add beginning and end points to account for lower and upper bounds. | ||
# np.array of string values with `dtype="timedelta64[ns]"` | ||
diffs = np.insert(diffs, 0, diffs[0]) | ||
diffs = np.append(diffs, diffs[-1]) | ||
|
||
# Get lower and upper bounds by using the width relative to nearest point. | ||
# Transpose both bound arrays into a 2D array. | ||
lower_bounds = da_coord - diffs[:-1] * width | ||
upper_bounds = da_coord + diffs[1:] * (1 - width) | ||
# In xarray and xCDAT, time coordinates with non-CF compliant calendars | ||
# (360-day, noleap) and/or units ("months", "years") are decoded using | ||
# `cftime` objects instead of `datetime` objects. `cftime` objects only | ||
# support arithmetic using `timedelta` objects, so the values of `diffs` | ||
# must be casted from `dtype="timedelta64[ns]"` to `timedelta`. | ||
if da_coord.name in ("T", "time") and issubclass( | ||
type(da_coord.values[0]), cftime.datetime | ||
): | ||
diffs = pd.to_timedelta(diffs) | ||
|
||
# FIXME: These lines produces the warning: `PerformanceWarning: | ||
# Adding/subtracting object-dtype array to TimedeltaArray not | ||
# vectorized` after converting diffs to `timedelta`. I (Tom) was not | ||
# able to find an alternative, vectorized solution at the time of this | ||
# implementation. | ||
with warnings.catch_warnings(): | ||
warnings.simplefilter("ignore", category=pd.errors.PerformanceWarning) | ||
lower_bounds = da_coord - diffs[:-1] * width | ||
upper_bounds = da_coord + diffs[1:] * (1 - width) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The primary code change
if hasattr(self, "_time_bounds") is False: | ||
self._time_bounds = ds.bounds.get_bounds("time") | ||
ds = self._dataset.copy() | ||
time_bounds = ds.bounds.get_bounds("time") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This update to center_times()
makes it callable as a standalone method, instead of having to pass a dataset object to it. (from ds.temporal.center_times(ds)
to ds.temporal.center_times()
)
Codecov Report
@@ Coverage Diff @@
## main #241 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 9 8 -1
Lines 742 728 -14
=========================================
- Hits 742 728 -14
Continue to review full report at Codecov.
|
Description
add_bounds()
breaks when time coordinates are incftime
objects instead ofdatetime
#240Summary of Changes
add_bounds()
breaking when time coords arecftime
objectsds
as a keyword arg forTemporalAccessor.center_times()
to allow for standalone usagetest_temporal.py
with masked dataChecklist
pd.PerformanceWarning
. There is a#FIXME
comment to address this in the future.If applicable: