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

New function for applying vectorized functions for unlabeled arrays to xarray objects #964

Merged
merged 40 commits into from
Jan 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
999c829
WIP: apply_ufunc for applying generic functions to xarray objects
shoyer Aug 11, 2016
231aff7
Move operations.py -> computation.py
shoyer Aug 12, 2016
709142b
Rewrite _build_and_check_signature
shoyer Aug 14, 2016
308dca6
More work on signatures, including auto-dask
shoyer Aug 16, 2016
7debff8
apply_groupby_ufunc
shoyer Aug 24, 2016
bbd1372
fixes
shoyer Aug 28, 2016
42efd80
add gufunc string signature parsing
shoyer Aug 29, 2016
d273ceb
Add some basic tests (and get them passing)
shoyer Aug 31, 2016
d337b1c
Signature parse tests
shoyer Aug 31, 2016
5e24fbf
more docs, work on Signature parsing
shoyer Aug 31, 2016
af40e4c
add check/test for unexpected dimensions
shoyer Sep 2, 2016
a929ddf
tests for core dimensions
shoyer Sep 2, 2016
03db947
build_output_coords fixes
shoyer Sep 7, 2016
b153ffa
Tests and fixes for binary ops
shoyer Sep 8, 2016
d0a30a9
performance improvements
shoyer Sep 9, 2016
2840a3e
GroupBy ufunc fixes
shoyer Sep 10, 2016
05f8534
More succinct tests & fixes for groupby ufuncs
shoyer Sep 10, 2016
18d6c40
More optimizations
shoyer Sep 12, 2016
698548f
Tests for _calculate_unified_dim_sizes
shoyer Sep 12, 2016
d4abc68
apply_dask_ufunc tests
shoyer Sep 12, 2016
ecd3629
Tests for dask.array
shoyer Sep 12, 2016
7ed216e
Fix function signatures
shoyer Sep 12, 2016
0d0f119
Tweaks
shoyer Sep 12, 2016
6ddbad4
Tests and full docstring for apply_ufunc
shoyer Sep 12, 2016
2c0df8f
Switch new_coords to a list
shoyer Sep 12, 2016
6b297a7
Add exclude_dims
shoyer Sep 13, 2016
e6bbad2
Move deep_align back into alignment.py
shoyer Sep 13, 2016
1a0e915
Lint
shoyer Sep 13, 2016
cbe2c62
changes per MaximilianR's review
shoyer Sep 14, 2016
90ae41c
style fixes
shoyer Sep 15, 2016
53ee21b
Docstrings
shoyer Sep 17, 2016
5f44423
Rename apply_ufunc to apply
shoyer Sep 17, 2016
5a116e4
Fix recursion bug in test
shoyer Sep 17, 2016
00f51b1
Simpler exclude_dims
shoyer Sep 18, 2016
ab14560
WIP
shoyer Sep 22, 2016
8537075
Merge branch 'master' into apply_ufunc
shoyer Dec 19, 2016
3b0b5f4
Fix test failures
shoyer Dec 19, 2016
3f13d6c
Remove unused function. Rename apply to apply_ufunc.
shoyer Jan 4, 2017
3086d52
Remove extraneous "new_coords" argument
shoyer Jan 4, 2017
d15a005
Merge branch 'master' into apply_ufunc
shoyer Jan 4, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 74 additions & 6 deletions xarray/core/alignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from .common import _maybe_promote
from .indexing import get_indexer
from .pycompat import iteritems, OrderedDict, suppress
from .utils import is_full_slice
from .utils import is_full_slice, is_dict_like
from .variable import Variable, IndexVariable


Expand All @@ -29,8 +29,12 @@ def _get_joiner(join):
raise ValueError('invalid value for join: %s' % join)


_DEFAULT_EXCLUDE = frozenset()


def align(*objects, **kwargs):
"""align(*objects, join='inner', copy=True)
"""align(*objects, join='inner', copy=True, indexes=None,
exclude=frozenset())

Given any number of Dataset and/or DataArray objects, returns new
objects with aligned indexes and dimension sizes.
Expand Down Expand Up @@ -76,15 +80,18 @@ def align(*objects, **kwargs):
join = kwargs.pop('join', 'inner')
copy = kwargs.pop('copy', True)
indexes = kwargs.pop('indexes', None)
exclude = kwargs.pop('exclude', None)
exclude = kwargs.pop('exclude', _DEFAULT_EXCLUDE)
if indexes is None:
indexes = {}
if exclude is None:
exclude = set()
if kwargs:
raise TypeError('align() got unexpected keyword arguments: %s'
% list(kwargs))

if not indexes and len(objects) == 1:
# fast path for the trivial case
obj, = objects
return (obj.copy(deep=copy),)

all_indexes = defaultdict(list)
unlabeled_dim_sizes = defaultdict(set)
for obj in objects:
Expand Down Expand Up @@ -142,11 +149,72 @@ def align(*objects, **kwargs):
for obj in objects:
valid_indexers = {k: v for k, v in joined_indexes.items()
if k in obj.dims}
result.append(obj.reindex(copy=copy, **valid_indexers))
if not valid_indexers:
# fast path for no reindexing necessary
new_obj = obj.copy(deep=copy)
else:
new_obj = obj.reindex(copy=copy, **valid_indexers)
result.append(new_obj)

return tuple(result)


def deep_align(objects, join='inner', copy=True, indexes=None,
exclude=frozenset(), raise_on_invalid=True):
"""Align objects for merging, recursing into dictionary values.

This function is not public API.
"""
if indexes is None:
indexes = {}

def is_alignable(obj):
return hasattr(obj, 'indexes') and hasattr(obj, 'reindex')

positions = []
keys = []
out = []
targets = []
no_key = object()
not_replaced = object()
for n, variables in enumerate(objects):
if is_alignable(variables):
positions.append(n)
keys.append(no_key)
targets.append(variables)
out.append(not_replaced)
elif is_dict_like(variables):
for k, v in variables.items():
if is_alignable(v) and k not in indexes:
# Skip variables in indexes for alignment, because these
# should to be overwritten instead:
# https://github.com/pydata/xarray/issues/725
positions.append(n)
keys.append(k)
targets.append(v)
out.append(OrderedDict(variables))
elif raise_on_invalid:
raise ValueError('object to align is neither an xarray.Dataset, '
'an xarray.DataArray nor a dictionary: %r'
% variables)
else:
out.append(variables)

aligned = align(*targets, join=join, copy=copy, indexes=indexes,
exclude=exclude)

for position, key, aligned_obj in zip(positions, keys, aligned):
if key is no_key:
out[position] = aligned_obj
else:
out[position][key] = aligned_obj

# something went wrong: we should have replaced all sentinel values
assert all(arg is not not_replaced for arg in out)

return out


def reindex_like_indexers(target, other):
"""Extract indexers to align target with other.

Expand Down
Loading