8
8
9
9
from . import conversion
10
10
11
+
12
+ def setup_registry (registry ):
13
+ """set up the given registry for use with pint_xarray
14
+
15
+ Namely, it enables ``force_ndarray_like`` to make sure results are always
16
+ duck arrays.
17
+
18
+ Parameters
19
+ ----------
20
+ registry : pint.UnitRegistry
21
+ The registry to modify
22
+ """
23
+ if not registry .force_ndarray and not registry .force_ndarray_like :
24
+ registry .force_ndarray_like = True
25
+
26
+ return registry
27
+
28
+
29
+ default_registry = setup_registry (pint .get_application_registry ())
30
+
11
31
# TODO could/should we overwrite xr.open_dataset and xr.open_mfdataset to make
12
32
# them apply units upon loading???
13
33
# TODO could even override the decode_cf kwarg?
@@ -47,6 +67,16 @@ def zip_mappings(*mappings, fill_value=None):
47
67
return zipped
48
68
49
69
70
+ def merge_mappings (first , * mappings ):
71
+ result = first .copy ()
72
+ for mapping in mappings :
73
+ result .update (
74
+ {key : value for key , value in mapping .items () if value is not None }
75
+ )
76
+
77
+ return result
78
+
79
+
50
80
def units_to_str_or_none (mapping ):
51
81
return {
52
82
key : str (value ) if isinstance (value , Unit ) else value
@@ -72,13 +102,27 @@ def either_dict_or_kwargs(positional, keywords, method_name):
72
102
return keywords
73
103
74
104
75
- def _get_registry (unit_registry , registry_kwargs ):
105
+ def get_registry (unit_registry , new_units , existing_units ):
106
+ units = merge_mappings (existing_units , new_units )
107
+ registries = {unit ._REGISTRY for unit in units .values () if isinstance (unit , Unit )}
108
+
76
109
if unit_registry is None :
77
- if registry_kwargs is None :
78
- registry_kwargs = {}
79
- registry_kwargs .update (force_ndarray = True )
80
- # TODO should this registry object then be stored somewhere global?
81
- unit_registry = pint .UnitRegistry (** registry_kwargs )
110
+ if not registries :
111
+ unit_registry = default_registry
112
+ elif len (registries ) == 1 :
113
+ (unit_registry ,) = registries
114
+ registries .add (unit_registry )
115
+
116
+ if len (registries ) > 1 or unit_registry not in registries :
117
+ raise ValueError (
118
+ "using multiple unit registries in the same object is not supported"
119
+ )
120
+
121
+ if not unit_registry .force_ndarray_like and not unit_registry .force_ndarray :
122
+ raise ValueError (
123
+ "invalid registry. Please enable 'force_ndarray_like' or 'force_ndarray'."
124
+ )
125
+
82
126
return unit_registry
83
127
84
128
@@ -110,9 +154,7 @@ class PintDataArrayAccessor:
110
154
def __init__ (self , da ):
111
155
self .da = da
112
156
113
- def quantify (
114
- self , units = None , unit_registry = None , registry_kwargs = None , ** unit_kwargs
115
- ):
157
+ def quantify (self , units = None , unit_registry = None , ** unit_kwargs ):
116
158
"""
117
159
Attaches units to the DataArray.
118
160
@@ -145,8 +187,6 @@ def quantify(
145
187
unit_registry : pint.UnitRegistry, optional
146
188
Unit registry to be used for the units attached to this DataArray.
147
189
If not given then a default registry will be created.
148
- registry_kwargs : dict, optional
149
- Keyword arguments to be passed to the unit registry.
150
190
**unit_kwargs
151
191
Keyword argument form of units.
152
192
@@ -187,7 +227,11 @@ def quantify(
187
227
188
228
units = either_dict_or_kwargs (units , unit_kwargs , ".quantify" )
189
229
190
- registry = _get_registry (unit_registry , registry_kwargs )
230
+ registry = get_registry (
231
+ unit_registry ,
232
+ units ,
233
+ conversion .extract_units (self .da ),
234
+ )
191
235
192
236
unit_attrs = conversion .extract_unit_attributes (self .da )
193
237
new_obj = conversion .strip_unit_attributes (self .da )
@@ -254,7 +298,7 @@ def dimensionality(self):
254
298
@property
255
299
def registry (self ):
256
300
# TODO is this a bad idea? (see GH issue #1071 in pint)
257
- return self .data . _REGISTRY
301
+ return getattr ( self .da . data , " _REGISTRY" , None )
258
302
259
303
@registry .setter
260
304
def registry (self , _ ):
@@ -385,9 +429,7 @@ class PintDatasetAccessor:
385
429
def __init__ (self , ds ):
386
430
self .ds = ds
387
431
388
- def quantify (
389
- self , units = None , unit_registry = None , registry_kwargs = None , ** unit_kwargs
390
- ):
432
+ def quantify (self , units = None , unit_registry = None , ** unit_kwargs ):
391
433
"""
392
434
Attaches units to each variable in the Dataset.
393
435
@@ -420,8 +462,6 @@ def quantify(
420
462
Unit registry to be used for the units attached to each
421
463
DataArray in this Dataset. If not given then a default
422
464
registry will be created.
423
- registry_kwargs : dict, optional
424
- Keyword arguments to be passed to `pint.UnitRegistry`.
425
465
**unit_kwargs
426
466
Keyword argument form of ``units``.
427
467
@@ -458,7 +498,11 @@ def quantify(
458
498
b (x) int64 <Quantity([ 5 -2 1], 'decimeter')>
459
499
"""
460
500
units = either_dict_or_kwargs (units , unit_kwargs , ".quantify" )
461
- registry = _get_registry (unit_registry , registry_kwargs )
501
+ registry = get_registry (
502
+ unit_registry ,
503
+ units ,
504
+ conversion .extract_units (self .ds ),
505
+ )
462
506
463
507
unit_attrs = conversion .extract_unit_attributes (self .ds )
464
508
new_obj = conversion .strip_unit_attributes (self .ds )
0 commit comments