Harmony API Introduction

This notebook provides an overview of the capabilities offered through the Harmony API, which supports the OpenGIS Web Map Service and the OGC API - Coverages specification. The examples below demonstrate synchronous and asynchronous access of several subsetting and reprojection services available from the Harmony/gdal demo service, native data access for data without transformation services, and the WMS map image service.

Authors: Amy Steiker, Patrick Quinn

Import packages

Most packages below should be included natively with the Anaconda Python distribution, for example, but some may need to install packages like rasterio manually using the following example:

In [1]:
# Install prerequisite packages
import sys
!{sys.executable} -m pip install rasterio OWSLib # Install a pip package in the current Jupyter kernel
In [2]:
from urllib import request, parse
from http.cookiejar import CookieJar
import getpass
import netrc
import os
import requests
import json
import pprint
from osgeo import gdal
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import rasterio
from rasterio.plot import show
import numpy as np
import os
import time
from netCDF4 import Dataset
from owslib.wms import WebMapService
%matplotlib inline

Local directory setup

Specify a local directory where the following Harmony outputs will be saved:

In [3]:
# ---- Change this to save to a directory where you have write permissions
local_dir = 'tmp/output/'

We need some boilerplate up front to log in to Earthdata Login. The function below will allow Python scripts to log into any Earthdata Login application programmatically. To avoid being prompted for credentials every time you run and also allow clients such as curl to log in, you can add the following to a .netrc (_netrc on Windows) file in your home directory:

machine uat.urs.earthdata.nasa.gov
    login <your username>
    password <your password>

Make sure that this file is only readable by the current user or you will receive an error stating "netrc access too permissive."

$ chmod 0600 ~/.netrc

In [4]:
def setup_earthdata_login_auth(endpoint):
    """
    Set up the request library so that it authenticates against the given Earthdata Login
    endpoint and is able to track cookies between requests.  This looks in the .netrc file 
    first and if no credentials are found, it prompts for them.

    Valid endpoints include:
        uat.urs.earthdata.nasa.gov - Earthdata Login UAT (Harmony's current default)
        urs.earthdata.nasa.gov - Earthdata Login production
    """
    try:
        username, _, password = netrc.netrc().authenticators(endpoint)
    except (FileNotFoundError, TypeError):
        # FileNotFound = There's no .netrc file
        # TypeError = The endpoint isn't in the netrc file, causing the above to try unpacking None
        print('Please provide your Earthdata Login credentials to allow data access')
        print('Your credentials will only be passed to %s and will not be exposed in Jupyter' % (endpoint))
        username = input('Username:')
        password = getpass.getpass()

    manager = request.HTTPPasswordMgrWithDefaultRealm()
    manager.add_password(None, endpoint, username, password)
    auth = request.HTTPBasicAuthHandler(manager)

    jar = CookieJar()
    processor = request.HTTPCookieProcessor(jar)
    opener = request.build_opener(auth, processor)
    request.install_opener(opener)

Now call the above function to set up Earthdata Login for subsequent requests

In [5]:
setup_earthdata_login_auth('uat.urs.earthdata.nasa.gov')

Identify a data collection of interest

A CMR collection ID is needed to request services through Harmony. The collection ID can be determined using the CMR API. We will query the corresponding ID of a known collection short name, harmony_example, which is a Level 3 test collection with transformation services available through Harmony.

In [6]:
params = {
    'short_name': 'harmony_example',
} # parameter dictionary with known CMR short_name

cmr_collections_url = 'https://cmr.uat.earthdata.nasa.gov/search/collections.json'
cmr_response = requests.get(cmr_collections_url, params=params)
cmr_results = json.loads(cmr_response.content) # Get json response from CMR collection metadata

collectionlist = [el['id'] for el in cmr_results['feed']['entry']]
harmony_collection_id = collectionlist[0]
print(harmony_collection_id)
C1233800302-EEDTEST

We can also view the harmony_example collection metadata to glean more information about the collection:

In [7]:
pprint.pprint(cmr_results)
{'feed': {'entry': [{'associations': {'services': ['S1237974227-EEDTEST',
                                                   'S1237980031-EEDTEST'],
                                      'variables': ['V1233801695-EEDTEST',
                                                    'V1233801696-EEDTEST',
                                                    'V1233801716-EEDTEST',
                                                    'V1233801717-EEDTEST']},
                     'browse_flag': False,
                     'data_center': 'EEDTEST',
                     'dataset_id': 'Harmony Example Data',
                     'has_formats': True,
                     'has_spatial_subsetting': True,
                     'has_temporal_subsetting': False,
                     'has_transforms': True,
                     'has_variables': True,
                     'id': 'C1233800302-EEDTEST',
                     'online_access_flag': False,
                     'orbit_parameters': {},
                     'original_format': 'ECHO10',
                     'short_name': 'harmony_example',
                     'summary': '    A collection to use in testing Harmony '
                                'whose data have the following attributes, '
                                'useful in testing current    and future '
                                'Harmony work, ensuring that results come back '
                                'correctly, and that metadata is preserved.    '
                                '1. Granule data is very small, under 1MB, '
                                'often well under 1MB    2. Data follows the '
                                'outlines of the continents, making visual '
                                'inspection easy    3. Data follows a '
                                'consistent gradient, with hue differing '
                                'slightly by granule in sequential temporal '
                                'order from       blue/purple (oldest) to red '
                                '(newest)    4. Files have color '
                                'interpretation set, allowing for color '
                                'output, if services preserve it    5. Files '
                                'have 4 variables / bands    6. Data bands '
                                'have descriptions set    7. Files have custom '
                                'metadata, HARMONY_HEX_COLOR, set to the '
                                "central hex value of the file's gradient, and "
                                'HARMONY_HUE, set to the numeric hue '
                                '(0.0-1.0)    8. File names contain useful '
                                'information about their sequential order, '
                                'color, and contents    9. Granules with '
                                'global extents exist, as well as granules '
                                'which cover each continent, with '
                                'corresponding metadata    10. Granule '
                                'temporal aligns to full days (UTC) starting '
                                'with January 1, 2020, with each file name '
                                'starting with the numeric        julian '
                                'date  ',
                     'time_start': '1970-06-26T00:00:00.000Z',
                     'title': 'Harmony Example Data',
                     'updated': '2000-01-01T00:00:00.000Z',
                     'version_id': '1'},
                    {'associations': {'services': ['S1237974301-EEDTEST',
                                                   'S1237980031-EEDTEST'],
                                      'variables': ['V1234088187-EEDTEST',
                                                    'V1234088188-EEDTEST',
                                                    'V1234088189-EEDTEST',
                                                    'V1234088190-EEDTEST']},
                     'browse_flag': False,
                     'data_center': 'EEDTEST',
                     'dataset_id': 'Harmony Example Data v2',
                     'has_formats': True,
                     'has_spatial_subsetting': True,
                     'has_temporal_subsetting': False,
                     'has_transforms': True,
                     'has_variables': True,
                     'id': 'C1234088182-EEDTEST',
                     'online_access_flag': False,
                     'orbit_parameters': {},
                     'original_format': 'ECHO10',
                     'short_name': 'harmony_example',
                     'summary': '    A collection to use in testing Harmony '
                                'whose data have the following attributes, '
                                'useful in testing current    and future '
                                'Harmony work, ensuring that results come back '
                                'correctly, and that metadata is preserved.    '
                                '1. Granule data is very small, under 1MB, '
                                'often well under 1MB    2. Data follows the '
                                'outlines of the continents, making visual '
                                'inspection easy    3. Data follows a '
                                'consistent gradient, with hue differing '
                                'slightly by granule in sequential temporal '
                                'order from       blue/purple (oldest) to red '
                                '(newest)    4. Files have color '
                                'interpretation set, allowing for color '
                                'output, if services preserve it    5. Files '
                                'have 4 variables / bands    6. Data bands '
                                'have descriptions set    Differences from '
                                'v1:    1. Produced via the NetCDF4 API, with '
                                'deliberate chunking of 16 chunks per '
                                'variable    2. File custom metadata renamed '
                                'to HarmonyHexColor, set to the central hex '
                                "value of the file's gradient, and HarmonyHue, "
                                'set to the numeric hue (0.0-1.0)    3. Each '
                                'geographic area is separated to a different '
                                'month with each sub-file as the same day of '
                                'that month    4. File names are improved to '
                                'have a year-month-day format  ',
                     'time_start': '1970-06-26T00:00:00.000Z',
                     'title': 'Harmony Example Data v2',
                     'updated': '2000-01-01T00:00:00.000Z',
                     'version_id': '2'}],
          'id': 'https://cmr.uat.earthdata.nasa.gov:443/search/collections.json?short_name=harmony_example',
          'title': 'ECHO dataset metadata',
          'updated': '2020-11-18T15:46:58.152Z'}}

Determine service availability

We will determine what services are available for the harmony_example collection based on the services.yml file available in the Harmony repository.

In [8]:
yml_path = str(os.getcwd() + '/../config/services.yml')

with open(yml_path, 'r') as yml:
    data = yml.read()
    print(data)
# Order for each CMR endpoint in this file will reflect precedence of the service when
# multiple services handle a collection

# Default turbo configuration
x-turbo-config: &default-turbo-config
  name: turbo
  params: &default-turbo-params
    env: &default-turbo-env
      USE_LOCALSTACK: !Env ${USE_LOCALSTACK}
      AWS_DEFAULT_REGION: us-west-2
      STAGING_BUCKET: !Env ${STAGING_BUCKET}
      TEXT_LOGGER: !Env ${TEXT_LOGGER}
      BACKEND_HOST: !Env ${BACKEND_HOST}
      EDL_USERNAME: !Env ${EDL_USERNAME}
      EDL_PASSWORD: !Env ${EDL_PASSWORD}
      OAUTH_UID: !Env ${OAUTH_UID}
      OAUTH_PASSWORD: !Env ${OAUTH_PASSWORD}
      OAUTH_HOST: !Env ${OAUTH_HOST}
      OAUTH_CLIENT_ID: !Env ${OAUTH_CLIENT_ID}
      OAUTH_REDIRECT_URI: !Env ${OAUTH_REDIRECT_URI}
      FALLBACK_AUTHN_ENABLED: !Env ${FALLBACK_AUTHN_ENABLED}

https://cmr.earthdata.nasa.gov:
  - name: asfdataservices/gdal-subsetter
    data_operation_version: '0.9.0'
    type:
      <<: *default-turbo-config
      params:
        <<: *default-turbo-params
        template: asf-gdal-subsetter
        image: !Env ${ASF_GDAL_IMAGE}
        image_pull_policy: !Env ${ASF_GDAL_IMAGE_PULL_POLICY}
        env:
          <<: *default-turbo-env
          STAGING_PATH: public/asfdataservices/gdal-subsetter
    collections:
      - C1595422627-ASF
      - C1214354031-ASF
      - C1808440897-ASF
    capabilities:
      subsetting:
        bbox: true
        variable: true
        multiple_variable: true
      output_formats:
        - image/tiff
        - image/png
        - image/gif
      reprojection: true

  - name: harmony/gdal
    data_operation_version: '0.9.0'
    type:
      <<: *default-turbo-config
      params:
        <<: *default-turbo-params
        template: harmony-gdal
        image: !Env ${GDAL_IMAGE}
        image_pull_policy: !Env ${GDAL_IMAGE_PULL_POLICY}
        env:
          <<: *default-turbo-env
          STAGING_PATH: public/harmony/gdal
    collections:
      - C1756916832-XYZ_PROV
    capabilities:
      subsetting:
        bbox: true
        variable: true
        multiple_variable: true
      output_formats:
        - image/tiff
        - image/png
        - image/gif
      reprojection: true

  - name: podaac/l2-subsetter
    data_operation_version: '0.9.0'
    type:
      <<: *default-turbo-config
      params:
        <<: *default-turbo-params
        template: podaac-l2-subsetter
        image: !Env ${PODAAC_L2_SUBSETTER_IMAGE}
        image_pull_policy: !Env ${PODAAC_L2_SUBSETTER_IMAGE_PULL_POLICY}
        env:
          <<: *default-turbo-env
          STAGING_PATH: public/podaac/l2-subsetter
    collections:
      - C1940473819-POCLOUD
      - C1940475563-POCLOUD
      - C1940466008-POCLOUD
    capabilities:
      subsetting:
        bbox: true
        variable: true
      output_formats:
        - application/netcdf # Incorrect mime-type, remove when no longer needed
        - application/x-netcdf4

https://cmr.uat.earthdata.nasa.gov:

  - name: asfdataservices/gdal-subsetter
    data_operation_version: '0.9.0'
    type:
      <<: *default-turbo-config
      params:
        <<: *default-turbo-params
        template: asf-gdal-subsetter
        image: !Env ${ASF_GDAL_IMAGE}
        image_pull_policy: !Env ${ASF_GDAL_IMAGE_PULL_POLICY}
        env:
          <<: *default-turbo-env
          STAGING_PATH: public/asfdataservices/gdal-subsetter
    collections:
      - C1225776654-ASF
      - C1207038647-ASF
      - C1233629671-ASF
    capabilities:
      subsetting:
        bbox: true
        variable: true
        multiple_variable: true
      output_formats:
        - image/tiff
        - image/png
        - image/gif
      reprojection: true

  - name: harmony/gdal
    data_operation_version: '0.9.0'
    type:
      <<: *default-turbo-config
      params:
        <<: *default-turbo-params
        template: harmony-gdal
        image: !Env ${GDAL_IMAGE}
        image_pull_policy: !Env ${GDAL_IMAGE_PULL_POLICY}
        env:
          <<: *default-turbo-env
          STAGING_PATH: public/harmony/gdal
    collections:
      - C1233800302-EEDTEST
      - C1234088182-EEDTEST
    capabilities:
      subsetting:
        bbox: true
        variable: true
        multiple_variable: true
      output_formats:
        - image/tiff
        - image/png
        - image/gif
      reprojection: true

  - name: podaac/l2-subsetter
    data_operation_version: '0.9.0'
    type:
      <<: *default-turbo-config
      params:
        <<: *default-turbo-params
        template: podaac-l2-subsetter
        image: !Env ${PODAAC_L2_SUBSETTER_IMAGE}
        image_pull_policy: !Env ${PODAAC_L2_SUBSETTER_IMAGE_PULL_POLICY}
        env:
          <<: *default-turbo-env
          STAGING_PATH: public/podaac/l2-subsetter
    collections:
      - C1234208436-POCLOUD
      - C1234208437-POCLOUD
      - C1234208438-POCLOUD
      - C1234724470-POCLOUD
      - C1234724471-POCLOUD
      - C1234071416-POCLOUD
    capabilities:
      subsetting:
        bbox: true
        variable: true
      output_formats:
        - application/netcdf # Incorrect mime-type, remove when no longer needed
        - application/x-netcdf4

  - name: sds/swath-projector
    data_operation_version: '0.9.0'
    type:
      <<: *default-turbo-config
      params:
        <<: *default-turbo-params
        template: swath-projector
        image: !Env ${SWATH_PROJECTOR_IMAGE}
        image_pull_policy: !Env ${SWATH_PROJECTOR_IMAGE_PULL_POLICY}
        env:
          <<: *default-turbo-env
          STAGING_PATH: public/sds/swath-projector
    collections:
      - C1233860183-EEDTEST
      - C1233800302-EEDTEST
      - C1221286860-NSIDC_TS1
      - C1226288788-EDF_DEV07
      - C1233147317-EEDTEST
      - C1233147319-EEDTEST
      - C1234724470-POCLOUD
    capabilities:
      subsetting:
        bbox: false
        variable: false
      output_formats:
        - image/tiff
        - image/png
        - image/gif
        - application/netcdf # Incorrect mime-type, remove when no longer needed
        - application/x-netcdf4
      reprojection: true

  - name: sds/variable-subsetter
    data_operation_version: '0.9.0'
    type:
      <<: *default-turbo-config
      params:
        <<: *default-turbo-params
        template: var-subsetter
        image: !Env ${VAR_SUBSETTER_IMAGE}
        image_pull_policy: !Env ${VAR_SUBSETTER_IMAGE_PULL_POLICY}
        env:
          <<: *default-turbo-env
          STAGING_PATH: public/sds/variable-subsetter
    collections:
      - C1234714691-EEDTEST  # ATL03
      - C1234714698-EEDTEST  # ATL08
    capabilities:
      subsetting:
        variable: true
      output_formats:
        - application/netcdf # Incorrect mime-type, remove when no longer needed
        - application/x-netcdf4

  # This is an example service and backend from example/http-backend.js mounted by
  # the frontend callback server.
  # EOSS Example: curl -Lnbj 'http://localhost:3000/C1104-PVC_TS2/eoss/0.2.0/items/G1216319051-PVC_TS2'
  - name: harmony/example
    data_operation_version: '0.9.0'
    enabled: !Env ${EXAMPLE_SERVICES}
    type:
      name: http
      params:
        url: http://localhost:4000/example/harmony
    collections:
      # AMSR-E/Aqua L2B Global Swath Ocean Products derived from Wentz Algorithm V086
      # Good example, being in UAT, global, many public non-global granules,
      # and not yet on the services roadmap.
      - C1104-PVC_TS2
    capabilities:
      subsetting:
        variable: true
        bbox: true
      output_formats:
        - image/tiff
      reprojection: true

  # This is an example service and backend from example/http-backend.js mounted by
  # the frontend callback server.
  - name: harmony/chaining-example
    data_operation_version: '0.9.0'
    type:
      <<: *default-turbo-config
      params:
        <<: *default-turbo-params
        # Minimal parameters for current partial chaining implementation
        image: harmony/query-cmr:latest
        template_type: chaining
        env:
          <<: *default-turbo-env
    collections:
      # AMSR-E/Aqua L2A Global Swath Spatially-Resampled Brightness Temperatures (Tb) V086
      # Good example, being in UAT, global, many public non-global granules,
      # and not yet on the services roadmap.
      - C1096-PVC_TS2
    capabilities:
      subsetting:
        variable: true
        bbox: true
      output_formats:
        - image/tiff
      reprojection: true

   # This is an example service using a result handler
  - name: harmony/result-handler-example
    data_operation_version: '0.9.0'
    type:
      <<: *default-turbo-config
      params:
        <<: *default-turbo-params
        image: harmony/query-cmr:latest
        template: test-chain-with-result-handler
        image_pull_policy: !Env ${DEFAULT_IMAGE_PULL_POLICY}
        env:
          <<: *default-turbo-env
          STAGING_PATH: public/harmony/result-handler-example
    collections:
      # AMSR-E/Aqua L2A Global Swath Spatially-Resampled Brightness Temperatures (Tb) V086
      # Good example, being in UAT, global, many public non-global granules,
      # and not yet on the services roadmap.
      - C1096-PVC_TS2
    capabilities:
      subsetting:
        bbox: false
        variable: false
      output_formats:
        - image/tiff
        - image/png
        - image/gif
        - application/netcdf # Incorrect mime-type, remove when no longer needed
        - application/x-netcdf4
      reprojection: true

  # PO.DAAC Shapefiles
  - name: podaac/ps3
    data_operation_version: '0.9.0'
    type:
      <<: *default-turbo-config
      params:
        <<: *default-turbo-params
        template: podaac-ps3
        image: !Env ${PODAAC_PS3_IMAGE}
        image_pull_policy: !Env ${PODAAC_PS3_IMAGE_PULL_POLICY}
        env:
          <<: *default-turbo-env
          STAGING_PATH: public/podaac/ps3
    collections:
      - C1234530532-EEDTEST
      - C1234530533-EEDTEST
    capabilities:
      subsetting:
        shape: true
        variable: false
      output_formats:
        - application/shapefile+zip

  # PO.DAAC NetCDF to COG
  - name: podaac/netcdf-converter
    data_operation_version: '0.9.0'
    type:
      <<: *default-turbo-config
      params:
        <<: *default-turbo-params
        template: podaac-netcdf-converter
        image: !Env ${PODAAC_NETCDF_CONVERTER_IMAGE}
        image_pull_policy: !Env ${PODAAC_NETCDF_CONVERTER_IMAGE_PULL_POLICY}
        env:
          <<: *default-turbo-env
          STAGING_PATH: public/podaac/netcdf-converter
    collections:
      - C1234410736-POCLOUD
    maximum_sync_granules: 0
    capabilities:
      subsetting:
        shape: false
        variable: false
      output_formats:
        - image/tiff

  - name: harmony/netcdf-to-zarr
    data_operation_version: '0.9.0'
    is_batched: true
    max_batch_inputs: 100
    type:
      <<: *default-turbo-config
      params:
        <<: *default-turbo-params
        template: harmony-netcdf-to-zarr
        image: !Env ${NETCDF_TO_ZARR_IMAGE}
        image_pull_policy: !Env ${NETCDF_TO_ZARR_IMAGE_PULL_POLICY}
        env:
          <<: *default-turbo-env
          STAGING_PATH: public/harmony/netcdf-to-zarr
    collections:
      - C1234088182-EEDTEST
      - C1233800302-EEDTEST
      - C1233860183-EEDTEST
      - C1234410736-POCLOUD
      - C1234082763-POCLOUD
      - C1234071416-POCLOUD
      - C1234208437-POCLOUD
      - C1234208436-POCLOUD
      - C1234208438-POCLOUD
      - C1234724470-POCLOUD
      - C1234724471-POCLOUD
    maximum_sync_granules: 0
    capabilities:
      subsetting:
        variable: false
      output_formats:
        - application/x-zarr

According to the services.yml, our C1233800302-EEDTEST collection is associated with the harmony/gdal service with bounding box and variable subsetting, reprojection, and reformatting. We will request these services below.

Explore the Harmony Root URL

Harmony conforms to the OGC API - Coverages specification: https://github.com/opengeospatial/ogc_api_coverages.

The basic Harmony URL convention is as follows:

<harmony_root>/<collection_id>/ogc-api-coverages/1.0.0/

We will set the Harmony root path with our chosen collection id:

In [9]:
harmony_root = 'https://harmony.uat.earthdata.nasa.gov'
config = {
    'collection_id': harmony_collection_id,
    'ogc-api-coverages_version': '1.0.0'
}
coverages_root = harmony_root+'/{collection_id}/ogc-api-coverages/{ogc-api-coverages_version}/'.format(**config)
print('Request URL', coverages_root)
Request URL https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/

This root URL of the coverages endpoint provides links to its child resources:

In [10]:
root_response = request.urlopen(coverages_root)
root_results = root_response.read()
root_json = json.loads(root_results.decode('utf-8'))
pprint.pprint(root_json)
{'links': [{'href': 'https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/',
            'rel': 'self',
            'title': 'this document',
            'type': 'application/json'},
           {'href': 'https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/api',
            'rel': 'service-desc',
            'title': 'the API definition',
            'type': 'text/openapi+yaml;version=3.0'},
           {'href': 'https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/conformance',
            'rel': 'conformance',
            'title': 'OGC conformance classes implemented by this API',
            'type': 'application/json'},
           {'href': 'https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections',
            'rel': 'data',
            'title': 'Metadata about the resource collections',
            'type': 'application/json'}]}

The service_desc endpoint contains OpenAPI documentation, including information on all supported request parameters:

In [11]:
service_desc = harmony_root+'/{collection_id}/ogc-api-coverages/{ogc-api-coverages_version}/api/'.format(**config)
service_response = request.urlopen(service_desc)
service_results = service_response.read()
service_txt = service_results.decode('utf-8')
print(service_txt)
description: A coverage's rangetype.
          content:
            application/geo+json:
              schema:
                $ref: http://schemas.opengis.net/cis/1.1/json/coverage-schema.json#/definitions/rangeType
            text/html:
              schema:
                type: string
        default:
          $ref: '#/components/responses/default'
  /collections/{collectionId}/coverage/metadata:
    get:
      tags:
      - Coverage
      summary: (Not yet implemented) retrieve a coverage's metadata; use content negotiation to request
        HTML or GeoJSON
      description: Not yet implemented
      operationId: getCoverageMetadata
      parameters:
      - $ref: '#/components/parameters/collectionId'
      responses:
        "200":
          description: A coverage's metadata.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/coverageMetadata'
            text/html:
              schema:
                type: string
        default:
          $ref: '#/components/responses/default'
  /collections/{collectionId}/coverage/rangeset:
    get:
      tags:
      - Coverage
      summary: Retrieve a coverage's rangeset
      description: Retrieve the coverage's rangeset, i.e. its data values in their native format
      operationId: getCoverageRangeset
      parameters:
      - $ref: '#/components/parameters/collectionId'
      - $ref: '#/components/parameters/outputCrs'
      - $ref: '#/components/parameters/subset'
      - $ref: '#/components/parameters/interpolation'
      - $ref: '#/components/parameters/scaleExtent'
      - $ref: '#/components/parameters/scaleSize'
      # Parameters below this line are not part of the OGC specification
      - $ref: '#/components/parameters/granuleId'
      - $ref: '#/components/parameters/width'
      - $ref: '#/components/parameters/height'
      - $ref: '#/components/parameters/format'
      - $ref: '#/components/parameters/forceAsync'
      - $ref: '#/components/parameters/maxResults'
      responses:
        "200":
          description: A coverage's range set.
          content:
            image/*:
              schema:
                $ref: '#/components/schemas/rangeSetImage'
            application/*:
              schema:
                $ref: '#/components/schemas/rangeSetImage'
        default:
          $ref: '#/components/responses/default'
    post:
      tags:
      - Coverage
      summary: Retrieve a coverage's rangeset
      description: Retrieve the coverage's rangeset, i.e. its data values in their native format
      operationId: postCoverageRangeset
      parameters:
      - $ref: '#/components/parameters/collectionId'
      - $ref: '#/components/parameters/outputCrs'
      - $ref: '#/components/parameters/subset'
      - $ref: '#/components/parameters/interpolation'
      - $ref: '#/components/parameters/scaleExtent'
      - $ref: '#/components/parameters/scaleSize'
      # Parameters below this line are not part of the OGC specification
      - $ref: '#/components/parameters/granuleId'
      - $ref: '#/components/parameters/width'
      - $ref: '#/components/parameters/height'
      - $ref: '#/components/parameters/format'
      - $ref: '#/components/parameters/forceAsync'
      - $ref: '#/components/parameters/maxResults'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                shapefile:
                  type: string
                  format: binary
            encoding:
              shapefile:
                contentType: 'application/geo+json,application/shapefile+zip,application/vnd.google-earth.kml+xml'

      responses:
        "200":
          description: A coverage's range set.
          content:
            image/*:
              schema:
                $ref: '#/components/schemas/rangeSetImage'
            application/*:
              schema:
                $ref: '#/components/schemas/rangeSetImage'
        default:
          $ref: '#/components/responses/default'
  /collections/{collectionId}/coverage/all:
    get:
      tags:
      - Coverage
      summary: (Not yet implemented) retrieve a coverages rangeset; use content negotiation to request HTML
        or GeoJSON
      description: Not yet implemented
      operationId: getCoverageAll
      parameters:
      - $ref: '#/components/parameters/collectionId'
      - $ref: '#/components/parameters/subset'
      - $ref: '#/components/parameters/rangeSubset'
      - $ref: '#/components/parameters/scaleFactor'
      - $ref: '#/components/parameters/scaleAxis'
      - $ref: '#/components/parameters/scaleSize'
      - $ref: '#/components/parameters/scaleExtent'
      - $ref: '#/components/parameters/subsettingCrs'
      - $ref: '#/components/parameters/outputCrs'
      - $ref: '#/components/parameters/interpolation'
      responses:
        "200":
          description: A full coverage.
          content:
            application/multipart+related:
              schema:
                $ref: '#/components/schemas/coverageMultipart'
            image/*:
              schema:
                $ref: '#/components/schemas/rangeSetImage'
            application/*:
              schema:
                $ref: '#/components/schemas/rangeSetImage'
            text/html:
              schema:
                type: string
        default:
          $ref: '#/components/responses/default'
components:
  responses:
    default:
      description: An error occured.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/exception'
        text/html:
          schema:
            type: string
  schemas:
    exception:
      required:
      - code
      type: object
      properties:
        code:
          type: string
        description:
          type: string
    root:
      required:
      - links
      type: object
      properties:
        links:
          type: array
          example:
          - href: http://data.example.org/
            rel: self
            type: application/json
            title: this document
          - href: http://data.example.org/api
            rel: service
            type: application/openapi+json;version=3.0
            title: the API definition
          - href: http://data.example.org/conformance
            rel: conformance
            type: application/json
            title: OGC conformance classes implemented by this API
          - href: http://data.example.org/collections
            title: Metadata about the resource collections
          items:
            $ref: '#/components/schemas/link'
    req-classes:
      required:
      - conformsTo
      type: object
      properties:
        conformsTo:
          type: array
          example:
          - http://www.opengis.net/spec/ogcapi-common/1.0/conf/core
          - http://www.opengis.net/spec/ogcapi-common/1.0/conf/collections
          - http://www.opengis.net/spec/ogcapi-common/1.0/conf/oas3
          - http://www.opengis.net/spec/ogcapi-common/1.0/conf/html
          - http://www.opengis.net/spec/ogcapi-common/1.0/conf/geojson
          - http://www.opengis.net/spec/ogcapi-coverages/1.0/conf/core
          items:
            type: string
    link:
      required:
      - href
      type: object
      properties:
        href:
          type: string
        rel:
          type: string
          example: prev
        type:
          type: string
          example: application/geo+json
        hreflang:
          type: string
          example: en
    content:
      required:
      - collections
      - links
      type: object
      properties:
        links:
          type: array
          example:
          - href: http://data.example.org/collections.json
            rel: self
            type: application/json
            title: this document
          - href: http://data.example.org/collections.html
            rel: alternate
            type: text/html
            title: this document as HTML
          - href: http://schemas.example.org/1.0/foobar.xsd
            rel: describedBy
            type: application/xml
            title: XML schema for Acme Corporation data
          items:
            $ref: '#/components/schemas/link'
        collections:
          type: array
          items:
            $ref: '#/components/schemas/collectionInfo'
    collectionInfo:
      required:
      - links
      - name
      type: object
      properties:
        name:
          type: string
          description: identifier of the collection used, for example, in URIs
          example: buildings
        title:
          type: string
          description: human readable title of the collection
          example: Buildings
        description:
          type: string
          description: a description of the data in the collection
          example: Buildings in the city of Bonn.
        links:
          type: array
          example:
          - href: http://data.example.org/collections/buildings/items
            rel: item
            type: application/geo+json
            title: Buildings
          - href: http://example.org/concepts/building.html
            rel: describedBy
            type: text/html
            title: Coverage for buildings
          items:
            $ref: '#/components/schemas/link'
        extent:
          $ref: '#/components/schemas/extent'
        crs:
          type: array
          description: The coordinate reference systems in which geometries may be
            retrieved. Coordinate reference systems are identified by a URI. The first
            coordinate reference system is the coordinate reference system that is
            used by default. This is always "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
            i.e. WGS84 longitude/latitude.
          items:
            type: string
          default:
          - http://www.opengis.net/def/crs/OGC/1.3/CRS84
    extent:
      type: object
      properties:
        crs:
          type: string
          description: Coordinate reference system of the coordinates in the spatial
            extent (property `spatial`). In the Core, only WGS84 longitude/latitude
            is supported. Extensions may support additional coordinate reference systems.
          default: http://www.opengis.net/def/crs/OGC/1.3/CRS84
          enum:
          - http://www.opengis.net/def/crs/OGC/1.3/CRS84
        spatial:
          maxItems: 6
          minItems: 4
          type: array
          description: West, north, east, south edges of the spatial extent. The minimum
            and maximum values apply to the coordinate reference system WGS84 longitude/latitude
            that is supported in the Core. If, for example, a projected coordinate
            reference system is used, the minimum and maximum values need to be adjusted.
          example:
          - -180
          - -90
          - 180
          - 90
          items:
            type: number
        trs:
          type: string
          description: Temporal reference system of the coordinates in the temporal
            extent (property `temporal`). In the Core, only the Gregorian calendar
            is supported. Extensions may support additional temporal reference systems.
          default: http://www.opengis.net/def/uom/ISO-8601/0/Gregorian
          enum:
          - http://www.opengis.net/def/uom/ISO-8601/0/Gregorian
        temporal:
          maxItems: 2
          minItems: 2
          type: array
          description: Begin and end times of the temporal extent.
          example:
          - 2011-11-11T12:22:11.000Z
          - 2012-11-24T12:32:43.000Z
          items:
            type: string
            format: dateTime
    coverageOffering:
      type: string
    coverageDescription:
      type: string
    coverageMetadata:
      type: string
    coverageMultipart:
      type: string
    rangeSetImage:
      type: string
  parameters:
    limit:
      name: limit
      in: query
      description: |
        The optional limit parameter limits the number of items that are
        presented in the response document.

        Only items are counted that are on the first level of the collection in
        the response document. Nested objects contained within the explicitly
        requested items shall not be counted.

        * Minimum = 1
        * Maximum = 10000
        * Default = 10
      required: false
      style: form
      explode: false
      schema:
        maximum: 10000
        minimum: 1
        type: integer
        default: 10
    bbox:
      name: bbox
      in: query
      description: |
        Only collections that have a geometry that intersects the bounding box are selected. The bounding box is provided as four or six numbers, depending on whether the coordinate reference system includes a vertical axis (elevation or depth):
        * Lower left corner, coordinate axis 1 * Lower left corner, coordinate axis 2 * Lower left corner, coordinate axis 3 (optional) * Upper right corner, coordinate axis 1 * Upper right corner, coordinate axis 2 * Upper right corner, coordinate axis 3 (optional)
        The coordinate reference system of the values is WGS84 longitude/latitude (http://www.opengis.net/def/crs/OGC/1.3/CRS84) unless a different coordinate reference system is specified in the parameter `bbox-crs`.
        For WGS84 longitude/latitude the values are in most cases the sequence of minimum longitude, minimum latitude, maximum longitude and maximum latitude. However, in cases where the box spans the antimeridian the first value (west-most box edge) is larger than the third value (east-most box edge).
        If a collection has multiple spatial geometry properties, it is the decision of the server whether only a single spatial geometry property is used to determine the extent or all relevant geometries.
      required: false
      style: form
      explode: false
      schema:
        maxItems: 6
        minItems: 4
        type: array
        items:
          type: number
    time:
      name: time
      in: query
      description: |-
        Either a date-time or a period string that adheres to RFC 3339. Examples:
        * A date-time: "2018-02-12T23:20:50Z" * A period: "2018-02-12T00:00:00Z/2018-03-18T12:31:12Z" or "2018-02-12T00:00:00Z/P1M6DT12H31M12S"
        Only collections that have a temporal property that intersects the value of `time` are selected.
        If a collection has multiple temporal properties, it is the decision of the server whether only a single temporal property is used to determine the extent or all relevant temporal properties.
      required: false
      style: form
      explode: false
      schema:
        type: string
    collectionId:
      name: collectionId
      in: path
      description: |-
        Names or concept ids of the UMM-Var variables to be retrieved, or "all" to retrieve all variables within the CMR collection(s).
        Multiple variables may be retrieved by separating them with a comma.  This API interprets OGC "collections" to be
        equivalent to CMR "variables" which produces some overloading in the name.  In this document, a "collection" is
        a CMR / UMM-Var variable and a "CMR collection" is a CMR / UMM-C collection.
      required: true
      style: simple
      explode: false
      schema:
        type: string
    granuleId:
      name: granuleId
      in: query
      description: The CMR Granule ID for the granule which should be retrieved
      required: false
      style: form
      explode: true
      schema:
        type: array
        items:
          type: string
          minLength: 1
    subset:
      name: subset
      in: query
      description: '
        get a subset of the coverage by slicing or trimming among one axis.  Harmony supports
        the axes "lat" and "lon" for spatial subsetting, regardless of the names of those axes in the data
        files.  Examples:
          - Subset to the lat/lon bounding box with southwest corner (-10, -10) and northeast corner (10, 10)
            subset=lat(-10:10)&subset=lon(-10:10)
          - Subset to all latitudes north of -10 degrees and all longitudes west of 10 degrees
            subset=lat(-10:*)&subset=lon(*:10)
          - Subset to only points with latitudes from -10 to 10 degrees, disregarding longitude
            subset=lat(-10:10)

        For full syntax and examples, see
        https://github.com/opengeospatial/ogc_api_coverages/blob/master/standard/clause_9_subset.adoc'
      required: false
      style: form
      explode: true
      schema:
        type: array
        items:
          type: string
    rangeSubset:
      name: rangeSubset
      in: query
      description: subset the resulting coverage by choosing and/or rearrange particular
        fields
      required: false
      style: form
      explode: true
      schema:
        type: string
    scaleFactor:
      name: scaleFactor
      in: query
      description: scale the resulting coverage either among all axes by a given factor
      required: false
      style: form
      explode: true
      schema:
        type: string
    scaleAxis:
      name: scaleAxis
      in: query
      description: scale the resulting coverage either among one axis by a given factor
      required: false
      style: form
      explode: true
      schema:
        type: string
    scaleSize:
      name: scaleSize
      in: query
      description: scale the resulting coverage either among one axis to a given size
      required: false
      style: form
      explode: false
      schema:
        minItems: 2
        maxItems: 2
        type: array
        items:
          type: number
          minimum: 0
    scaleExtent:
      name: scaleExtent
      in: query
      description: scale the resulting coverage either among one axis to a given extent
      required: false
      style: form
      explode: false
      schema:
        minItems: 4
        maxItems: 4
        type: array
        items:
          type: number
    subsettingCrs:
      name: subsettingcrs
      in: query
      description: specify the projection in which the subsets are expressed
      required: false
      style: form
      explode: true
      schema:
        type: string
    outputCrs:
      name: outputcrs
      in: query
      description: reproject the output coverage to the given CRS.  Recognizes CRS types that can be inferred
        by gdal, including EPSG codes, Proj4 strings, and OGC URLs (http://www.opengis.net/def/crs/...)
      required: false
      style: form
      explode: true
      schema:
        type: string
    interpolation:
      name: interpolation
      in: query
      description: specify the interpolation method used during reprojection and scaling
      required: false
      style: form
      explode: true
      schema:
        type: string
    width:
      name: width
      in: query
      description: number of columns to return in the output coverage
      required: false
      schema:
        type: integer
        minimum: 1
    height:
      name: height
      in: query
      description: number of rows to return in the output coverage
      required: false
      schema:
        type: integer
        minimum: 1
    format:
      name: format
      in: query
      description: the output mime type to return
      schema:
        type: string
        example:
          - 'application/x-zarr'
          - 'image/tiff'
          - 'image/png'
    forceAsync:
      name: forceAsync
      in: query
      description: if "true", override the default API behavior and always treat the request as asynchronous
      required: false
      schema:
        type: boolean
    maxResults:
      name: maxResults
      in: query
      description: limits the number of input granules processed in the request
      required: false
      schema:
        type: integer
        minimum: 1

The conformance endpoint provides the specifications this API conforms to:

In [12]:
conform_desc = harmony_root+'/{collection_id}/ogc-api-coverages/{ogc-api-coverages_version}/conformance/'.format(**config)
conform_response = request.urlopen(conform_desc)
conform_results = conform_response.read()
conform_json = json.loads(conform_results.decode('utf-8'))
print(conform_json)
{'conformsTo': ['http://www.opengis.net/spec/ogcapi-common-1/1.0/conf/core', 'http://www.opengis.net/spec/ogcapi-common-1/1.0/conf/collections', 'http://www.opengis.net/spec/ogcapi-coverages-1/1.0/conf/core']}

The collections endpoint provides metadata on the resource collections, which include variable metadata from CMR's UMM-Var schema in this example:

In [13]:
collections_desc = harmony_root+'/{collection_id}/ogc-api-coverages/{ogc-api-coverages_version}/collections/'.format(**config)
collections_response = request.urlopen(collections_desc)
collections_results = collections_response.read()
collections_json = json.loads(collections_results.decode('utf-8'))
pprint.pprint(collections_json)
{'collections': [{'description': 'All variables harmony_example v1 (EEDTEST)',
                  'extent': {'temporal': {'interval': ['1970-06-26T00:00:00.000Z',
                                                       None],
                                          'trs': 'http://www.opengis.net/def/uom/ISO-8601/0/Gregorian'}},
                  'id': 'C1233800302-EEDTEST/all',
                  'itemType': 'Variable',
                  'links': [{'href': 'https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset',
                             'title': 'Perform rangeset request for all'}],
                  'title': 'all harmony_example v1'},
                 {'description': 'Alpha channel  harmony_example v1 (EEDTEST)',
                  'extent': {'temporal': {'interval': ['1970-06-26T00:00:00.000Z',
                                                       None],
                                          'trs': 'http://www.opengis.net/def/uom/ISO-8601/0/Gregorian'}},
                  'id': 'C1233800302-EEDTEST/V1233801717-EEDTEST',
                  'itemType': 'Variable',
                  'links': [{'href': 'https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections/alpha_var/coverage/rangeset',
                             'title': 'Perform rangeset request for '
                                      'alpha_var'}],
                  'title': 'alpha_var harmony_example v1'},
                 {'description': 'Blue channel harmony_example v1 (EEDTEST)',
                  'extent': {'temporal': {'interval': ['1970-06-26T00:00:00.000Z',
                                                       None],
                                          'trs': 'http://www.opengis.net/def/uom/ISO-8601/0/Gregorian'}},
                  'id': 'C1233800302-EEDTEST/V1233801716-EEDTEST',
                  'itemType': 'Variable',
                  'links': [{'href': 'https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections/blue_var/coverage/rangeset',
                             'title': 'Perform rangeset request for blue_var'}],
                  'title': 'blue_var harmony_example v1'},
                 {'description': 'Green channel harmony_example v1 (EEDTEST)',
                  'extent': {'temporal': {'interval': ['1970-06-26T00:00:00.000Z',
                                                       None],
                                          'trs': 'http://www.opengis.net/def/uom/ISO-8601/0/Gregorian'}},
                  'id': 'C1233800302-EEDTEST/V1233801696-EEDTEST',
                  'itemType': 'Variable',
                  'links': [{'href': 'https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections/green_var/coverage/rangeset',
                             'title': 'Perform rangeset request for '
                                      'green_var'}],
                  'title': 'green_var harmony_example v1'},
                 {'description': 'Red Channel harmony_example v1 (EEDTEST)',
                  'extent': {'temporal': {'interval': ['1970-06-26T00:00:00.000Z',
                                                       None],
                                          'trs': 'http://www.opengis.net/def/uom/ISO-8601/0/Gregorian'}},
                  'id': 'C1233800302-EEDTEST/V1233801695-EEDTEST',
                  'itemType': 'Variable',
                  'links': [{'href': 'https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections/red_var/coverage/rangeset',
                             'title': 'Perform rangeset request for red_var'}],
                  'title': 'red_var harmony_example v1'}],
 'links': [{'href': 'https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0',
            'rel': 'root',
            'title': 'OGC coverages API root for harmony_example v1',
            'type': 'application/json'},
           {'href': 'https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections',
            'rel': 'self',
            'title': 'Collections listing for harmony_example v1',
            'type': 'application/json'}]}

Access native data without transformation services

For EOSDIS collections without associated Harmony transformation services, the Harmony API can still be utilized to access data through the provided data access links. Before we request services for harmony_example, We will use ATL08, or the "ATLAS/ICESat-2 L3A Land and Vegetation Height" data product, as an example of this "no processing" request. Note that this collection has restricted access and therefore cannot be queried for collection ID like above without passing Earthdata Login credentials. For convenience the collection ID was predetermined for this example: C1229246405-NSIDC_TS1.

The URL for requesting ATLO8 is printed below. In this simple case, the entire data product is requested. The request response is also printed below, which includes information such as JobID, data access links, associated granule IDs, request messages, and status:

In [14]:
noProcConfig = {
    'is2collection_id': 'C1229246405-NSIDC_TS1',
    'ogc-api-coverages_version': '1.0.0'
}

no_proc_url = harmony_root+'/{is2collection_id}/ogc-api-coverages/{ogc-api-coverages_version}/collections/all/coverage/rangeset'.format(**noProcConfig)
print('Request URL', no_proc_url)

no_proc_response = request.urlopen(no_proc_url)
no_proc_results = no_proc_response.read()
no_proc_json = json.loads(no_proc_results)
pprint.pprint(no_proc_json)
TLAS/ATL08.002/2018.10.16/ATL08_20181016101230_02720101_002_01.h5',
            'rel': 'data',
            'title': 'G1229652697-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016114648_02730101_002_01.h5',
            'rel': 'data',
            'title': 'G1229652694-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016115350_02730102_002_01.h5',
            'rel': 'data',
            'title': 'G1229481161-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016120220_02730103_002_01.h5',
            'rel': 'data',
            'title': 'G1229481176-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016121254_02730105_002_01.h5',
            'rel': 'data',
            'title': 'G1229481199-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016121819_02730106_002_01.h5',
            'rel': 'data',
            'title': 'G1229481170-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016124656_02730110_002_01.h5',
            'rel': 'data',
            'title': 'G1229481189-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016125437_02730111_002_01.h5',
            'rel': 'data',
            'title': 'G1229481202-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016130020_02730112_002_01.h5',
            'rel': 'data',
            'title': 'G1229481162-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016131403_02730114_002_01.h5',
            'rel': 'data',
            'title': 'G1229481185-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016132105_02740101_002_01.h5',
            'rel': 'data',
            'title': 'G1229652686-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016132807_02740102_002_01.h5',
            'rel': 'data',
            'title': 'G1229485291-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016133637_02740103_002_01.h5',
            'rel': 'data',
            'title': 'G1229485289-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016134712_02740105_002_01.h5',
            'rel': 'data',
            'title': 'G1229485293-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016135237_02740106_002_01.h5',
            'rel': 'data',
            'title': 'G1229485294-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016140107_02740107_002_01.h5',
            'rel': 'data',
            'title': 'G1229485290-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016140809_02740108_002_01.h5',
            'rel': 'data',
            'title': 'G1229485292-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016142113_02740110_002_01.h5',
            'rel': 'data',
            'title': 'G1229485288-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016142854_02740111_002_01.h5',
            'rel': 'data',
            'title': 'G1229485296-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016143437_02740112_002_01.h5',
            'rel': 'data',
            'title': 'G1229485287-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016145523_02750101_002_01.h5',
            'rel': 'data',
            'title': 'G1229653555-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016162940_02760101_002_01.h5',
            'rel': 'data',
            'title': 'G1229652688-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016193814_02780101_002_01.h5',
            'rel': 'data',
            'title': 'G1229652707-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016211232_02790101_002_01.h5',
            'rel': 'data',
            'title': 'G1229652693-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016224649_02800101_002_01.h5',
            'rel': 'data',
            'title': 'G1229653712-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.17/ATL08_20181017015524_02820101_002_01.h5',
            'rel': 'data',
            'title': 'G1229653722-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.17/ATL08_20181017050359_02840101_002_01.h5',
            'rel': 'data',
            'title': 'G1229653719-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.17/ATL08_20181017063816_02850101_002_01.h5',
            'rel': 'data',
            'title': 'G1229653704-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.17/ATL08_20181017081233_02860101_002_01.h5',
            'rel': 'data',
            'title': 'G1229653693-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.17/ATL08_20181017094651_02870101_002_01.h5',
            'rel': 'data',
            'title': 'G1229653694-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.17/ATL08_20181017112108_02880101_002_01.h5',
            'rel': 'data',
            'title': 'G1229653679-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.17/ATL08_20181017125526_02890101_002_01.h5',
            'rel': 'data',
            'title': 'G1229653710-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.23/ATL08_20181023212834_03860102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652423-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.23/ATL08_20181023230252_03870102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652591-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024034544_03900102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652416-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024052002_03910102_002_01.h5',
            'rel': 'data',
            'title': 'G1229653691-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024065419_03920102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652425-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024082837_03930102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652426-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024100254_03940102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652420-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024113711_03950102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652427-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024131129_03960102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652497-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024192838_04000102_002_01.h5',
            'rel': 'data',
            'title': 'G1229653695-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024210256_04010102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652594-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024223713_04020102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652418-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.25/ATL08_20181025062840_04070102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652414-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.25/ATL08_20181025080258_04080102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652417-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.25/ATL08_20181025093715_04090102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652498-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.25/ATL08_20181025111133_04100102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652422-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.25/ATL08_20181025124550_04110102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652419-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.25/ATL08_20181025142007_04120102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652504-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.06/ATL08_20181106152938_05960102_002_01.h5',
            'rel': 'data',
            'title': 'G1229653728-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.08/ATL08_20181108051237_06200102_002_01.h5',
            'rel': 'data',
            'title': 'G1229653725-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.08/ATL08_20181108064654_06210102_002_01.h5',
            'rel': 'data',
            'title': 'G1229653726-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.08/ATL08_20181108082111_06220102_002_01.h5',
            'rel': 'data',
            'title': 'G1229653729-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.08/ATL08_20181108095529_06230102_002_01.h5',
            'rel': 'data',
            'title': 'G1229653730-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.08/ATL08_20181108112946_06240102_002_01.h5',
            'rel': 'data',
            'title': 'G1229653727-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.08/ATL08_20181108130404_06250102_002_01.h5',
            'rel': 'data',
            'title': 'G1229653732-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.16/ATL08_20181116190430_07510102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652411-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.16/ATL08_20181116203848_07520102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652421-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.16/ATL08_20181116221305_07530102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652691-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117012139_07550102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652714-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117025557_07560102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652709-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117043014_07570102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652708-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117060431_07580102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652699-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117073848_07590102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652695-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117091306_07600102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652685-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117104723_07610102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652692-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117122141_07620102_002_01.h5',
            'rel': 'data',
            'title': 'G1229653028-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117135558_07630102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652698-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117153015_07640102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652595-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117183850_07660102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652700-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117201307_07670102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652684-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117214724_07680102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652592-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.18/ATL08_20181118005557_07700102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652711-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.18/ATL08_20181118023014_07710102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652501-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.18/ATL08_20181118040431_07720102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652503-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.18/ATL08_20181118053849_07730102_002_01.h5',
            'rel': 'data',
            'title': 'G1229652499-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125073026_08810103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653030-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125090444_08820103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653734-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125103901_08830103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653721-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125121318_08840103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653717-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125134735_08850103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653720-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125152152_08860103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653735-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125200445_08890103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653701-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125213902_08900103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653703-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125231320_08910103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653706-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126004737_08920103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653702-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126035611_08940103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653709-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126053029_08950103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653708-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126070446_08960103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653707-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126083904_08970103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653711-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126101321_08980103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653705-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126114738_08990103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653718-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126132156_09000103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653696-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126145613_09010103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653697-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126163030_09020103_002_01.h5',
            'rel': 'data',
            'title': 'G1229653698-NSIDC_TS1'},
           {'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2019.01.14/ATL08_20190114204204_02660203_002_01.h5',
            'rel': 'data',
            'title': 'G1233305183-NSIDC_TS1'}],
 'message': 'Returning direct download links because no operations can be '
            'performed on C1229246405-NSIDC_TS1.',
 'progress': 100,
 'request': 'https://harmony.uat.earthdata.nasa.gov/C1229246405-NSIDC_TS1/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset',
 'status': 'successful',
 'updatedAt': '2020-11-18T15:47:07.387Z',
 'username': 'somebody'}

Note that the request located all granules available in that collection. We can pull those data access links from the request response:

In [ ]:

In [15]:
links = no_proc_json['links'] #list of links from response

for i in range(len(links)):
    link_dict = links[i]
    print(link_dict['href'])
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.14/ATL08_20181014044639_02380101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.14/ATL08_20181014062057_02390101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.14/ATL08_20181014075514_02400101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.14/ATL08_20181014092931_02410101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.14/ATL08_20181014110349_02420101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.14/ATL08_20181014123806_02430101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.14/ATL08_20181014141223_02440101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.14/ATL08_20181014154641_02450101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.14/ATL08_20181014185515_02470101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.14/ATL08_20181014202933_02480101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.14/ATL08_20181014220350_02490101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.15/ATL08_20181015042100_02530101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.15/ATL08_20181015055518_02540101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.15/ATL08_20181015072935_02550101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.15/ATL08_20181015103810_02570101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.15/ATL08_20181015121227_02580101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.15/ATL08_20181015134645_02590101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.15/ATL08_20181015152102_02600101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.15/ATL08_20181015200354_02630101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.15/ATL08_20181015213811_02640101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016052938_02690101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016083813_02710101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016101230_02720101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016114648_02730101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016115350_02730102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016120220_02730103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016121254_02730105_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016121819_02730106_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016124656_02730110_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016125437_02730111_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016130020_02730112_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016131403_02730114_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016132105_02740101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016132807_02740102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016133637_02740103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016134712_02740105_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016135237_02740106_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016140107_02740107_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016140809_02740108_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016142113_02740110_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016142854_02740111_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016143437_02740112_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016145523_02750101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016162940_02760101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016193814_02780101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016211232_02790101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.16/ATL08_20181016224649_02800101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.17/ATL08_20181017015524_02820101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.17/ATL08_20181017050359_02840101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.17/ATL08_20181017063816_02850101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.17/ATL08_20181017081233_02860101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.17/ATL08_20181017094651_02870101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.17/ATL08_20181017112108_02880101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.17/ATL08_20181017125526_02890101_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.23/ATL08_20181023212834_03860102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.23/ATL08_20181023230252_03870102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024034544_03900102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024052002_03910102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024065419_03920102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024082837_03930102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024100254_03940102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024113711_03950102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024131129_03960102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024192838_04000102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024210256_04010102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.24/ATL08_20181024223713_04020102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.25/ATL08_20181025062840_04070102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.25/ATL08_20181025080258_04080102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.25/ATL08_20181025093715_04090102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.25/ATL08_20181025111133_04100102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.25/ATL08_20181025124550_04110102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.25/ATL08_20181025142007_04120102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.06/ATL08_20181106152938_05960102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.08/ATL08_20181108051237_06200102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.08/ATL08_20181108064654_06210102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.08/ATL08_20181108082111_06220102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.08/ATL08_20181108095529_06230102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.08/ATL08_20181108112946_06240102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.08/ATL08_20181108130404_06250102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.16/ATL08_20181116190430_07510102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.16/ATL08_20181116203848_07520102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.16/ATL08_20181116221305_07530102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117012139_07550102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117025557_07560102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117043014_07570102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117060431_07580102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117073848_07590102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117091306_07600102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117104723_07610102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117122141_07620102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117135558_07630102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117153015_07640102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117183850_07660102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117201307_07670102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.17/ATL08_20181117214724_07680102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.18/ATL08_20181118005557_07700102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.18/ATL08_20181118023014_07710102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.18/ATL08_20181118040431_07720102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.18/ATL08_20181118053849_07730102_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125073026_08810103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125090444_08820103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125103901_08830103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125121318_08840103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125134735_08850103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125152152_08860103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125200445_08890103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125213902_08900103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.25/ATL08_20181125231320_08910103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126004737_08920103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126035611_08940103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126053029_08950103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126070446_08960103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126083904_08970103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126101321_08980103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126114738_08990103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126132156_09000103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126145613_09010103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.11.26/ATL08_20181126163030_09020103_002_01.h5
https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2019.01.14/ATL08_20190114204204_02660203_002_01.h5

Instead of requesting the entire ATL08 collection, we can also specify a single granule ID to download. For convenience, the first granule returned in the request above is queried separately to demonstrate this single granule request:

In [16]:
# Determine first granule ID in list
first_link_dict = links[0]
granuleID = first_link_dict['title']
print(granuleID)

# Update noProcConfig
noProcConfig = {
    'is2collection_id': 'C1229246405-NSIDC_TS1',
    'ogc-api-coverages_version': '1.0.0',
    'variable': 'all',
    'granuleID': granuleID
}

no_proc_single_url = harmony_root+'/{is2collection_id}/ogc-api-coverages/{ogc-api-coverages_version}/collections/{variable}/coverage/rangeset?granuleID={granuleID}'.format(**noProcConfig)
print(no_proc_single_url)
no_proc_single_response = request.urlopen(no_proc_single_url)
no_proc_single_results = no_proc_single_response.read()
no_proc_single_json = json.loads(no_proc_single_results)
pprint.pprint(no_proc_single_json)
G1229652687-NSIDC_TS1
https://harmony.uat.earthdata.nasa.gov/C1229246405-NSIDC_TS1/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?granuleID=G1229652687-NSIDC_TS1
{'createdAt': '2020-11-18T15:47:08.114Z',
 'links': [{'href': 'https://n5eil11u.ecs.nsidc.org/TS1/DP2/ATLAS/ATL08.002/2018.10.14/ATL08_20181014044639_02380101_002_01.h5',
            'rel': 'data',
            'title': 'G1229652687-NSIDC_TS1'}],
 'message': 'Returning direct download links because no operations can be '
            'performed on C1229246405-NSIDC_TS1.',
 'progress': 100,
 'request': 'https://harmony.uat.earthdata.nasa.gov/C1229246405-NSIDC_TS1/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?granuleID=G1229652687-NSIDC_TS1',
 'status': 'successful',
 'updatedAt': '2020-11-18T15:47:08.114Z',
 'username': 'somebody'}

The single file output is downloaded to a directory with write permissions:

In [17]:
single_link = no_proc_single_json['links']
single_dict = single_link[0]
file_url = single_dict['href']

file_response = request.urlopen(file_url)
file_results = file_response.read()

# Write data to file 
file_name = 'harmonyNoProc.h5'
filepath = str(local_dir+file_name)
file_ = open(filepath, 'wb')
file_.write(file_results)
file_.close()

Access data subsetted by variable

Now we'll move into some subsetting examples with the harmony_example collection, beginning with a basic variable subset of a single pre-determined granule with global coverage. The variable request is included in the URL below as a /collections path. As stated in the API documentation, "This API interprets OGC 'collections' to be equivalent to CMR 'variables'". Unlike the no processing requests above, this result will be returned synchronously to us. By default, any single granule request that has associated Harmony services will be returned synchronously.

In [18]:
varSubsetConfig = {
    'collection_id': harmony_collection_id,
    'ogc-api-coverages_version': '1.0.0',
    'variable': 'blue_var',
    'granuleid': 'G1233800343-EEDTEST'
}
var_url = harmony_root+'/{collection_id}/ogc-api-coverages/{ogc-api-coverages_version}/collections/{variable}/coverage/rangeset?granuleid={granuleid}'.format(**varSubsetConfig)
print('Request URL', var_url)
var_response = request.urlopen(var_url)
var_results = var_response.read()
Request URL https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections/blue_var/coverage/rangeset?granuleid=G1233800343-EEDTEST

This single subsetted file output is downloaded to the Harmony outputs directory:

In [19]:
file_name = 'harmonyvarsubset.tif'
var_filepath = str(local_dir+file_name)
file_ = open(var_filepath, 'wb')
file_.write(var_results)
file_.close()

We can plot the TIF output of the single blue_var band to verify our output:

In [20]:
var_raster = rasterio.open(var_filepath)
blue = var_raster.read(1) # read first band, in this case blue_var
plt.imshow(blue, cmap='Blues');
In [21]:
bboxSubsetConfig = {
    'collection_id': harmony_collection_id,
    'ogc-api-coverages_version': '1.0.0',
    'variable': 'all',
    'granuleid': 'G1233800343-EEDTEST',
    'lat': '(-45.75:-9)',
    'lon': '(110:156)'
}
bbox_url = harmony_root+'/{collection_id}/ogc-api-coverages/{ogc-api-coverages_version}/collections/{variable}/coverage/rangeset?granuleid={granuleid}&subset=lat{lat}&subset=lon{lon}'.format(**bboxSubsetConfig)
print('Request URL', bbox_url)
bbox_response = request.urlopen(bbox_url)
bbox_results = bbox_response.read()
Request URL https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?granuleid=G1233800343-EEDTEST&subset=lat(-45.75:-9)&subset=lon(110:156)

This spatially subsetted file output is downloaded to the Harmony outputs directory:

In [22]:
bbox_file_name = 'harmonybboxsubset.tif'
bbox_filepath = str(local_dir+bbox_file_name)
file_ = open(bbox_filepath, 'wb')
file_.write(bbox_results)
file_.close()

We can plot the TIF output of the subsetted file to verify our output. All bands are overlaid to plot the color composite, with this code example modified from the following source:

https://automating-gis-processes.github.io/CSC/notebooks/L5/plotting-raster.html \ © Copyright 2018, Henrikki Tenkanen \ License

In [23]:
# Open the file:
bbox_raster = rasterio.open(bbox_filepath)

# Read the grid values into numpy arrays
red = bbox_raster.read(3)
green = bbox_raster.read(2)
blue = bbox_raster.read(1)

# Function to normalize the grid values
def normalize(array):
    """Normalizes numpy arrays into scale 0.0 - 1.0"""
    import numpy as np
    np.seterr(divide='ignore', invalid='ignore') #ignore divide by 0 error
    array_min, array_max = array.min(), array.max()
    return ((array - array_min)/(array_max - array_min))

# Normalize the bands
redn = normalize(red)
greenn = normalize(green)
bluen = normalize(blue)

# Create RGB natural color composite
rgb = np.dstack((redn, greenn, bluen))

# Let's see how our color composite looks like
plt.imshow(rgb);

Access data filtered by temporal range

Filering data results by temporal range is also available on this test collection. According to the Harmony API documentation, the time keyword within the rangeset query supports the following:

Either a date-time or a period string that adheres to RFC 3339. Examples:

    * A date-time: "2018-02-12T23:20:50Z" * A period: "2018-02-12T00:00:00Z/2018-03-18T12:31:12Z" or "2018-02-12T00:00:00Z/P1M6DT12H31M12S"

Only collections that have a temporal property that intersects the value of time are selected. If a collection has multiple temporal properties, it is the decision of the server whether only a single temporal property is used to determine the extent or all relevant temporal properties.

We will search for the following time range:

Start time: 2020-01-16 02:00:00 \ End time: 2020-01-16 03:00:00

According to Earthdata Search, a single granule 016_01_ff0000_africa is returned over this time.

In [24]:
timeSubsetConfig = {
    'collection_id': harmony_collection_id,
    'ogc-api-coverages_version': '1.0.0',
    'variable': 'all',
    'time': '("2020-01-16T02:00:00.000Z":"2020-01-16T03:00:00.000Z")'
}

time_url = harmony_root+'/{collection_id}/ogc-api-coverages/{ogc-api-coverages_version}/collections/{variable}/coverage/rangeset?&subset=time{time}'.format(**timeSubsetConfig)
print('Request URL', time_url)
time_response = request.urlopen(time_url)
time_results = time_response.read()
Request URL https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?&subset=time("2020-01-16T02:00:00.000Z":"2020-01-16T03:00:00.000Z")

This file returned over the time range of interest is downloaded to the Harmony outputs directory:

In [25]:
time_file_name = 'harmonytimesubset.tif'
time_filepath = str(local_dir+time_file_name)
file_ = open(time_filepath, 'wb')
file_.write(time_results)
file_.close()

We can plot the TIF output of this file to verify the coverage over Africa (for simplicity, plotting the first band):

In [26]:
time_raster = rasterio.open(time_filepath)
time_band = time_raster.read(1)
plt.imshow(time_band, cmap='Blues');

Access reprojected data

The Harmony API accepts reprojection requests with a given coordinate reference system using the outputCrs keyword. According to the Harmony API documentation, this keyword "recognizes CRS types that can be inferred by gdal, including EPSG codes, Proj4 strings, and OGC URLs (http://www.opengis.net/def/crs/...) ". Two examples below demonstrate inputting an EPSG code and Proj4 string using the global test granule from previous examples. First, let's view the projection information of the granule in the native projection, using the variable subset example:

In [27]:
native_proj = gdal.Open(var_filepath, gdal.GA_ReadOnly)
native_proj.GetProjection()
Out[27]:
'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433],AUTHORITY["EPSG","4326"]]'

Request reprojection to EPSG 6933 ("WGS 84 / NSIDC EASE-Grid 2.0 Global"):

In [28]:
epsgConfig = {
    'collection_id': harmony_collection_id,
    'ogc-api-coverages_version': '1.0.0',
    'variable': 'all',
    'granuleid': 'G1233800343-EEDTEST',
    'outputCrs': 'EPSG:6933',
}

epsg_url = harmony_root+'/{collection_id}/ogc-api-coverages/{ogc-api-coverages_version}/collections/{variable}/coverage/rangeset?&granuleid={granuleid}&outputCrs={outputCrs}'.format(**epsgConfig)
print('Request URL', epsg_url)
epsg_response = request.urlopen(epsg_url)
epsg_results = epsg_response.read()
Request URL https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?&granuleid=G1233800343-EEDTEST&outputCrs=EPSG:6933

This reprojected output is downloaded to the Harmony outputs directory and the projection information can be viewed using GDAL:

In [29]:
epsg_file_name = 'harmonyepsg.tif'
epsg_filepath = str(local_dir+epsg_file_name)
file_ = open(epsg_filepath, 'wb')
file_.write(epsg_results)
file_.close()

# get projection information
epsg = gdal.Open(epsg_filepath, gdal.GA_ReadOnly)
epsg.GetProjection()
Out[29]:
'PROJCS["unknown",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433],AUTHORITY["EPSG","4326"]],PROJECTION["Cylindrical_Equal_Area"],PARAMETER["standard_parallel_1",30],PARAMETER["central_meridian",0],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]'

We can see that the output was reprojected to Cylindrical Equal Area as expected. We can do a visual check of this as well:

In [30]:
epsg_raster = rasterio.open(epsg_filepath)
epsg_band = epsg_raster.read(1)
plt.imshow(epsg_band, cmap='Blues');

Reprojection can also be requested using a proj4 string. You must ensure that the proper URL encoding is included in the request so that proj4 string spaces and special characters are handled without error:

In [31]:
# URL encode string using urllib parse package
proj_string = '+proj=cea +lon_0=0 +lat_ts=30 +x_0=0 +y_0=0 +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs' # proj4 of WGS 84 / NSIDC EASE-Grid 2.0 Global projection
proj_encode = parse.quote(proj_string)

projConfig = {
    'collection_id': harmony_collection_id,
    'ogc-api-coverages_version': '1.0.0',
    'variable': 'all',
    'granuleid': 'G1233800343-EEDTEST',
    'outputCrs': proj_encode
}

proj_url = harmony_root+'/{collection_id}/ogc-api-coverages/{ogc-api-coverages_version}/collections/{variable}/coverage/rangeset?&granuleid={granuleid}&outputCrs={outputCrs}'.format(**projConfig)
print('Request URL', proj_url)
proj_response = request.urlopen(proj_url)
proj_results = proj_response.read()
Request URL https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?&granuleid=G1233800343-EEDTEST&outputCrs=%2Bproj%3Dcea%20%2Blon_0%3D0%20%2Blat_ts%3D30%20%2Bx_0%3D0%20%2By_0%3D0%20%2Bellps%3DWGS84%20%2Btowgs84%3D0%2C0%2C0%2C0%2C0%2C0%2C0%20%2Bunits%3Dm%20%2Bno_defs

This reprojected output is downloaded to a directory with write permissions and the projection information can be viewed using GDAL. The projection is equivalent to the specified EPSG request above as expected:

In [32]:
proj_file_name = 'harmonyproj4.tif'
proj_filepath = str(local_dir+proj_file_name)
file_ = open(proj_filepath, 'wb')
file_.write(proj_results)
file_.close()

# get projection information
proj = gdal.Open(proj_filepath, gdal.GA_ReadOnly)
proj.GetProjection()
Out[32]:
'PROJCS["unknown",GEOGCS["unknown",DATUM["Unknown_based_on_WGS84_ellipsoid",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],PROJECTION["Cylindrical_Equal_Area"],PARAMETER["standard_parallel_1",30],PARAMETER["central_meridian",0],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]]]'

Access Level 2 swath regridded data

Moving outside of the harmony/gdal service, we will now request regridding from the sds/swath-projector service using the C1233860183-EEDTEST, or Harmony L2 swath example, collection provided in NetCDF format.

The Harmony API accepts several query parameters related to regridding and interpolation in addition to the reprojection parameters above:

interpolation=<String> - Both near and bilinear are valid options

scaleSize=x,y - 2 comma separated numbers as floats

scaleExtent=xmin,ymin,xmax,ymax - 4 comma separated numbers as floats

width=<Float>

height=<Float>

An error is returned if both scaleSize and width/height parameters are both provided (only one or the other can be used).

Request reprojection to Europe Lambert Conformal Conic with a new scale extent and nearest neighbor interpolation:

In [33]:
# URL encode string using urllib parse package
l2proj_string = '+proj=lcc +lat_1=43 +lat_2=62 +lat_0=30 +lon_0=10 +x_0=0 +y_0=0 +ellps=intl +units=m +no_defs'
l2proj_encode = parse.quote(proj_string)


regridConfig = {
    'l2collection_id': 'C1233860183-EEDTEST',
    'ogc-api-coverages_version': '1.0.0',
    'variable': 'all',
    'granuleid': 'G1233860486-EEDTEST',
    'outputCrs': l2proj_encode,
    'interpolation': 'near',
    'scaleExtent': '-7000000,1000000,8000000,8000000'
}

regrid_url = harmony_root+'/{l2collection_id}/ogc-api-coverages/{ogc-api-coverages_version}/collections/{variable}/coverage/rangeset?&granuleid={granuleid}&outputCrs={outputCrs}&interpolation={interpolation}&scaleExtent={scaleExtent}'.format(**regridConfig)
print('Request URL', regrid_url)
regrid_response = request.urlopen(regrid_url)
regrid_results = regrid_response.read()
Request URL https://harmony.uat.earthdata.nasa.gov/C1233860183-EEDTEST/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?&granuleid=G1233860486-EEDTEST&outputCrs=%2Bproj%3Dcea%20%2Blon_0%3D0%20%2Blat_ts%3D30%20%2Bx_0%3D0%20%2By_0%3D0%20%2Bellps%3DWGS84%20%2Btowgs84%3D0%2C0%2C0%2C0%2C0%2C0%2C0%20%2Bunits%3Dm%20%2Bno_defs&interpolation=near&scaleExtent=-7000000,1000000,8000000,8000000

This reprojected and regridded output is downloaded to the Harmony outputs directory and we can inspect a variable to check for projection and grid dimension:

In [34]:
regrid_file_name = 'regrid.nc'
regrid_filepath = str(local_dir+regrid_file_name)
file_ = open(regrid_filepath, 'wb')
file_.write(regrid_results)
file_.close()

# Inspect dimensions of the blue_var:
regrid_nc = Dataset(regrid_filepath)
print(regrid_nc.variables.keys())
blue_var = regrid_nc.variables['blue_var']
print(blue_var)
dict_keys(['time', 'blue_var', 'lambert_cylindrical_equal_area', 'x', 'y', 'alpha_var', 'green_var', 'red_var'])
<class 'netCDF4._netCDF4.Variable'>
uint8 blue_var(time, y, x)
    _FillValue: 0
    add_offset: 28
    scale_factor: 2
    grid_mapping: lambert_cylindrical_equal_area
unlimited dimensions:
current shape = (1, 635, 1360)
filling on

Print the x and y dimensions to confirm that the output matches the requested scale extent in meters:

In [35]:
x = regrid_nc.variables['x']
y = regrid_nc.variables['y']
print('min x', min(x), 'max x', max(x))
print('min y', min(y), 'max y', max(y))
min x -6994485.60355348 max x 7993643.938090177
min y 1002230.909365048 max y 7994485.603553479

Access multiple files from an asynchronous request

By default, a request resulting in more than one file will be returned asynchronously via a Job URL. The initial request submission is automatically redirected to this URL, and output links are appended to the response as they complete. The following query should return three granules based on the following temporal range:

In [36]:
asyncConfig = {
    'collection_id': harmony_collection_id,
    'ogc-api-coverages_version': '1.0.0',
    'variable': 'all',
    'time': '("2020-01-16T02:00:00.000Z":"2020-01-16T07:00:00.000Z")'
}

async_url = harmony_root+'/{collection_id}/ogc-api-coverages/{ogc-api-coverages_version}/collections/{variable}/coverage/rangeset?&subset=time{time}'.format(**asyncConfig)
print('Request URL', async_url)
async_response = request.urlopen(async_url)
async_results = async_response.read()
async_json = json.loads(async_results)
pprint.pprint(async_json)
Request URL https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?&subset=time("2020-01-16T02:00:00.000Z":"2020-01-16T07:00:00.000Z")
{'createdAt': '2020-11-18T15:48:19.761Z',
 'jobID': '2bd7d3a3-971d-4edf-ada7-7a258d3f3f9b',
 'links': [{'href': 'https://harmony.uat.earthdata.nasa.gov/jobs/2bd7d3a3-971d-4edf-ada7-7a258d3f3f9b',
            'rel': 'self',
            'title': 'Job Status',
            'type': 'application/json'}],
 'message': 'The job is being processed',
 'progress': 0,
 'request': 'https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?subset=time(%222020-01-16T02%3A00%3A00.000Z%22%3A%222020-01-16T07%3A00%3A00.000Z%22)',
 'status': 'running',
 'updatedAt': '2020-11-18T15:48:19.761Z',
 'username': 'somebody'}

The async response initially shows 0% progress. The initial request URL will automatically redirect to a job URL, which we can manually determine using the jobID:

In [37]:
jobConfig = {
    'jobID': async_json['jobID']
}

job_url = harmony_root+'/jobs/{jobID}'.format(**jobConfig)
print('Job URL', job_url)
Job URL https://harmony.uat.earthdata.nasa.gov/jobs/2bd7d3a3-971d-4edf-ada7-7a258d3f3f9b

The links list in the job response will continue to be updated as outputs are produced:

In [38]:
job_response = request.urlopen(job_url)
job_results = job_response.read()
job_json = json.loads(job_results)

print('Job response:')
print()
pprint.pprint(job_json)
Job response:

{'createdAt': '2020-11-18T15:48:19.761Z',
 'jobID': '2bd7d3a3-971d-4edf-ada7-7a258d3f3f9b',
 'links': [{'href': 'https://harmony.uat.earthdata.nasa.gov/jobs/2bd7d3a3-971d-4edf-ada7-7a258d3f3f9b',
            'rel': 'self',
            'title': 'Job Status',
            'type': 'application/json'}],
 'message': 'The job is being processed',
 'progress': 0,
 'request': 'https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?subset=time(%222020-01-16T02%3A00%3A00.000Z%22%3A%222020-01-16T07%3A00%3A00.000Z%22)',
 'status': 'running',
 'updatedAt': '2020-11-18T15:48:19.761Z',
 'username': 'somebody'}

A loop can be set up to query the job status and download outputs once the job is complete:

In [39]:
#Continue loop while request is still processing
while job_json['status'] == 'running' and job_json['progress'] < 100:
    print('Job status is running. Progress is ', job_json['progress'], '%. Trying again.')
    time.sleep(10)
    loop_response = request.urlopen(job_url)
    loop_results = loop_response.read()
    job_json = json.loads(loop_results)
    if job_json['status'] == 'running':
        continue

if job_json['status'] == 'successful' and job_json['progress'] == 100:
    print('Job progress is 100%. Output links printed below:')
    links = [link for link in job_json['links'] if link.get('rel', 'data') == 'data'] #list of data links from response
    for i in range(len(links)):
        link_dict = links[i]
        print(link_dict['href'])
        output_file_name = str(link_dict['title']+'.tif')
        proj_filepath = str(local_dir+output_file_name)
        file_ = open(proj_filepath, 'wb')
        file_.write(proj_results)
        file_.close()
Job status is running. Progress is  0 %. Trying again.

Previewing a small number of results

By default, a request will return as many results as match the spatial and temporal query parameters, although this is subject to system limitations to prevent users from inadvertently overwhelming the system. If a user wishes to further limit the number of results returned in order to preview a small number of results before requesting a larger transformation, they can simply supply a parameter called 'maxResults'.

In [40]:
asyncConfig = {
    'collection_id': harmony_collection_id,
    'ogc-api-coverages_version': '1.0.0',
    'variable': 'all',
    'maxResults': '2'
}

async_url = harmony_root+'/{collection_id}/ogc-api-coverages/{ogc-api-coverages_version}/collections/{variable}/coverage/rangeset?&maxResults={maxResults}'.format(**asyncConfig)
print('Request URL', async_url)
async_response = request.urlopen(async_url)
async_results = async_response.read()
async_json = json.loads(async_results)
pprint.pprint(async_json)
Request URL https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?&maxResults=2
{'createdAt': '2020-11-18T15:48:33.798Z',
 'jobID': 'd8e2ad8a-85af-4072-bc62-13f41dcb3633',
 'links': [{'href': 'https://harmony.uat.earthdata.nasa.gov/jobs/d8e2ad8a-85af-4072-bc62-13f41dcb3633',
            'rel': 'self',
            'title': 'Job Status',
            'type': 'application/json'}],
 'message': 'CMR query identified 177 granules, but the request has been '
            'limited to process only the first 2 granules because you '
            'requested 2 maxResults.',
 'progress': 0,
 'request': 'https://harmony.uat.earthdata.nasa.gov/C1233800302-EEDTEST/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?maxResults=2',
 'status': 'running',
 'updatedAt': '2020-11-18T15:48:33.798Z',
 'username': 'somebody'}