Getting started with the Data API¶
Let's search & download some imagery of farmland near Stockton, CA. You can get the notebook here. Here are the steps we'll follow:
- Define an Area of Interest (AOI)
- Save our AOI's coordinates to GeoJSON format
- Create a few search filters
- Search for imagery using those filters
- Activate an image for downloading
- Download an image
Requirements¶
- Python 2.7 or 3+
- requests
- A Planet API Key
Define an Area of Interest¶
An Area of Interest (or AOI) is how we define the geographic "window" out of which we want to get data.
For the Data API, this could be a simple bounding box with four corners, or a more complex shape, as long as the definition is in GeoJSON format.
For this example, let's just use a simple box. To make it easy, I'll use geojson.io to quickly draw a shape & generate GeoJSON output for our box:
We only need the "geometry" object for our Data API request:
# Stockton, CA bounding box (created via geojson.io) geojson_geometry = { "type": "Polygon", "coordinates": [ [ [-121.59290313720705, 37.93444993515032], [-121.27017974853516, 37.93444993515032], [-121.27017974853516, 38.065932950547484], [-121.59290313720705, 38.065932950547484], [-121.59290313720705, 37.93444993515032] ] ] }
Create Filters¶
Now let's set up some filters to further constrain our Data API search:
# get images that overlap with our AOI geometry_filter = { "type": "GeometryFilter", "field_name": "geometry", "config": geojson_geometry } # get images acquired within a date range date_range_filter = { "type": "DateRangeFilter", "field_name": "acquired", "config": { "gte": "2016-08-31T00:00:00.000Z", "lte": "2016-09-01T00:00:00.000Z" } } # only get images which have <50% cloud coverage cloud_cover_filter = { "type": "RangeFilter", "field_name": "cloud_cover", "config": { "lte": 0.2 } } # combine our geo, date, cloud filters combined_filter = { "type": "AndFilter", "config": [geometry_filter, date_range_filter, cloud_cover_filter] }
Searching: Items and Assets¶
Planet's products are categorized as items and assets: an item is a single picture taken by a satellite at a certain time. Items have multiple asset types including the image in different formats, along with supporting metadata files.
For this demonstration, let's get a satellite image that is best suited for analytic applications; i.e., a 4-band image with spectral data for Red, Green, Blue and Near-infrared values. To get the image we want, we will specify an item type of PSScene4Band
, and asset type analytic
.
You can learn more about item & asset types in Planet's Data API here.
Now let's search for all the items that match our filters:
import os import json import requests from requests.auth import HTTPBasicAuth from planet.api.auth import find_api_key # API Key stored as an env variable PLANET_API_KEY = find_api_key() item_type = "PSScene4Band" # API request object search_request = { "interval": "day", "item_types": [item_type], "filter": combined_filter } # fire off the POST request search_result = \ requests.post( 'https://api.planet.com/data/v1/quick-search', auth=HTTPBasicAuth(PLANET_API_KEY, ''), json=search_request) print(json.dumps(search_result.json(), indent=1))
Our search returns metadata for all of the images within our AOI that match our date range and cloud coverage filters. It looks like there are multiple images here; let's extract a list of just those image IDs:
# extract image IDs only image_ids = [feature['id'] for feature in search_result.json()['features']] print(image_ids)
[u'20160831_143848_0c79', u'20160831_212703_0c43', u'20160831_212705_0c43', u'20160831_212706_0c43', u'20160831_212707_0c43', u'20160831_212704_0c43', u'20160831_212703_1_0c43', u'20160831_180302_0e26', u'20160831_180303_0e26', u'20160831_180301_0e26', u'20160831_143847_0c79', u'20160831_143846_0c79', u'20160831_143845_0c79', u'20160831_143843_1_0c79', u'20160831_180236_0e0e', u'20160831_180235_0e0e', u'20160831_180234_0e0e']
Since we just want a single image, and this is only a demonstration, for our purposes here we can arbitrarily select the first image in that list. Let's do that, and get the asset
list available for that image:
# For demo purposes, just grab the first image ID id0 = image_ids[0] id0_url = 'https://api.planet.com/data/v1/item-types/{}/items/{}/assets'.format(item_type, id0) # Returns JSON metadata for assets in this ID. Learn more: planet.com/docs/reference/data-api/items-assets/#asset result = \ requests.get( id0_url, auth=HTTPBasicAuth(PLANET_API_KEY, '') ) # List of asset types available for this particular satellite image print(result.json().keys())
[u'basic_analytic_rpc_nitf', u'analytic_xml', u'basic_analytic_dn', u'basic_analytic_dn_xml_nitf', u'basic_analytic_dn_nitf', u'basic_analytic_xml', u'basic_analytic_nitf', u'basic_analytic_rpc', u'analytic_dn', u'basic_udm', u'basic_analytic_dn_rpc_nitf', u'analytic', u'analytic_dn_xml', u'basic_analytic_dn_xml', u'basic_analytic_dn_rpc', u'basic_analytic_xml_nitf', u'basic_analytic', u'udm']
## Activation and Downloading
The Data API does not pre-generate assets, so they are not always immediately availiable to download. In order to download an asset, we first have to activate it.
Remember, earlier we decided we wanted a color-corrected image best suited for analytic applications. We can check the status of the analytic asset we want to download like so:
# This is "inactive" if the "analytic" asset has not yet been activated; otherwise 'active' print(result.json()['analytic']['status'])
active
Let's now go ahead and activate that asset for download:
# Parse out useful links links = result.json()[u"analytic"]["_links"] self_link = links["_self"] activation_link = links["activate"] # Request activation of the 'analytic' asset: activate_result = \ requests.get( activation_link, auth=HTTPBasicAuth(PLANET_API_KEY, '') )
At this point, we wait for the activation status for the asset we are requesting to change from inactive
to active
. We can monitor this by polling the "status" of the asset:
activation_status_result = \ requests.get( self_link, auth=HTTPBasicAuth(PLANET_API_KEY, '') ) print(activation_status_result.json()["status"])
active
Once the asset has finished activating (status is "active"), we can download it.
Note: the download link on an active asset is temporary
# Image can be downloaded by making a GET with your Planet API key, from here: download_link = activation_status_result.json()["location"] print(download_link)
https://api.planet.com/data/v1/download?token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzQXRzTGVHRmFKWGtFYm0wcXJQY3FDaWZ4ZXRsRmtaK2pYZlRoNTJKNzlFVzF5UE1LRWxrUTB0NG5tNTM0U1Nhb1JYSnVvV1dIRzAvSlZieThvU205Zz09IiwiaXRlbV90eXBlX2lkIjoiUFNTY2VuZTRCYW5kIiwidG9rZW5fdHlwZSI6InR5cGVkLWl0ZW0iLCJleHAiOjE1Mzc0NTM4NzgsIml0ZW1faWQiOiIyMDE2MDgzMV8xNDM4NDhfMGM3OSIsImFzc2V0X3R5cGUiOiJhbmFseXRpYyJ9.pmHVEPJKibFAj_PqbCvuavPSnRT-MYZMP0Z5X6YTJ1f5sSv-idN9pEPby7Izn8_nqr_8L0dSLSR4UBfqG3z5HA