ajdawson / eofs

EOF analysis in Python
http://ajdawson.github.io/eofs/
GNU General Public License v3.0
199 stars 60 forks source link

Error while using solver.eofs with eofs.xarray #127

Open Pearl-Ayem opened 2 years ago

Pearl-Ayem commented 2 years ago

I am confused by this error as this code was working perfectly fine until last week. biweekly_data is an Xarray Dataset and when I type the following:

coslat = np.cos(np.deg2rad(biweekly_data.coords['rlat'].values))
wgts = np.sqrt(coslat)[..., np.newaxis]
solver = Eof(biweekly_data, weights=wgts)

eof1 = solver.eofs()

I get this error: TypeError: the input must be an xarray DataArray

So I tried:

coslat = np.cos(np.deg2rad(biweekly_data.coords['rlat'].values))
wgts = np.sqrt(coslat)[..., np.newaxis]
solver = Eof(biweekly_data.snowmelt, weights=wgts)

eof1 = solver.eofs()

And then get this: TypeError: Using a DataArray object to construct a variable is ambiguous, please extract the data using the .data property

So one more time I tried:

coslat = np.cos(np.deg2rad(biweekly_data.coords['rlat'].values))
wgts = np.sqrt(coslat)[..., np.newaxis]
solver = Eof(biweekly_data.snowmelt.data, weights=wgts)

eof1 = solver.eofs()

And get: TypeError: the input must be an xarray DataArray

It just baffled me because I've used the code as shown in the very top block before to create maps like these: 2016 to 2020 snowmelt EOF for daily data SUMMER ONLY

Note:

The solver works if I use eofs.standard when I use solver = Eof(biweekly_data.snowmelt.data, weights=wgts)

Pearl-Ayem commented 2 years ago

1. Error while using solver = Eof(biweekly_data, weights=wgts)

TypeError                                 Traceback (most recent call last)
Input In [19], in <cell line: 3>()
      1 coslat = np.cos(np.deg2rad(biweekly_data.coords['rlat'].values))
      2 wgts = np.sqrt(coslat)[..., np.newaxis]
----> 3 solver = Eof(biweekly_data, weights=wgts)
      5 eof1 = solver.eofs()
      6 pc1  = solver.pcs()

File ~\anaconda3\envs\dissenv\lib\site-packages\eofs\xarray.py:95, in Eof.__init__(self, array, weights, center, ddof)
     36 """Create an Eof object.
     37 
     38 The EOF solution is computed at initialization time. Method
   (...)
     92 
     93 """
     94 if not isinstance(array, xr.DataArray):
---> 95     raise TypeError('the input must be an xarray DataArray')
     96 # Find a time-like dimension, and check if it is the first.
     97 time_coords = find_time_coordinates(array)

TypeError: the input must be an xarray DataArray

2. Error while using solver = Eof(biweekly_data.snowmelt, weights=wgts)

TypeError                                 Traceback (most recent call last)
Input In [20], in <cell line: 5>()
      2 wgts = np.sqrt(coslat)[..., np.newaxis]
      3 solver = Eof(biweekly_data.snowmelt, weights=wgts)
----> 5 eof1 = solver.eofs()
      6 pc1  = solver.pcs()
      7 varfrac = solver.varianceFraction()

File ~\anaconda3\envs\dissenv\lib\site-packages\eofs\xarray.py:229, in Eof.eofs(self, eofscaling, neofs)
    226 long_name = 'empirical_orthogonal_functions'
    227 eofs = xr.DataArray(eofs, coords=coords, name='eofs',
    228                     attrs={'long_name': long_name})
--> 229 eofs.coords.update({coord.name: (coord.dims, coord)
    230                     for coord in self._space_ndcoords})
    231 return eofs

File ~\anaconda3\envs\dissenv\lib\site-packages\xarray\core\coordinates.py:163, in Coordinates.update(self, other)
    161 def update(self, other: Mapping[Any, Any]) -> None:
    162     other_vars = getattr(other, "variables", other)
--> 163     coords, indexes = merge_coords(
    164         [self.variables, other_vars], priority_arg=1, indexes=self.xindexes
    165     )
    166     self._update_coords(coords, indexes)

File ~\anaconda3\envs\dissenv\lib\site-packages\xarray\core\merge.py:471, in merge_coords(objects, compat, join, priority_arg, indexes, fill_value)
    467 coerced = coerce_pandas_values(objects)
    468 aligned = deep_align(
    469     coerced, join=join, copy=False, indexes=indexes, fill_value=fill_value
    470 )
--> 471 collected = collect_variables_and_indexes(aligned)
    472 prioritized = _get_priority_vars_and_indexes(aligned, priority_arg, compat=compat)
    473 variables, out_indexes = merge_collected(collected, prioritized, compat=compat)

File ~\anaconda3\envs\dissenv\lib\site-packages\xarray\core\merge.py:291, in collect_variables_and_indexes(list_of_mappings)
    288     indexes.pop(name, None)
    289     append_all(coords, indexes)
--> 291 variable = as_variable(variable, name=name)
    293 if variable.dims == (name,):
    294     idx_variable = variable.to_index_variable()

File ~\anaconda3\envs\dissenv\lib\site-packages\xarray\core\variable.py:112, in as_variable(obj, name)
    110 elif isinstance(obj, tuple):
    111     if isinstance(obj[1], DataArray):
--> 112         raise TypeError(
    113             "Using a DataArray object to construct a variable is"
    114             " ambiguous, please extract the data using the .data property."
    115         )
    116     try:
    117         obj = Variable(*obj)

TypeError: Using a DataArray object to construct a variable is ambiguous, please extract the data using the .data property.

3. Error while using solver = Eof(biweekly_data.snowmelt.data, weights=wgts)

TypeError                                 Traceback (most recent call last)
Input In [21], in <cell line: 3>()
      1 coslat = np.cos(np.deg2rad(biweekly_data.coords['rlat'].values))
      2 wgts = np.sqrt(coslat)[..., np.newaxis]
----> 3 solver = Eof(biweekly_data.snowmelt.data, weights=wgts)
      5 eof1 = solver.eofs()
      6 pc1  = solver.pcs()

File ~\anaconda3\envs\dissenv\lib\site-packages\eofs\xarray.py:95, in Eof.__init__(self, array, weights, center, ddof)
     36 """Create an Eof object.
     37 
     38 The EOF solution is computed at initialization time. Method
   (...)
     92 
     93 """
     94 if not isinstance(array, xr.DataArray):
---> 95     raise TypeError('the input must be an xarray DataArray')
     96 # Find a time-like dimension, and check if it is the first.
     97 time_coords = find_time_coordinates(array)

TypeError: the input must be an xarray DataArray
mshiv commented 2 years ago

@Pearl-Ayem - possible duplicate of #123? The fix posted was to change line 229 in your xarray.py file

229 eofs.coords.update({coord.name: (coord.dims, coord)
230                     for coord in self._space_ndcoords})

to the following:

229 eofs.coords.update({coord.name: (coord.dims, coord.data)
230                     for coord in self._space_ndcoords})
ajdawson commented 2 years ago

@Pearl-Ayem are you able to check if your issue is resolved in the latest master branch?

anton-seaice commented 1 year ago

@ajdawson. I had the same TypeError: Using a DataArray object to construct a variable is ambiguous, please extract the data using the .data property when using with xarray.

I cloned the master branch and imported that instead, and it works now. Thanks for the fix.

huazai-beyond121 commented 1 year ago

In my problems, i change all the related in the '..lib\site-packages\eofs\xarray.py' file eofs.coords.update({coord.name: (coord.dims, coord) for coord in self._space_ndcoords}) to xxx.coords.update({coord.name: (coord.dims, coord.data) for coord in self._space_ndcoords})

then, the errors are resoved