@@ -68,28 +68,9 @@ def n_inputs(self):
68
68
return len (self .input_core_dims )
69
69
70
70
@property
71
- def n_outputs (self ):
71
+ def num_outputs (self ):
72
72
return len (self .output_core_dims )
73
73
74
- @classmethod
75
- def default (cls , n_inputs ):
76
- return cls ([()] * n_inputs , [()])
77
-
78
- @classmethod
79
- def from_sequence (cls , nested ):
80
- if (not isinstance (nested , collections .Sequence ) or
81
- not len (nested ) == 2 or
82
- any (not isinstance (arg_list , collections .Sequence )
83
- for arg_list in nested ) or
84
- any (isinstance (arg , basestring ) or
85
- not isinstance (arg , collections .Sequence )
86
- for arg_list in nested for arg in arg_list )):
87
- raise TypeError ('functions signatures not provided as a string '
88
- 'must be a triply nested sequence providing the '
89
- 'list of core dimensions for each variable, for '
90
- 'both input and output.' )
91
- return cls (* nested )
92
-
93
74
def __eq__ (self , other ):
94
75
try :
95
76
return (self .input_core_dims == other .input_core_dims and
@@ -190,7 +171,7 @@ def apply_dataarray_ufunc(func, *args, **kwargs):
190
171
data_vars = [getattr (a , 'variable' , a ) for a in args ]
191
172
result_var = func (* data_vars )
192
173
193
- if signature .n_outputs > 1 :
174
+ if signature .num_outputs > 1 :
194
175
out = tuple (DataArray (variable , coords , name = name , fastpath = True )
195
176
for variable , coords in zip (result_var , result_coords ))
196
177
else :
@@ -269,10 +250,10 @@ def _as_variables_or_variable(arg):
269
250
270
251
def _unpack_dict_tuples (
271
252
result_vars , # type: Mapping[Any, Tuple[Variable]]
272
- n_outputs , # type: int
253
+ num_outputs , # type: int
273
254
):
274
255
# type: (...) -> Tuple[Dict[Any, Variable]]
275
- out = tuple (OrderedDict () for _ in range (n_outputs ))
256
+ out = tuple (OrderedDict () for _ in range (num_outputs ))
276
257
for name , values in result_vars .items ():
277
258
for value , results_dict in zip (values , out ):
278
259
results_dict [name ] = value
@@ -298,8 +279,8 @@ def apply_dict_of_variables_ufunc(func, *args, **kwargs):
298
279
for name , variable_args in zip (names , grouped_by_name ):
299
280
result_vars [name ] = func (* variable_args )
300
281
301
- if signature .n_outputs > 1 :
302
- return _unpack_dict_tuples (result_vars , signature .n_outputs )
282
+ if signature .num_outputs > 1 :
283
+ return _unpack_dict_tuples (result_vars , signature .num_outputs )
303
284
else :
304
285
return result_vars
305
286
@@ -335,8 +316,8 @@ def apply_dataset_ufunc(func, *args, **kwargs):
335
316
336
317
if (dataset_join not in _JOINS_WITHOUT_FILL_VALUES and
337
318
fill_value is _DEFAULT_FILL_VALUE ):
338
- raise TypeError ('To apply an operation to datasets with different ' ,
339
- 'data variables, you must supply the ' ,
319
+ raise TypeError ('to apply an operation to datasets with different '
320
+ 'data variables with apply_ufunc , you must supply the '
340
321
'dataset_fill_value argument.' )
341
322
342
323
if kwargs :
@@ -353,7 +334,7 @@ def apply_dataset_ufunc(func, *args, **kwargs):
353
334
func , * args , signature = signature , join = dataset_join ,
354
335
fill_value = fill_value )
355
336
356
- if signature .n_outputs > 1 :
337
+ if signature .num_outputs > 1 :
357
338
out = tuple (_fast_dataset (* args )
358
339
for args in zip (result_vars , list_of_coords ))
359
340
else :
@@ -388,12 +369,12 @@ def apply_groupby_ufunc(func, *args):
388
369
from .variable import Variable
389
370
390
371
groupbys = [arg for arg in args if isinstance (arg , GroupBy )]
391
- if not groupbys :
392
- raise ValueError ('must have at least one groupby to iterate over' )
372
+ assert groupbys , 'must have at least one groupby to iterate over'
393
373
first_groupby = groupbys [0 ]
394
374
if any (not first_groupby ._group .equals (gb ._group ) for gb in groupbys [1 :]):
395
- raise ValueError ('can only perform operations over multiple groupbys '
396
- 'at once if they are all grouped the same way' )
375
+ raise ValueError ('apply_ufunc can only perform operations over '
376
+ 'multiple GroupBy objets at once if they are all '
377
+ 'grouped the same way' )
397
378
398
379
grouped_dim = first_groupby ._group .name
399
380
unique_values = first_groupby ._unique_coord .values
@@ -430,7 +411,7 @@ def unified_dim_sizes(variables, exclude_dims=frozenset()):
430
411
for var in variables :
431
412
if len (set (var .dims )) < len (var .dims ):
432
413
raise ValueError ('broadcasting cannot handle duplicate '
433
- 'dimensions: %r' % list (var .dims ))
414
+ 'dimensions on a variable : %r' % list (var .dims ))
434
415
for dim , size in zip (var .dims , var .shape ):
435
416
if dim not in exclude_dims :
436
417
if dim not in dim_sizes :
@@ -462,15 +443,17 @@ def broadcast_compat_data(variable, broadcast_dims, core_dims):
462
443
set_old_dims = set (old_dims )
463
444
missing_core_dims = [d for d in core_dims if d not in set_old_dims ]
464
445
if missing_core_dims :
465
- raise ValueError ('operation requires dimensions missing on input '
466
- 'variable: %r' % missing_core_dims )
446
+ raise ValueError ('operand to apply_ufunc has required core dimensions '
447
+ '%r, but some of these are missing on the input '
448
+ 'variable: %r' % (list (core_dims ), missing_core_dims ))
467
449
468
450
set_new_dims = set (new_dims )
469
451
unexpected_dims = [d for d in old_dims if d not in set_new_dims ]
470
452
if unexpected_dims :
471
- raise ValueError ('operation encountered unexpected dimensions %r '
472
- 'on input variable: these are core dimensions on '
473
- 'other input or output variables' % unexpected_dims )
453
+ raise ValueError ('operand to apply_ufunc encountered unexpected '
454
+ 'dimensions %r on an input variable: these are core '
455
+ 'dimensions on other input or output variables'
456
+ % unexpected_dims )
474
457
475
458
# for consistency with numpy, keep broadcast dimensions to the left
476
459
old_broadcast_dims = tuple (d for d in broadcast_dims if d in set_old_dims )
@@ -520,8 +503,11 @@ def apply_variable_ufunc(func, *args, **kwargs):
520
503
521
504
if any (isinstance (array , dask_array_type ) for array in input_data ):
522
505
if dask == 'forbidden' :
523
- raise ValueError ('encountered dask array, but did not set '
524
- "dask='allowed'" )
506
+ raise ValueError ('apply_ufunc encountered a dask array on an '
507
+ 'argument, but handling for dask arrays has not '
508
+ 'been enabled. Either set the ``dask`` argument '
509
+ 'or load your data into memory first with '
510
+ '``.load()`` or ``.compute()``' )
525
511
elif dask == 'parallelized' :
526
512
input_dims = [broadcast_dims + input_dims
527
513
for input_dims in signature .input_core_dims ]
@@ -532,11 +518,11 @@ def apply_variable_ufunc(func, *args, **kwargs):
532
518
elif dask == 'allowed' :
533
519
pass
534
520
else :
535
- raise ValueError ('unknown setting for dask array handling: {} '
536
- .format (dask ))
521
+ raise ValueError ('unknown setting for dask array handling in '
522
+ 'apply_ufunc: {}' .format (dask ))
537
523
result_data = func (* input_data )
538
524
539
- if signature .n_outputs > 1 :
525
+ if signature .num_outputs > 1 :
540
526
output = []
541
527
for dims , data in zip (output_dims , result_data ):
542
528
output .append (Variable (dims , data ))
@@ -550,23 +536,26 @@ def _apply_with_dask_atop(func, args, input_dims, output_dims, signature,
550
536
output_dtypes , output_sizes = None ):
551
537
import dask .array as da
552
538
553
- if signature .n_outputs > 1 :
554
- raise NotImplementedError (
555
- "multiple outputs not yet supported with dask='parallelized'" )
539
+ if signature .num_outputs > 1 :
540
+ raise NotImplementedError ('multiple outputs from apply_ufunc not yet '
541
+ " supported with dask='parallelized'" )
556
542
557
543
if output_dtypes is None :
558
- raise ValueError (
559
- "output dtypes (output_dtypes) required when using dask='parallelized'" )
560
- if len (output_dtypes ) != signature .n_outputs :
561
- raise ValueError ('wrong number of output dtypes' )
544
+ raise ValueError ('output dtypes (output_dtypes) must be supplied to '
545
+ "apply_func when using dask='parallelized'" )
546
+ if len (output_dtypes ) != signature .num_outputs :
547
+ raise ValueError ('apply_ufunc arguments output_dtypes and '
548
+ 'output_core_dims must have the same length: {} vs {}'
549
+ .format (len (output_dtypes ), signature .num_outputs ))
562
550
(dtype ,) = output_dtypes
563
551
564
552
if output_sizes is None :
565
553
output_sizes = {}
566
554
567
555
new_dims = signature .all_output_core_dims - signature .all_input_core_dims
568
556
if any (dim not in output_sizes for dim in new_dims ):
569
- raise ValueError ('output core dimensions not found on inputs must have '
557
+ raise ValueError ("when using dask='parallelized' with apply_ufunc, "
558
+ 'output core dimensions not found on inputs must have '
570
559
'explicitly set sizes with ``output_sizes``: {}'
571
560
.format (new_dims ))
572
561
@@ -595,11 +584,14 @@ def apply_array_ufunc(func, *args, **kwargs):
595
584
596
585
if any (isinstance (arg , dask_array_type ) for arg in args ):
597
586
if dask == 'forbidden' :
598
- raise ValueError ('encountered dask array, but did not set '
599
- "dask='allowed'" )
587
+ raise ValueError ('apply_ufunc encountered a dask array on an '
588
+ 'argument, but handling for dask arrays has not '
589
+ 'been enabled. Either set the ``dask`` argument '
590
+ 'or load your data into memory first with '
591
+ '``.load()`` or ``.compute()``' )
600
592
elif dask == 'parallelized' :
601
- raise ValueError ("cannot use dask='parallelized' unless at least "
602
- 'one input is an xarray object' )
593
+ raise ValueError ("cannot use dask='parallelized' for apply_ufunc "
594
+ 'unless at least one input is an xarray object' )
603
595
elif dask == 'allowed' :
604
596
pass
605
597
else :
@@ -619,7 +611,7 @@ def apply_ufunc(func, *args, **kwargs):
619
611
dataset_fill_value : Any = _DEFAULT_FILL_VALUE,
620
612
keep_attrs : bool = False,
621
613
kwargs : Mapping = None,
622
- dask_array : str = 'forbidden',
614
+ dask : str = 'forbidden',
623
615
output_dtypes : Optional[Sequence] = None,
624
616
output_sizes : Optional[Mapping[Any, int]] = None)
625
617
@@ -698,8 +690,8 @@ def apply_ufunc(func, *args, **kwargs):
698
690
- 'forbidden' (default): raise an error if a dask array is encountered.
699
691
- 'allowed': pass dask arrays directly on to ``func``.
700
692
- 'parallelized': automatically parallelize ``func`` if any of the
701
- inputs are a dask array. If used, the ``otypes `` argument must also be
702
- provided. Multiple output arguments are not yet supported.
693
+ inputs are a dask array. If used, the ``output_dtypes `` argument must
694
+ also be provided. Multiple output arguments are not yet supported.
703
695
output_dtypes : list of dtypes, optional
704
696
Optional list of output dtypes. Only used if dask='parallelized'.
705
697
output_sizes : dict, optional
0 commit comments