Use Traveler APIs to search for scenes and download satellite data (Part 1)

Introduction

This article is divided into two parts: Part 1 and Part 2.
Using Tellus Satellite Data Traveler APIs through JupyterLab, the article guides you to how to download satellite data. In Part 1, you can search for scenes and get scene information. In Part 2, you can get file information registered to the scene and generate download URLs. This section is Part 1.

Please click here for more details about the APIs

As for JupyterLab, you need to set it up in advance.

Issue an API token

To use the Tellus Satellite Data Traveler APIs, you need an API token.

See “How to Issue an API Token” to generate one.

When you copy and paste the sample code provided in this article, replace the value of TOKEN (displayed as "TOKENXXXXXXXXXXXXXXXXXX") with your own API token.

Install the “Requests” module

To use the “Requests” module for API calls, change your JupyterLab's Python version to Python 3.7 or a later version. If the “Requests” module is not yet installed, run the following command to install it using Terminal on Mac or Command Prompt on Windows. You can run the command using JupyterLab as well prefixing it with “!”.

If you are using Anaconda, the “Requests” module is installed by default in most of its versions.

First, make sure you already have pip installed.

- Run this command using Terminal or Command Prompt.

pip -V



- In JupyterLab, run this command instead.

!pip –V


traveler_api_p1-02.PNG

After ensuring that pip has been installed, please install the “Requests” module in the environment using the following command.

pip install requests


Confirm that the “Requests” module has been installed with the following command.

pip list


Using Anaconda, you can also install the “Requests” module with the command “conda.”

conda install requests


Python 3.4 and later versions include pip by default; if you don't find pip, install it as needed.

python get-pip.py


Now that you’re ready, let's move on to how to use the APIs.

Search for scenes by specifying search criteria

Filter by catalog elements

Launch JupyterLab and paste the following sample code into it.

You can search by entering search criteria as arguments when calling the function.

Here, two APIs are used: the API /data-search/ and the API /datasets/{dataset_id}/data-search/. The former allows searching for scenes across multiple datasets, while the latter allows searching for scenes by specifying one dataset.

import json
import requests
TOKEN = "TOKENXXXXXXXXXXXXXXXXXX"
# Common settings for API calls
BASE_URL = "https://www.tellusxdp.com/api/traveler/v1"
REQUESTS_HEADERS = {
    "Authorization": "Bearer " + TOKEN,
    "Content-Type": "application/json",
}
def search_scene(datasets=None, intersects=None, query={}, sortby=None, paginate=None):
    url = "{}/data-search/".format(BASE_URL)
    payloads = {}
    if isinstance(datasets, list):
        if len(datasets) == 1:
           url = "{}/datasets/{}/data-search/".format(BASE_URL, datasets[0])
        else:
            payloads["datasets"] = datasets
    elif isinstance(datasets, str):
        url = "{}/datasets/{}/data-search/".format(BASE_URL, datasets)
    if intersects is not None:
        payloads["intersects"] = intersects
    if query is not None:
        payloads["query"] = query
    if isinstance(sortby, list):
        payloads["sortby"] = sortby
    if paginate is not None:
        payloads["paginate"] = paginate
    res = requests.post(url, headers=REQUESTS_HEADERS, data=json.dumps(payloads))
    try:
        res.raise_for_status()
    except Exception as err:
        raise SystemError("Error:{}".format(err))
    return res.json()
print(search_scene(
    datasets=["1a41a4b1-4594-431f-95fb-82f9bdc35d6b", "b0e16dea-6544-4422-926f-ad3ec9a3fcbd"],
    query={
        "sar:observation_direction":{"eq":"left"},
        "sat:orbit_state":{"eq":"descending"},
        "view:off_nadir":{"gte":15,"lte":46.2},
        "start_datetime": {"gte": "2022-01-12T00:00:00Z"},
        "end_datetime": {"lte": "2022-01-20T23:59:59Z"}
    },
    sortby=[{"field": "properties.end_datetime", "direction": "desc"}],
    paginate={"size":10,"cursor":None}
))


The above code specifies the search criteria below, as well as the sort criteria and the maximum number of search results to be displayed per page.

Search criteria

Item Details
Dataset

Equal to one of the following.

[Tellus Official] PALSAR-2_L1.1
(ID: 1a41a4b1-4594-431f-95fb-82f9bdc35d6b)

[Tellus Official] PALSAR-2_L2.1
(ID: b0e16dea-6544-4422-926f-ad3ec9a3fcbd)

Observation direction(SAR) left
Orbit direction descending
Off-nadir angle 15 or more, 46.2 or less
Data aquisition date January 12, 2022 to January 20, 2022

The JupyterLab screen is shown below.

Change the codes marked in a rectangle to use your own API token and search criteria.。

230823-04.png

To learn more about search criteria, please refer to the parameters that can be specified as search criteria for scenes or the Schema information in the API document.

Filter by AOI

You can also try searching by specifying an AOI (Area of Interest).

It is also possible to specify an area when searching for scenes.

The image below is an example of searching with an AOI on the Tellus Traveler's website.

240221-04.png

Below is a code sample for the search API.

Specify coordinates for AOI in “coordinates” under “intersects.” The values must be specified counterclockwise. Make sure the first and last values are the same.

import json
import requests
TOKEN = "TOKENXXXXXXXXXXXXXXXXXX"
# Common settings for API calls
BASE_URL = "https://www.tellusxdp.com/api/traveler/v1"
REQUESTS_HEADERS = {
    "Authorization": "Bearer " + TOKEN,
    "Content-Type": "application/json",
}
def search_scene(datasets=None, intersects=None, query={}, sortby=None, paginate=None):
    url = "{}/data-search/".format(BASE_URL)
    payloads = {}
    if isinstance(datasets, list):
        if len(datasets) == 1:
           url = "{}/datasets/{}/data-search/".format(BASE_URL, datasets[0])
        else:
            payloads["datasets"] = datasets
    elif isinstance(datasets, str):
        url = "{}/datasets/{}/data-search/".format(BASE_URL, datasets)
    if intersects is not None:
        payloads["intersects"] = intersects
    if query is not None:
        payloads["query"] = query
    if isinstance(sortby, list):
        payloads["sortby"] = sortby
    if paginate is not None:
        payloads["paginate"] = paginate
    res = requests.post(url, headers=REQUESTS_HEADERS, data=json.dumps(payloads))
    try:
        res.raise_for_status()
    except Exception as err:
        raise SystemError("Error:{}".format(err))
    return res.json()
print(search_scene(
    intersects={
        "type":"Polygon","coordinates":[
            [
                [-162.33,11.55],
                [-149.32,11.55],
                [-149.32,24.07],
                [-162.33,24.07],
                [-162.33,11.55]
            ]
        ]
    },
    query={
        "start_datetime": {"gte": "2018-01-12T00:00:00Z"}
    },
    sortby=[
        {"field": "properties.end_datetime", "direction": "desc"}
    ],
    paginate={"size":10,"cursor":None}
))

The JupyterLab screen is shown below. Change the codes marked in a rectangle to use your own API token and scene information you want to search for.

230823-05.png

If you have difficulty entering search criteria manually, you can also reuse the search criteria saved on the Tellus Traveler's website.

First, search for scenes by specifying some search criteria on the Tellus Traveler’s website.

240221-03.png

Copy the “Condition details (JSON)” in the pop-up which shows up when you click the “Save this condition” button.

240221-06.png

Create a file named {any file name}.json, then paste the criteria into it and save.

The following content is saved as sample.json in the example.

{
  "query": {
    "start_datetime": { "gte": "2023-06-01T00:00:00Z" },
    "end_datetime": { "lte": "2023-06-15T23:59:59Z" },
    "eo:cloud_cover": { "gte": 0, "lte": 55 }
  },
  "intersects": {
    "type": "Polygon",
    "coordinates": [
      [
        [138.44970703125, 34.795474269863455],
        [141.78131103515625, 34.795474269863455],
        [141.78131103515625, 36.81285280928946],
        [138.44970703125, 36.81285280928946],
        [138.44970703125, 34.795474269863455]
      ]
    ]
  },
  "datasets": [
    "182d2ec2-e296-4e18-9c1a-5f769416f23d",
    "21d74302-bbc0-4f14-8192-3aad0986b197"
  ],
  "sortby": [{ "field": "properties.end_datetime", "direction": "desc" }]
}

Upload the json file created to JupyterLab.

In the image below, the file is uploaded to a folder named “demo.”

230823-09.png

Run the following search script in JupyterLab.

Before executing, save the json file with the search criteria in the same folder as the script file. Replace `%%JSON_FILE_NAME%%` with the json file name.

You can search for scenes using the search criteria set in json.

import json
import requests
TOKEN = "TOKENXXXXXXXXXXXXXXXXXX"
# Common settings for API calls
BASE_URL = "https://www.tellusxdp.com/api/traveler/v1"
REQUESTS_HEADERS = {
    "Authorization": "Bearer " + TOKEN,
    "Content-Type": "application/json",
}
def search_scene_by_json(filename):
    condition = json.load(open(filename))    
    url = "{}/data-search/".format(BASE_URL)
    res = requests.post(url, headers=REQUESTS_HEADERS, json=condition)
    try:
        res.raise_for_status()
    except Exception as err:
        raise SystemError("Error:{}".format(err))
    return res.json()["features"]
# print(scene_search_by_json("sample.json"))
print(search_scene_by_json("%%JSON_FILE_NAME%%"))

230823-16.png

The values marked in blue rectangles are the dataset_id and data_id. These will be used for the API in the next chapter.

Get scene information from search results

The API endpoint /datasets/{dataset_id}/data/{data_id}/ is used to get information on individual scenes.

Launch JupyterLab and paste the following sample code into it.

Use the values of “dataset_id” and “data_id” you got from the previous search as arguments to the function call in the sample code.

import requests
TOKEN = "TOKENXXXXXXXXXXXXXXXXXX"
# Common settings for API calls
BASE_URL = "https://www.tellusxdp.com/api/traveler/v1"
REQUESTS_HEADERS = {
    "Authorization": "Bearer " + TOKEN,
    "Content-Type": "application/json",
}
def get_scene_info(dataset_id , data_id):
    url = "{}/datasets/{}/data/{}/".format(BASE_URL, dataset_id, data_id)
    res = requests.get(url, headers=REQUESTS_HEADERS)
    try:
        res.raise_for_status()
    except Exception as err:
        raise SystemError("Error:{}".format(err))
    return res.json()
print(get_scene_info('ea71ef6e-9569-49fc-be16-ba98d876fb73','e432ad2b-d49c-4b50-892a-3487bebb0148'))

The JupyterLab screen is shown below.

Change the codes marked in a rectangle to use your own API token and scene information you want to search for.

230823-11.png

You can find the dataset_id (dataset's ID) on Tellus Traveler's Dataset Details page, as marked below.

240221-02.png

You can also find the data_id (scene's ID) on Tellus Traveler's Retrieved Scene Details page, as marked below.

240221-01.png

In Part 1, we have so far introduced how to issue an API token, install the “Requests” module, search for scenes using search criteria, and get scene information based on the search results.

In Part 2, we will introduce how to get a scene's file information and generate file download URLs.