Accessing data on the USGS LPDAAC server via OPeNDAP protocol

Author

Eli Holmes (NOAA)

Colab Badge JupyterHub Badge Download Badge

Overview

The USGS LPDAAC server requires NASA Earthdata login authentication, but doesn’t require a EULA (as far as I know). However they have similar redirect issues as data that does require a EULA. I could not get the data into an xarray.

Prerequisites

I assume you have a .netrc file at ~ (home). ~/.netrc should look just like this with your username and password.

machine urs.earthdata.nasa.gov
        login yourusername
        password yourpassword

Packages

import xarray as xr
import pydap.client
import pydap

Set up a token-based session with earthaccess

# create an authenticated session
import earthaccess
earthaccess.login()
edl_session = earthaccess.get_requests_https_session()
# if it keeps asking for your password, run this instead to save to .netrc file
auth = earthaccess.login()
# are we authenticated?
if not auth.authenticated:
    # ask for credentials and persist them in a .netrc file
    auth.login(strategy="interactive", persist=True)

USGS LPDAAC

Their OPeNDAP server also uses NASA Earthdata login authentication.

url="https://opendap.cr.usgs.gov/opendap/hyrax/MOD13Q1.061/h09v06.ncml"
# this works
pydap_ds = pydap.client.open_url(url, session=edl_session, protocol="dap4")
# this works too
store = xr.backends.PydapDataStore(pydap_ds)
ds = xr.open_dataset(store)
# this works too
url="dap4://opendap.cr.usgs.gov/opendap/hyrax/MOD13Q1.061/h09v06.ncml"
ds = xr.open_dataset(url, engine="pydap", session=edl_session)
print(f"Dataset size: {ds.nbytes/1e9:.2f} Tb")
Dataset size: 690.46 Tb
ds
<xarray.Dataset> Size: 690GB
Dimensions:                                          (/YDim: 4800, /XDim: 4800,
                                                      /time: 576)
Coordinates:
    Latitude                                         (/YDim, /XDim) float64 184MB ...
    Longitude                                        (/YDim, /XDim) float64 184MB ...
Dimensions without coordinates: /YDim, /XDim, /time
Data variables: (12/16)
    YDim                                             (/YDim) float64 38kB ...
    XDim                                             (/XDim) float64 38kB ...
    MODIS_Grid_16DAY_250m_500m_VI_eos_cf_projection  uint8 1B ...
    _250m_16_days_VI_Quality                         (/time, /YDim, /XDim) float32 53GB ...
    _250m_16_days_red_reflectance                    (/time, /YDim, /XDim) float32 53GB ...
    _250m_16_days_sun_zenith_angle                   (/time, /YDim, /XDim) float32 53GB ...
    ...                                               ...
    _250m_16_days_EVI                                (/time, /YDim, /XDim) float32 53GB ...
    _250m_16_days_composite_day_of_the_year          (/time, /YDim, /XDim) float32 53GB ...
    _250m_16_days_MIR_reflectance                    (/time, /YDim, /XDim) float32 53GB ...
    _250m_16_days_blue_reflectance                   (/time, /YDim, /XDim) float32 53GB ...
    _250m_16_days_NDVI                               (/time, /YDim, /XDim) float32 53GB ...
    time                                             (/time) datetime64[ns] 5kB ...
Attributes:
    HDFEOSVersion:                     HDFEOS_V2.19
    identifier_product_doi:            10.5067/MODIS/MOD13Q1.061
    identifier_product_doi_authority:  http://dx.doi.org
# loading data works
ds["_250m_16_days_VI_Quality"].isel({"/time": 1, "/YDim": 1}).load()
<xarray.DataArray '_250m_16_days_VI_Quality' (/XDim: 4800)> Size: 19kB
array([2116., 2116., 2116., ..., 2116., 2116., 2116.], dtype=float32)
Coordinates:
    Latitude   (/XDim) float64 38kB 30.0 30.0 30.0 30.0 ... 30.0 30.0 30.0 30.0
    Longitude  (/XDim) float64 38kB -103.9 -103.9 -103.9 ... -92.38 -92.37
Dimensions without coordinates: /XDim
Attributes:
    long_name:     250m 16 days VI Quality
    units:         bit field
    valid_range:   [0, 65534]
    Legend:        \n\t Bit Fields Description (Right to Left): \n\t[0-1] : M...
    grid_mapping:  MODIS_Grid_16DAY_250m_500m_VI_eos_cf_projection
    Maps:          ()
# this is another url that works with pydap
url = "https://opendap.cr.usgs.gov/opendap/hyrax/ECOSTRESS/ECO2CLD.001/2018.07.09/ECOSTRESS_L2_CLOUD_00048_001_20180709T204901_0601_03.h5"
pydap_ds = pydap.client.open_url(url, session=edl_session, protocol="dap4")

Setting token-based authentication with pydap

If you don’t want to use earthaccess, here is how to set up token-based authentication with pydap. Go on your Earthdata login user profile to create a token.

edl_token = "put your token here"
import requests
auth_hdr="Bearer " + edl_token
token_session = requests.Session()
token_session.headers={"Authorization": auth_hdr}

Conclusion

Working with USGS data on its OPeNDAP server requires Earthdata authentication. Use token-based authentication to solve redirect errors. earthaccess helps with this.

References