xarray-contrib / xarray-contrib/pint-xarray

Raise pint.DimensionalityError instead of ValueError

Open
#144 9 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
119
Forks
15
PR merge metrics
No merged PRs in 30d

Description

If you try to convert a pint.Quantity to an incompatible unit you get a pint.DimensionalityError, whereas if you try to convert a quantified DataArray to an incompatible unit you get a ValueError. These should give the same type of error.

In [1]: import pint_xarray

In [2]: import xarray as xr

In [3]: import pint

In [4]: mass_q = pint.Quantity(10, units='kg')

In [5]: mass_q.to('seconds')
---------------------------------------------------------------------------
DimensionalityError                       Traceback (most recent call last)
<ipython-input-5-86c449341523> in <module>
----> 1 mass_q.to('seconds')

~/Documents/Work/Code/pint/pint/quantity.py in to(self, other, *contexts, **ctx_kwargs)
    722         other = to_units_container(other, self._REGISTRY)
    723 
--> 724         magnitude = self._convert_magnitude_not_inplace(other, *contexts, **ctx_kwargs)
    725 
    726         return self.__class__(magnitude, other)

~/Documents/Work/Code/pint/pint/quantity.py in _convert_magnitude_not_inplace(self, other, *contexts, **ctx_kwargs)
    671                 return self._REGISTRY.convert(self._magnitude, self._units, other)
    672 
--> 673         return self._REGISTRY.convert(self._magnitude, self._units, other)
    674 
    675     def _convert_magnitude(self, other, *contexts, **ctx_kwargs):

~/Documents/Work/Code/pint/pint/registry.py in convert(self, value, src, dst, inplace)
   1001             return value
   1002 
-> 1003         return self._convert(value, src, dst, inplace)
   1004 
   1005     def _convert(self, value, src, dst, inplace=False, check_dimensionality=True):

~/Documents/Work/Code/pint/pint/registry.py in _convert(self, value, src, dst, inplace)
   1915                 value, src = src._magnitude, src._units
   1916 
-> 1917         return super()._convert(value, src, dst, inplace)
   1918 
   1919     def _get_compatible_units(self, input_units, group_or_system):

~/Documents/Work/Code/pint/pint/registry.py in _convert(self, value, src, dst, inplace)
   1516 
   1517         if not (src_offset_unit or dst_offset_unit):
-> 1518             return super()._convert(value, src, dst, inplace)
   1519 
   1520         src_dim = self._get_dimensionality(src)

~/Documents/Work/Code/pint/pint/registry.py in _convert(self, value, src, dst, inplace, check_dimensionality)
   1034             # then the conversion cannot be performed.
   1035             if src_dim != dst_dim:
-> 1036                 raise DimensionalityError(src, dst, src_dim, dst_dim)
   1037 
   1038         # Here src and dst have only multiplicative units left. Thus we can

DimensionalityError: Cannot convert from 'kilogram' ([mass]) to 'second' ([time])

In [6]: mass_da = xr.DataArray(10).pint.quantify(units='kg')

In [7]: mass_da.pint.to('seconds')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~/Documents/Work/Code/pint-xarray/pint_xarray/conversion.py in convert_units(obj, units)
    231     try:
--> 232         new_obj = call_on_dataset(
    233             convert_units_dataset, obj, name=temporary_name, units=units

~/Documents/Work/Code/pint-xarray/pint_xarray/compat.py in call_on_dataset(func, obj, name, *args, **kwargs)
     12 
---> 13         result = func(ds, *args, **kwargs)
     14 

~/Documents/Work/Code/pint-xarray/pint_xarray/conversion.py in convert_units_dataset(obj, units)
    216     if failed:
--> 217         raise ValueError(failed)
    218 

ValueError: {None: DimensionalityError()}

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
<ipython-input-7-00816f2a573d> in <module>
----> 1 mass_da.pint.to('seconds')

~/Documents/Work/Code/pint-xarray/pint_xarray/accessors.py in to(self, units, **unit_kwargs)
    568         units = either_dict_or_kwargs(units, unit_kwargs, "to")
    569 
--> 570         return conversion.convert_units(self.da, units)
    571 
    572     def chunk(self, chunks, name_prefix="xarray-", token=None, lock=False):

~/Documents/Work/Code/pint-xarray/pint_xarray/conversion.py in convert_units(obj, units)
    238             failed[obj.name] = failed.pop(temporary_name)
    239 
--> 240         raise ValueError(format_error_message(failed, "convert")) from e
    241 
    242     return new_obj

ValueError: Cannot convert variables:
    incompatible units for variable None: Cannot convert from 'kilogram' ([mass]) to 'second' ([time])

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in pint_xarray/conversion.py at convert_units and convert_units_dataset, where the traceback shows the conversion failure being wrapped, then follow the call from pint_xarray/accessors.py. Reproduce the incompatible kilogram-to-second conversion from the issue and verify that it raises pint.DimensionalityError rather than ValueError.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.