Skip to content
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

[PR] time type conversion to timedelta if timedelta64 is given #660

Merged
merged 6 commits into from
Jun 10, 2024

Conversation

lee1043
Copy link
Collaborator

@lee1043 lee1043 commented Jun 6, 2024

Description

make sure time diff type is timedelta: in case it was timedelta64 convert it, so following .seconds line could run without error

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • My changes generate no new warnings
  • Any dependent changes have been merged and published in downstream modules

If applicable:

  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass with my changes (locally and CI/CD build)
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have noted that this is a breaking change for a major release (fix or feature that would cause existing functionality to not work as expected)

@lee1043 lee1043 self-assigned this Jun 6, 2024
Copy link

codecov bot commented Jun 6, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (9ad91a0) to head (189e526).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #660   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           15        15           
  Lines         1542      1544    +2     
=========================================
+ Hits          1542      1544    +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Collaborator

@pochedls pochedls left a comment

Choose a reason for hiding this comment

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

@lee1043 - thanks for creating this issue and PR. Even though this was solved with use_cftime=True, I think this is an issue because this functionality should work with np.datetime64 axes.

I have a minor comment that I'm not really sure about the answer to (I'm curious about your opinion and @tomvothecoder's opinion).

xcdat/bounds.py Outdated
Comment on lines 606 to 609
diff = pd.to_timedelta(time.values[1] - time.values[0])
# `cftime` objects only support arithmetic using `timedelta` objects, so
# the values of `diffs` must be casted from `dtype="timedelta64[ns]"`
# to `timedelta` objects.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
diff = pd.to_timedelta(time.values[1] - time.values[0])
# `cftime` objects only support arithmetic using `timedelta` objects, so
# the values of `diffs` must be casted from `dtype="timedelta64[ns]"`
# to `timedelta` objects.
# `cftime` objects only support arithmetic using `timedelta` objects, so
# the values of `diffs` must be casted from `dtype="timedelta64[ns]"`
# to `timedelta` objects.
diff = pd.to_timedelta(time.values[1] - time.values[0])

Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggest putting the comment ahead of the code (as is done earlier in the code).

Copy link
Collaborator

Choose a reason for hiding this comment

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

I was initially averse to adding in a pandas converter here, because in a different project I've run into issues with this (the behavior of the datetime conversion is sensitive to the input array), but your pointing out that this is already done earlier in the code makes me way less worried about this.

In the code block you pointed out in the issue, this conversion is conditioned on the array being a time axis (not needed here) and the array containing cftime objects. It does seem like it might prevent problems to only do this conversion if necessary (i.e., add a conditional here).

But I am a little confused because the existing conditional is meant to apply to cftime-based axes (and here it is meant to apply to axes that do not have cftime objects).

I'm curious about:

  • should there be a conditional to do this type conversion?
  • should the conditional be applied if the object type(time.values[0]) == np.datetime64) or not contains_cftime_datetimes(xr.as_variable(time))?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@pochedls thanks for the suggestion. I initially have coded as like below:

if isinstance(diff, np.timedelta64):
    diff = pd.to_timedelta(diff)

but this interrupted the GitHub Action CI check process for build, which was complaining that the function is too complicated. It seem like the CI process didn't like having more than a certain number of if layers.

I tested the code with a CMIP model data that has cftime-based time axis, and the same operation was running okay without errors, so was presuming it was okay with cftime-based axes. But I am open to any suggestion to make the code more robust.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I like this... @tomvothecoder may be able to suggest some a way to pass the CI tests (or skip them for that line, e.g., here).

Copy link
Collaborator Author

@lee1043 lee1043 Jun 6, 2024

Choose a reason for hiding this comment

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

I also like it but it does pass flake8 C901 with the error message of xcdat/bounds.py:507:5: C901 'BoundsAccessor._create_time_bounds' is too complex (11)

# type: ignore or #noqa: C901 (following the Stackoverflow) didn't help.

Copy link
Collaborator Author

@lee1043 lee1043 Jun 6, 2024

Choose a reason for hiding this comment

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

I updated the code to have the if statement (fb90864) but as expected it fails flake8 checks. @tomvothecoder Any help will be appreciated.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I added #noqa: C901 and updated the comment inside _create_time_bounds() here: 4c290e7.

I can help with adding the unit test tomorrow, which you can hopefully try out in #655 too.

lee1043 and others added 5 commits June 10, 2024 14:49
…vert it, so following `.seconds` line could run without error
Co-authored-by: Stephen Po-Chedley <[email protected]>
- Add comment about needing to convert dype=timedelta64[ns] to pandas timedelta object
- Ignore C901 flake8 error
@tomvothecoder
Copy link
Collaborator

I pushed commit c6b314a to add test coverage for the new code. This PR should be good to go.

tests/test_bounds.py Outdated Show resolved Hide resolved
@lee1043
Copy link
Collaborator Author

lee1043 commented Jun 10, 2024

@tomvothecoder thanks for the addition.

I am merging this PR.

@lee1043 lee1043 merged commit c653bf2 into main Jun 10, 2024
9 checks passed
@lee1043 lee1043 deleted the bug/659-timedelta64 branch June 10, 2024 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

[Bug]: add_missing_bounds not working when time type is numpy.timedelta64
3 participants