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

Add option to not roll coords #2360

Merged
merged 10 commits into from
Aug 15, 2018
Merged

Add option to not roll coords #2360

merged 10 commits into from
Aug 15, 2018

Conversation

ahuang11
Copy link
Contributor

@ahuang11 ahuang11 commented Aug 10, 2018

  • Closes roll doesn't handle periodic boundary conditions well #1875
  • Tests added (for all bug fixes or enhancements)
  • Tests passed (for all non-documentation changes)
  • Fully documented, including whats-new.rst for all changes and api.rst for new API (remove if this change should not be visible to users, e.g., if it is an internal clean-up, or if this is part of a larger project that will be documented later)

image

Will add the others stuff from the checklist soon.

Copy link
Member

@fujiisoup fujiisoup left a comment

Choose a reason for hiding this comment

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

Thanks for sending a PR.

I personally like more explicit argument name, such as roll_coordinate rather than simple coords so that users easily know a boolean should be passed for this.

Any idea?

For example, a boolean argument of interpolate_na is use_coordinate.

@@ -2015,14 +2015,20 @@ def shift(self, **shifts):
variable = self.variable.shift(**shifts)
return self._replace(variable)

def roll(self, **shifts):
def roll(self, coords, **shifts):
Copy link
Member

Choose a reason for hiding this comment

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

This argument should have a default.

fujiisoup
fujiisoup previously approved these changes Aug 12, 2018
Copy link
Member

@fujiisoup fujiisoup left a comment

Choose a reason for hiding this comment

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

Thanks. Looks good to me.
@shoyer, can you take a look?

@fujiisoup fujiisoup dismissed their stale review August 12, 2018 05:14

Logic should be updated.

var_shifts = dict((k, v) for k, v in shifts.items()
if k in var.dims)
variables[name] = var.roll(**var_shifts)
if name in self.data_vars or roll_coords:
Copy link
Member

Choose a reason for hiding this comment

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

I think this logic should be updated.
All the variables in data_vars should be rolled, independent from roll_coords value.
Other variables (variables in self.coord_names) may depend on whether roll_coords is True or not.

elif name in coord_names and roll_coords is None:
warnings.warn("roll_coords will be set to False in the future."
" Explicitly set roll_coords to silence warning.",
DeprecationWarning, stacklevel=3)
Copy link
Member

Choose a reason for hiding this comment

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

My previous comment seemed confusing...
I think your previous commit is cleaner.

Or how about something like this?

if roll_coords is None:
    warnings.warn("roll_coords will be set to False in the future."
                  " Explicitly set roll_coords to silence warning.",
                  DeprecationWarning, stacklevel=3)
    roll_coords = True

unrolled_vars = () if roll_coords else self.coord_names
variables = OrderedDict()
for k, v in self.variables:
    if k not in unrolled_vars:
        variables[k] = v.roll(**coords)
    else:
        variables[k] = v

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that definitely looks cleaner.

Copy link
Member

@fujiisoup fujiisoup left a comment

Choose a reason for hiding this comment

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

Thanks. This looks nice to me.

if roll_coords is None:
warnings.warn("roll_coords will be set to False in the future."
" Explicitly set roll_coords to silence warning.",
DeprecationWarning, stacklevel=3)
Copy link
Member

Choose a reason for hiding this comment

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

Use FutureWarning here, which doesn't get silenced by default and is intended for warning about future changes in behavior.

if roll_coords is None:
warnings.warn("roll_coords will be set to False in the future."
" Explicitly set roll_coords to silence warning.",
DeprecationWarning, stacklevel=3)
Copy link
Member

Choose a reason for hiding this comment

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

Also -- consider using stacklevel=2 here. stacklevel=3 here would be confusing if Dataset.roll() is called directly.

I think it's probably better to incorrect indicate that the error is being raised internally inside xarray rather than to incorrectly indicate that it's being raised by some arbitrary user code.


def test_roll_coords_none(self):
arr = DataArray([1, 2, 3], coords={'x': range(3)}, dims='x')
actual = arr.roll(x=1, roll_coords=None)
Copy link
Member

Choose a reason for hiding this comment

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

Please verify that the warning is raised, e.g.,

with pytest.raises(FutureWarning):
    ...

Indicates whether to roll the coordinates by the offset
The current default of roll_coords (None, equivalent to True) is
deprecated and will change to False in a future version.
Explicitly pass roll_coords to silence the warning and sort.
Copy link
Member

Choose a reason for hiding this comment

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

What does "and sort" refer to?

@@ -2015,14 +2015,20 @@ def shift(self, **shifts):
variable = self.variable.shift(**shifts)
return self._replace(variable)

def roll(self, **shifts):
def roll(self, roll_coords=None, **shifts):
Copy link
Member

Choose a reason for hiding this comment

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

It might be nice to use utils.either_dict_or_kwargs here, to handle potential (unlikely) conflicts between the name "roll_coords" and dimension names.

Example usage:

indexers = either_dict_or_kwargs(indexers, indexers_kwargs, 'isel')

Copy link
Contributor Author

@ahuang11 ahuang11 Aug 13, 2018

Choose a reason for hiding this comment

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

Not too sure I understand this util; let me know if I implemented it inaccurately. (I think I got it now?)

Copy link
Member

@fujiisoup fujiisoup left a comment

Choose a reason for hiding this comment

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

Thanks a lot :)
A few further comments, but it is almost ready.

@@ -2046,7 +2052,10 @@ def roll(self, **shifts):
Coordinates:
* x (x) int64 2 0 1
"""
ds = self._to_temp_dataset().roll(**shifts)
shifts = either_dict_or_kwargs(shifts,
Copy link
Member

@fujiisoup fujiisoup Aug 13, 2018

Choose a reason for hiding this comment

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

Thanks.
You can pass both shifts and shifts_kwargs to _to_temp_dataset().roll directly, in order to simplify the script here. It will be handled propery in dataset.roll.

@@ -3389,15 +3399,27 @@ def roll(self, **shifts):
Data variables:
foo (x) object 'd' 'e' 'a' 'b' 'c'
"""
shifts = either_dict_or_kwargs(shifts,
Copy link
Member

Choose a reason for hiding this comment

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

Maybe better to avoid unnecessary line breaks.
Simply write either_dict_or_kwargs(shifts, shifts_kwargs, 'roll')

@fujiisoup fujiisoup merged commit cbb2aeb into pydata:master Aug 15, 2018
@fujiisoup
Copy link
Member

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

roll doesn't handle periodic boundary conditions well
3 participants