xarray-contrib / pint-xarray

Interface for using pint with xarray, providing convenience accessors
https://pint-xarray.readthedocs.io/en/latest/
Apache License 2.0
103 stars 12 forks source link

AttributeError: 'Dataset' object has no attribute 'pint' #224

Closed forestbat closed 1 year ago

forestbat commented 1 year ago

This is my method:

def unify_streamflow_unit(ds: xarray.Dataset, area=None, inverse=False):
    """Unify the unit of xr_dataset to be mm/day in a basin or inverse

    Parameters
    ----------
    ds: xarray dataset
        _description_
    area:
        area of each basin

    Returns
    -------
    _type_
        _description_
    """
    # use pint to convert unit
    if not inverse:
        target_unit = "mm/d"
        q = ds.pint.quantify()
        a = area.pint.quantify()
        r = q[list(q.keys())[0]] / a[list(a.keys())[0]]
        result = r.pint.to(target_unit).to_dataset(name=list(q.keys())[0])
    else:
        target_unit = "m^3/s"
        r = ds.pint.quantify()
        a = area.pint.quantify()
        q = r[list(r.keys())[0]] * a[list(a.keys())[0]]
        result = q.pint.to(target_unit).to_dataset(name=list(r.keys())[0])
    # dequantify to get normal xr_dataset
    return result.pint.dequantify()

And my version of pint is 0.3, however when I try to debug this code, it tells me:

..\torchhydro\datasets\data_scalers.py:568: in unify_streamflow_unit
    q = ds.pint.quantify()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <xarray.Dataset>
Dimensions:     (basin: 1, time: 366)
Coordinates:
  * basin       (basin) object '01013500'
  * time...2000-10-02 ... 2001-10-01
Data variables:
    streamflow  (basin, time) float64 107.0 104.0 104.0 ... 273.0 275.0 275.0
name = 'pint'

    def __getattr__(self, name: str) -> Any:
        if name not in {"__dict__", "__setstate__"}:
            # this avoids an infinite loop when pickle looks for the
            # __setstate__ attribute before the xarray object is initialized
            for source in self._attr_sources:
                with suppress(KeyError):
                    return source[name]
>       raise AttributeError(
            f"{type(self).__name__!r} object has no attribute {name!r}"
        )
E       AttributeError: 'Dataset' object has no attribute 'pint'

So why this problem will occur?

keewis commented 1 year ago

you seem to have figured this out already, but for the accessor to register you need to import pint_xarray first (if you use autoformatters / linters with auto-correct – i.e. ruff – make sure to mark that line with # noqa: F401).