nsidc / earthaccess

Python Library for NASA Earthdata APIs
https://earthaccess.readthedocs.io/
MIT License
416 stars 84 forks source link

search_data() function fails on unexpected keyword argument 'keyattr_enabled' #233

Closed Joshdpaul closed 1 year ago

Joshdpaul commented 1 year ago

Attempting to use search_data() with the package readme example returns an unexpected keyword argument error. The granule search seems to work and the number of granules is returned, but the remainder of the function fails and the 'results' variable is not assigned. Any assistance here would be appreciated, thanks!

import earthaccess
auth = earthaccess.login()

some authentication lines hidden for privacy...

You're now authenticated with NASA Earthdata Login
Using token with expiration date: 06/17/2023
Using user provided credentials for EDL
results = earthaccess.search_data(
    short_name='ATL06',
    version="005",
    cloud_hosted=True,
    bounding_box=(-10, 20, 10, 50),
    temporal=("2020-02", "2020-03"),
    count=100
)

Granules found: 26

TypeError                                 Traceback (most recent call last)
Cell In[17], line 1
----> 1 results = earthaccess.search_data(
      2     short_name='ATL06',
      3     version="005",
      4     cloud_hosted=True,
      5     bounding_box=(-10, 20, 10, 50),
      6     temporal=("2020-02", "2020-03"),
      7     count=100
      8 )

File ~\Anaconda3\envs\earthaccess\Lib\site-packages\earthaccess\api.py:107, in search_data(count, **kwargs)
    105 print(f"Granules found: {granules_found}")
    106 if count > 0:
--> 107     return query.get(count)
    108 return query.get_all()

File ~\Anaconda3\envs\earthaccess\Lib\site-packages\earthaccess\search.py:541, in DataGranules.get(self, limit)
    539     else:
    540         cloud = False
--> 541     latest = list(
    542         DataGranule(granule, cloud_hosted=cloud)
    543         for granule in response.json()["items"]
    544     )
    545 else:
    546     latest = []

File ~\Anaconda3\envs\earthaccess\Lib\site-packages\earthaccess\search.py:542, in <genexpr>(.0)
    539     else:
    540         cloud = False
    541     latest = list(
--> 542         DataGranule(granule, cloud_hosted=cloud)
    543         for granule in response.json()["items"]
    544     )
    545 else:
    546     latest = []

File ~\Anaconda3\envs\earthaccess\Lib\site-packages\earthaccess\results.py:208, in DataGranule.__init__(self, collection, fields, cloud_hosted)
    202 def __init__(
    203     self,
    204     collection: Dict[str, Any],
    205     fields: Optional[List[str]] = None,
    206     cloud_hosted: bool = False,
    207 ):
--> 208     super().__init__(collection)
    209     self.cloud_hosted = cloud_hosted
    210     # TODO: maybe add area, start date and all that as an instance value

File ~\Anaconda3\envs\earthaccess\Lib\site-packages\earthaccess\results.py:20, in CustomDict.__init__(self, collection, fields, cloud_hosted)
     14 def __init__(
     15     self,
     16     collection: Dict[str, Any],
     17     fields: Optional[List[str]] = None,
     18     cloud_hosted: bool = False,
     19 ):
---> 20     super().__init__(collection)
     21     self.cloud_hosted = cloud_hosted
     22     self.uuid = str(uuid.uuid4())

File ~\Anaconda3\envs\earthaccess\Lib\site-packages\benedict\dicts\__init__.py:54, in benedict.__init__(self, *args, **kwargs)
     52     super().__init__(obj.dict(), **kwargs)
     53     return
---> 54 super().__init__(*args, **kwargs)

File ~\Anaconda3\envs\earthaccess\Lib\site-packages\benedict\dicts\keyattr\keyattr_dict.py:11, in KeyattrDict.__init__(self, *args, **kwargs)
      9 self._keyattr_enabled = kwargs.pop("keyattr_enabled", True)
     10 self._keyattr_dynamic = kwargs.pop("keyattr_dynamic", False)
---> 11 super().__init__(*args, **kwargs)

File ~\Anaconda3\envs\earthaccess\Lib\site-packages\benedict\dicts\keypath\keypath_dict.py:13, in KeypathDict.__init__(self, *args, **kwargs)
     11 super().__init__(*args, **kwargs)
     12 if check_keys:
---> 13     keypath_util.check_keys(self, self._keypath_separator)

File ~\Anaconda3\envs\earthaccess\Lib\site-packages\benedict\dicts\keypath\keypath_util.py:22, in check_keys(d, separator)
     17     if key and type_util.is_string(key) and separator in key:
     18         raise ValueError(
     19             f"Key should not contain keypath separator {separator!r}, found: {key!r}."
     20         )
---> 22 traverse(d, check_key)

File ~\Anaconda3\envs\earthaccess\Lib\site-packages\benedict\core\traverse.py:29, in traverse(d, callback)
     27 if not callable(callback):
     28     raise ValueError("callback argument must be a callable.")
---> 29 _traverse_collection(d, callback)

File ~\Anaconda3\envs\earthaccess\Lib\site-packages\benedict\core\traverse.py:6, in _traverse_collection(d, callback)
      4 def _traverse_collection(d, callback):
      5     if type_util.is_dict(d):
----> 6         _traverse_dict(d, callback)
      7     elif type_util.is_list_or_tuple(d):
      8         _traverse_list(d, callback)

File ~\Anaconda3\envs\earthaccess\Lib\site-packages\benedict\core\traverse.py:14, in _traverse_dict(d, callback)
     12 keys = list(d.keys())
     13 for key in keys:
---> 14     value = d.get(key, None)
     15     callback(d, key, value)
     16     _traverse_collection(value, callback)

File ~\Anaconda3\envs\earthaccess\Lib\site-packages\benedict\dicts\__init__.py:158, in benedict.get(self, key, default)
    157 def get(self, key, default=None):
--> 158     return self._cast(super().get(key, default))

File ~\Anaconda3\envs\earthaccess\Lib\site-packages\benedict\dicts\__init__.py:80, in benedict._cast(self, value)
     78 obj_type = type(self)
     79 if isinstance(value, dict) and not isinstance(value, obj_type):
---> 80     return obj_type(
     81         value,
     82         keyattr_enabled=self._keyattr_enabled,
     83         keyattr_dynamic=self._keyattr_dynamic,
     84         keypath_separator=self._keypath_separator,
     85         check_keys=False,
     86     )
     87 elif isinstance(value, list):
     88     for index, item in enumerate(value):

TypeError: DataGranule.__init__() got an unexpected keyword argument 'keyattr_enabled'

results


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[18], line 1
----> 1 results

NameError: name 'results' is not defined
Joshdpaul commented 1 year ago

I am using Python 3.11.3 and earthaccess version 0.5.1

arkottke commented 1 year ago

Same issue on Python 3.10.10

betolink commented 1 year ago

This is probably related to a Benedict dependency issue, we are moving away from it and will have a new release tomorrow!

betolink commented 1 year ago

@arkottke @Joshdpaul can you try installing v0.5.2 and see if this keeps happening?

conda install -c conda-forge earthaccess=0.5.2

or using pip

pip install earthaccess==0.5.2
arkottke commented 1 year ago

It now works for me.

On Fri, Apr 21, 2023 at 7:38 AM Luis López @.***> wrote:

@arkottke https://github.com/arkottke @Joshdpaul https://github.com/Joshdpaul can you try installing v0.5.2 and see if this keeps happening?

conda install -c conda-forge earthaccess=0.5.2

or using pip

pip install earthaccess==0.5.2

— Reply to this email directly, view it on GitHub https://github.com/nsidc/earthaccess/issues/233#issuecomment-1517936147, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAH4LM7L4JU4GJIMKNC7S23XCKLXNANCNFSM6AAAAAAXDFRHEA . You are receiving this because you were mentioned.Message ID: @.***>

Joshdpaul commented 1 year ago

Installing 0.5.2 fixed this issue for me. Thank you!

However, the results list I just generated shows some other issues. The MODIS granules are listed with file sizes of 0MB (which is not true, as the file download URLs link to .hdf files ~8MB). Should this be opened as a new issue? Or do you think its related to the 0.5.2 update?

import earthaccess
import geopandas as gpd
import xarray as xr

auth = earthaccess.login()

some authentication lines omitted for privacy...

You're now authenticated with NASA Earthdata Login
Using token with expiration date: 06/17/2023
extent = gpd.read_file('/shp/extent_mbg.shp')
poly = extent.to_crs(4326)
xy = poly.bounds.values.tolist()[0]
print(xy)

[-166.28104223150558, 56.411541689521265, -122.80983754793994, 69.07918623548356]
modis_lst_results = earthaccess.search_data(short_name='MYD11A2', version='061', bounding_box=(xy[0], xy[1], xy[2], xy[3]), temporal=('2021-06-01', '2021-06-15'))

Granules found: 27

modis_lst_results[0:2]

[Collection: {'ShortName': 'MYD11A2', 'Version': '061'}
 Spatial coverage: {'HorizontalSpatialDomain': {'Geometry': {'GPolygons': [{'Boundary': {'Points': [{'Longitude': -100.03352173756, 'Latitude': 60.0041666666667}, {'Longitude': -80.0285159682453, 'Latitude': 60.0041666666667}, {'Longitude': -116.964383085246, 'Latitude': 69.9958333333333}, {'Longitude': -146.202379163736, 'Latitude': 69.9958333333333}, {'Longitude': -100.03352173756, 'Latitude': 60.0041666666667}]}}]}}}
 Temporal coverage: {'RangeDateTime': {'BeginningDateTime': '2021-05-25T00:00:00.000Z', 'EndingDateTime': '2021-06-01T23:59:59.000Z'}}
 Size(MB): 0
 Data: ['https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/MYD11A2.061/MYD11A2.A2021145.h13v02.061.2021154064507/MYD11A2.A2021145.h13v02.061.2021154064507.hdf'],
 Collection: {'ShortName': 'MYD11A2', 'Version': '061'}
 Spatial coverage: {'HorizontalSpatialDomain': {'Geometry': {'GPolygons': [{'Boundary': {'Points': [{'Longitude': -120.038560848178, 'Latitude': 60.0041666666667}, {'Longitude': -100.033555078863, 'Latitude': 60.0041666666667}, {'Longitude': -146.202427893183, 'Latitude': 69.9958333333333}, {'Longitude': -175.440423971673, 'Latitude': 69.9958333333333}, {'Longitude': -120.038560848178, 'Latitude': 60.0041666666667}]}}]}}}
 Temporal coverage: {'RangeDateTime': {'BeginningDateTime': '2021-05-25T00:00:00.000Z', 'EndingDateTime': '2021-06-01T23:59:59.000Z'}}
 Size(MB): 0
 Data: ['https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/MYD11A2.061/MYD11A2.A2021145.h12v02.061.2021154064609/MYD11A2.A2021145.h12v02.061.2021154064609.hdf']]
Joshdpaul commented 1 year ago

Downloading the files also shows "0.0 GB" when the total size for these granules should be ~150MB

files = earthaccess.download(results, 'F:/GIS/OTHER/JP/files')

Getting 27 granules, approx download size: 0.0 GB

SUBMITTING | : 100%
27/27 [00:00<00:00, 1476.14it/s]
PROCESSING | : 100%
27/27 [00:22<00:00, 1.35it/s]
COLLECTING | : 100%
27/27 [00:00<00:00, 3856.37it/s]
betolink commented 1 year ago

@Joshdpaul You're right, there is a typo on the result's parser, it should still download the files. I'll be releasing a fixed version this week. Thanks for following up!