|
| 1 | +{ |
| 2 | + "cells": [ |
| 3 | + { |
| 4 | + "cell_type": "markdown", |
| 5 | + "metadata": {}, |
| 6 | + "source": [ |
| 7 | + "# Order and Delivery to Google Earth Engine\n", |
| 8 | + "\n", |
| 9 | + "In this notebook we're going to cover how to order data using the [Orders API](https://developers.planet.com/apis/orders/) and deliver it to [Google Earth Engine (GEE)](https://earthengine.google.com/) using [Planet’s GEE Delivery Integration](https://developers.planet.com/docs/integrations/gee/).\n", |
| 10 | + "\n", |
| 11 | + "This example demonstrates how to:\n", |
| 12 | + "1. Define the data to be ordered\n", |
| 13 | + "2. Build a cloud delivery configuration object (`delivery_config`), which tells the Orders API where to deliver the data\n", |
| 14 | + "3. Build an order request to be sent off to the Orders API, `iowa_order`\n", |
| 15 | + "4. Create the order and have it deliver to your GEE project\n", |
| 16 | + "\n", |
| 17 | + "**Prerequisites:** \n", |
| 18 | + "- [Planet's Python SDK 2.0](https://github.com/planetlabs/planet-client-python) installed and initialized in your environment. Please follow instructions in [our docs](https://planet-sdk-for-python-v2.readthedocs.io/en/latest/get-started/quick-start-guide/) to authenticate your account with Planet servers. (**This notebook is not compatible with earlier versions of Planet's Python SDK**)\n", |
| 19 | + "- An AOI - `iowa_aoi`\n", |
| 20 | + "- Item ID(s) - `iowa_images`\n", |
| 21 | + "- A GEE project with EE API enabled - `planet-devrel-dev`\n", |
| 22 | + "- A pre-existing GEE [ImageCollection](https://developers.google.com/earth-engine/guides/ic_creating) - `gee-integration-testing`\n", |
| 23 | + "- An account with a download quota. Not sure if you have download quota? Please [get in touch](https://www.planet.com/contact-sales/)." |
| 24 | + ] |
| 25 | + }, |
| 26 | + { |
| 27 | + "cell_type": "code", |
| 28 | + "execution_count": 1, |
| 29 | + "metadata": {}, |
| 30 | + "outputs": [], |
| 31 | + "source": [ |
| 32 | + "import planet" |
| 33 | + ] |
| 34 | + }, |
| 35 | + { |
| 36 | + "cell_type": "markdown", |
| 37 | + "metadata": {}, |
| 38 | + "source": [ |
| 39 | + "## Define data to be ordered" |
| 40 | + ] |
| 41 | + }, |
| 42 | + { |
| 43 | + "cell_type": "code", |
| 44 | + "execution_count": 2, |
| 45 | + "metadata": {}, |
| 46 | + "outputs": [], |
| 47 | + "source": [ |
| 48 | + "# The area of interest (AOI) defined as a polygon\n", |
| 49 | + "iowa_aoi = {\n", |
| 50 | + " \"type\":\n", |
| 51 | + " \"Polygon\",\n", |
| 52 | + " \"coordinates\": [[[-91.198465, 42.893071], [-91.121931, 42.893071],\n", |
| 53 | + " [-91.121931, 42.946205], [-91.198465, 42.946205],\n", |
| 54 | + " [-91.198465, 42.893071]]]\n", |
| 55 | + "}\n", |
| 56 | + "\n", |
| 57 | + "# The item IDs we wish to order\n", |
| 58 | + "iowa_images = ['20200925_161029_69_2223', '20200925_161027_48_2223']" |
| 59 | + ] |
| 60 | + }, |
| 61 | + { |
| 62 | + "cell_type": "markdown", |
| 63 | + "metadata": {}, |
| 64 | + "source": [ |
| 65 | + "## Define cloud delivery location\n", |
| 66 | + "This is the *key concept* of this notebook. Here, we are defining a cloud delivery configuration object, `cloud_config`, where we are defining the destination to be Google Earth Engine, in the project named `planet-devrel-dev`, in the ImageCollection named `gee-integration-testing`." |
| 67 | + ] |
| 68 | + }, |
| 69 | + { |
| 70 | + "cell_type": "code", |
| 71 | + "execution_count": 3, |
| 72 | + "metadata": {}, |
| 73 | + "outputs": [], |
| 74 | + "source": [ |
| 75 | + "# Google Earth Engine configuration\n", |
| 76 | + "cloud_config = planet.order_request.google_earth_engine(\n", |
| 77 | + " project='planet-devrel-dev', collection='gee-integration-testing')\n", |
| 78 | + "# Order delivery configuration\n", |
| 79 | + "delivery_config = planet.order_request.delivery(cloud_config=cloud_config)" |
| 80 | + ] |
| 81 | + }, |
| 82 | + { |
| 83 | + "cell_type": "markdown", |
| 84 | + "metadata": {}, |
| 85 | + "source": [ |
| 86 | + "## Build a simple order request\n", |
| 87 | + "Here we are building an order request, where we specify the products we wish to order. Spesifically, here we are requesting the IDs defined in `iowa_images`, as `analytic_udm2` assets, from the Planet Scope Scene product, `PSScene`." |
| 88 | + ] |
| 89 | + }, |
| 90 | + { |
| 91 | + "cell_type": "code", |
| 92 | + "execution_count": 4, |
| 93 | + "metadata": {}, |
| 94 | + "outputs": [ |
| 95 | + { |
| 96 | + "name": "stdout", |
| 97 | + "output_type": "stream", |
| 98 | + "text": [ |
| 99 | + "{'name': 'iowa_order', 'products': [{'item_ids': ['20200925_161029_69_2223', '20200925_161027_48_2223'], 'item_type': 'PSScene', 'product_bundle': 'analytic_sr_udm2'}], 'delivery': {'google_earth_engine': {'project': 'planet-devrel-dev', 'collection': 'gee-integration-testing'}}}\n" |
| 100 | + ] |
| 101 | + } |
| 102 | + ], |
| 103 | + "source": [ |
| 104 | + "# Product description for the order request\n", |
| 105 | + "data_products = [\n", |
| 106 | + " planet.order_request.product(item_ids=iowa_images,\n", |
| 107 | + " product_bundle='analytic_sr_udm2',\n", |
| 108 | + " item_type='PSScene')\n", |
| 109 | + "]\n", |
| 110 | + "\n", |
| 111 | + "# Build the order request\n", |
| 112 | + "iowa_order = planet.order_request.build_request(name='iowa_order',\n", |
| 113 | + " products=data_products,\n", |
| 114 | + " delivery=delivery_config)\n", |
| 115 | + "\n", |
| 116 | + "print(iowa_order)" |
| 117 | + ] |
| 118 | + }, |
| 119 | + { |
| 120 | + "cell_type": "markdown", |
| 121 | + "metadata": {}, |
| 122 | + "source": [ |
| 123 | + "## Create and deliver the order\n", |
| 124 | + "Define a function that will create an order and update you with its progress. In this case, since we specified the delivery destination to be Google Earth Engine with `delivery_config`, it will also wait for it to be delivered to your project." |
| 125 | + ] |
| 126 | + }, |
| 127 | + { |
| 128 | + "cell_type": "code", |
| 129 | + "execution_count": 5, |
| 130 | + "metadata": {}, |
| 131 | + "outputs": [], |
| 132 | + "source": [ |
| 133 | + "async def create_and_deliver_order(order_request, client):\n", |
| 134 | + " '''Create and deliver an order.\n", |
| 135 | + "\n", |
| 136 | + " Parameters:\n", |
| 137 | + " order_request: An order request\n", |
| 138 | + " client: An Order client object\n", |
| 139 | + " '''\n", |
| 140 | + " with planet.reporting.StateBar(state='creating') as reporter:\n", |
| 141 | + " # Place an order to the Orders API\n", |
| 142 | + " order = await client.create_order(order_request)\n", |
| 143 | + " reporter.update(state='created', order_id=order['id'])\n", |
| 144 | + " # Wait while the order is being completed\n", |
| 145 | + " await client.wait(order['id'],\n", |
| 146 | + " callback=reporter.update_state,\n", |
| 147 | + " max_attempts=0)\n", |
| 148 | + "\n", |
| 149 | + " # Grab the details of the orders\n", |
| 150 | + " order_details = await client.get_order(order_id=order['id'])\n", |
| 151 | + "\n", |
| 152 | + " return order_details" |
| 153 | + ] |
| 154 | + }, |
| 155 | + { |
| 156 | + "cell_type": "markdown", |
| 157 | + "metadata": {}, |
| 158 | + "source": [ |
| 159 | + "Create and deliver the order, `iowa_order`, to the GEE project, `planet-devrel-dev`, in the ImageCollection, `gee-integration-testing`." |
| 160 | + ] |
| 161 | + }, |
| 162 | + { |
| 163 | + "cell_type": "code", |
| 164 | + "execution_count": 6, |
| 165 | + "metadata": {}, |
| 166 | + "outputs": [ |
| 167 | + { |
| 168 | + "name": "stderr", |
| 169 | + "output_type": "stream", |
| 170 | + "text": [ |
| 171 | + "54:18 - order befd89fa-d314-4194-9001-1ac656fc8d27 - state: success\n" |
| 172 | + ] |
| 173 | + } |
| 174 | + ], |
| 175 | + "source": [ |
| 176 | + "async with planet.Session() as ps:\n", |
| 177 | + " # The Orders API client\n", |
| 178 | + " client = planet.OrdersClient(ps)\n", |
| 179 | + " # Create the order and deliver it to GEE\n", |
| 180 | + " order_details = await create_and_deliver_order(iowa_order, client)" |
| 181 | + ] |
| 182 | + }, |
| 183 | + { |
| 184 | + "cell_type": "markdown", |
| 185 | + "metadata": {}, |
| 186 | + "source": [ |
| 187 | + "Display the results for the first item data in the order." |
| 188 | + ] |
| 189 | + }, |
| 190 | + { |
| 191 | + "cell_type": "code", |
| 192 | + "execution_count": 7, |
| 193 | + "metadata": {}, |
| 194 | + "outputs": [ |
| 195 | + { |
| 196 | + "name": "stdout", |
| 197 | + "output_type": "stream", |
| 198 | + "text": [ |
| 199 | + "{'delivery': 'success', 'expires_at': '2022-12-01T00:37:11.420Z', 'location': 'https://api.planet.com/compute/ops/download/?token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Njk4NTUwMzEsInN1YiI6IllzV0ZqTDE4c04zeXYyZE1HQmNjeEVjeDFCQ0ZHeVgrUmlZWG9UYkU1Q3lFL2lMblE2VHhVMzBMc3JuczR6aEI5TUZvTmVTc0pHUFEzQ3lkc1hRMDVRPT0iLCJ0b2tlbl90eXBlIjoiZG93bmxvYWQtYXNzZXQtc3RhY2siLCJhb2kiOiIiLCJhc3NldHMiOlt7Iml0ZW1fdHlwZSI6IiIsImFzc2V0X3R5cGUiOiIiLCJpdGVtX2lkIjoiIn1dLCJ1cmwiOiJodHRwczovL3N0b3JhZ2UuZ29vZ2xlYXBpcy5jb20vY29tcHV0ZS1vcmRlcnMtbGl2ZS8yMDIwMDkyNV8xNjEwMjlfNjlfMjIyM18zQl9BbmFseXRpY01TX1NSLnRpZj9YLUdvb2ctQWxnb3JpdGhtPUdPT0c0LVJTQS1TSEEyNTZcdTAwMjZYLUdvb2ctQ3JlZGVudGlhbD1jb21wdXRlLWdjcy1zdmNhY2MlNDBwbGFuZXQtY29tcHV0ZS1wcm9kLmlhbS5nc2VydmljZWFjY291bnQuY29tJTJGMjAyMjExMzAlMkZhdXRvJTJGc3RvcmFnZSUyRmdvb2c0X3JlcXVlc3RcdTAwMjZYLUdvb2ctRGF0ZT0yMDIyMTEzMFQwMDM3MTFaXHUwMDI2WC1Hb29nLUV4cGlyZXM9ODYzOTlcdTAwMjZYLUdvb2ctU2lnbmF0dXJlPWE2OWQxNjE4ZGMwZDk0ODY3Y2I2N2EzY2U3MGUyNTU0M2VhODMyMmU2ZTFmZjFjMjE1NWVlZGU4OGQyYTgyMWVhMWU2MGEzNzRlYWQ5MWVhYjQwMzQ4NmQ4NzNjNzJhZjEzYWEwOTI4ZTVmMmFkNjhlYzU2M2UyZGRiZWQ3ZWZkZWFjOGUyNGJiZDM5MzRmOWFkMTNlMmM5ZjRiMmU0NmUxNjkyYzYzMWY4ZWM4Mjc1ZWRmYzg3ZjE0ZDkxMmNmYjUxMDE2N2IwM2FhMTY5MDRjY2YwNTY1ZjU4MDMzYTg3N2Y1Mzg3ZjI1YjU5ZGFjMTg4MDM1MWI3NGFlMmQyYTgxMWVhNjQ2ZDcwNGIyNTZkZmY5MGIxNWVmYTc2MTBlZWZlMjExMDI4ZTQ0ZDc1MjYxOGY4YzM1MzZkYWFkNmQ4MjJkNDVkZjNiMDNkZGUxOWQ2MDQwNjEzNzA0ZDQ3MWNkOGM5ZGQ1MTFlZWRjYTNjYzJjNWQyZDU4YWQ4YzcwZjhjNGZjOWFjYzBhNmY0NjkwY2I4ZTY0MTY0YTc3Yzc1NjZkMWY1NmI0NWEwOWU5YjY2N2QwYTJmYTM0NmFmYTYxMDQxN2NjODg5MWVlODkzNDhlMDlhNWFiNGQ3MmM0YTA2ZTZiNTk0NTMzMWVlYWQwYjJhNmUxMTFjYjJjMzYwXHUwMDI2WC1Hb29nLVNpZ25lZEhlYWRlcnM9aG9zdCIsInNvdXJjZSI6Ik9yZGVycyBTZXJ2aWNlIn0.FnaAXSRd_oeayLitsmws_dF6Uw-c_17fSSzrQfmAG1SzE7O_T4a1QKh8kAR8ijew0H5URUQm75qRLY6Swt4crQ', 'name': '20200925_161029_69_2223_3B_AnalyticMS_SR.tif'}\n" |
| 200 | + ] |
| 201 | + } |
| 202 | + ], |
| 203 | + "source": [ |
| 204 | + "print(order_details['_links']['results'][0])" |
| 205 | + ] |
| 206 | + }, |
| 207 | + { |
| 208 | + "cell_type": "markdown", |
| 209 | + "metadata": {}, |
| 210 | + "source": [ |
| 211 | + "## Build an order request with clipping and harmonization applied\n", |
| 212 | + "Here we are building an order request similar to the one above, but with [clipping](https://developers.planet.com/apis/orders/tools/#clip) and [harmonization](https://developers.planet.com/apis/orders/tools/#harmonization) applied. Namely, we are asking the Orders API to clip our images to the AOI, as defined by `iowa_aoi`, and radiometrically harmonizing the imagery with Sentinel-2's sensor. It's important to note that although the Orders API supports more tools, clipping and harmonization are the only two that are currently supported with GEE integration." |
| 213 | + ] |
| 214 | + }, |
| 215 | + { |
| 216 | + "cell_type": "code", |
| 217 | + "execution_count": 8, |
| 218 | + "metadata": {}, |
| 219 | + "outputs": [ |
| 220 | + { |
| 221 | + "name": "stdout", |
| 222 | + "output_type": "stream", |
| 223 | + "text": [ |
| 224 | + "{'name': 'iowa_order', 'products': [{'item_ids': ['20200925_161029_69_2223', '20200925_161027_48_2223'], 'item_type': 'PSScene', 'product_bundle': 'analytic_sr_udm2'}], 'delivery': {'google_earth_engine': {'project': 'planet-devrel-dev', 'collection': 'gee-integration-testing'}}, 'tools': [{'clip': {'aoi': {'type': 'Polygon', 'coordinates': [[[-91.198465, 42.893071], [-91.121931, 42.893071], [-91.121931, 42.946205], [-91.198465, 42.946205], [-91.198465, 42.893071]]]}}}, {'harmonize': {'target_sensor': 'Sentinel-2'}}]}\n" |
| 225 | + ] |
| 226 | + } |
| 227 | + ], |
| 228 | + "source": [ |
| 229 | + "# Clip images to the AOI's perimeter and harmonize the data with Dove Classic\n", |
| 230 | + "tools = [\n", |
| 231 | + " planet.order_request.clip_tool(iowa_aoi),\n", |
| 232 | + " planet.order_request.harmonize_tool('Sentinel-2')\n", |
| 233 | + "]\n", |
| 234 | + "\n", |
| 235 | + "# Build the order request\n", |
| 236 | + "iowa_order = planet.order_request.build_request(name='iowa_order',\n", |
| 237 | + " products=data_products,\n", |
| 238 | + " delivery=delivery_config,\n", |
| 239 | + " tools=tools)\n", |
| 240 | + "\n", |
| 241 | + "print(iowa_order)" |
| 242 | + ] |
| 243 | + }, |
| 244 | + { |
| 245 | + "cell_type": "markdown", |
| 246 | + "metadata": {}, |
| 247 | + "source": [ |
| 248 | + "Create and deliver the clipped and harmonized data to `planet-devrel-dev` in `gee-integration-testing`." |
| 249 | + ] |
| 250 | + }, |
| 251 | + { |
| 252 | + "cell_type": "code", |
| 253 | + "execution_count": 9, |
| 254 | + "metadata": {}, |
| 255 | + "outputs": [ |
| 256 | + { |
| 257 | + "name": "stderr", |
| 258 | + "output_type": "stream", |
| 259 | + "text": [ |
| 260 | + "08:16 - order 37d82131-6a36-4b5c-a651-df30ca8ef945 - state: success\n" |
| 261 | + ] |
| 262 | + } |
| 263 | + ], |
| 264 | + "source": [ |
| 265 | + "async with planet.Session() as ps:\n", |
| 266 | + " # The Orders API client\n", |
| 267 | + " client = planet.OrdersClient(ps)\n", |
| 268 | + " # Create the order and deliver it to GEE\n", |
| 269 | + " order_details = await create_and_deliver_order(iowa_order, client)" |
| 270 | + ] |
| 271 | + }, |
| 272 | + { |
| 273 | + "cell_type": "markdown", |
| 274 | + "metadata": {}, |
| 275 | + "source": [ |
| 276 | + "Display the results for the first item data in the order." |
| 277 | + ] |
| 278 | + }, |
| 279 | + { |
| 280 | + "cell_type": "code", |
| 281 | + "execution_count": 10, |
| 282 | + "metadata": {}, |
| 283 | + "outputs": [ |
| 284 | + { |
| 285 | + "name": "stdout", |
| 286 | + "output_type": "stream", |
| 287 | + "text": [ |
| 288 | + "{'delivery': 'success', 'expires_at': '2022-12-01T01:05:06.668Z', 'location': 'https://api.planet.com/compute/ops/download/?token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2Njk4NTY3MDYsInN1YiI6IjdyZW9xVXRQaUQ5WVhaZkpwRU1wUkZQZVVBeFVzcDU2c3NaSnBTN0dMV3RZcWtZSFZJYWhwZXRISER6MHgxZTBTSWVYQk9CWjYrUXRDeDZFYnREVFlRPT0iLCJ0b2tlbl90eXBlIjoiZG93bmxvYWQtYXNzZXQtc3RhY2siLCJhb2kiOiIiLCJhc3NldHMiOlt7Iml0ZW1fdHlwZSI6IiIsImFzc2V0X3R5cGUiOiIiLCJpdGVtX2lkIjoiIn1dLCJ1cmwiOiJodHRwczovL3N0b3JhZ2UuZ29vZ2xlYXBpcy5jb20vY29tcHV0ZS1vcmRlcnMtbGl2ZS8yMDIwMDkyNV8xNjEwMjlfNjlfMjIyM18zQl91ZG0yX2NsaXAudGlmP1gtR29vZy1BbGdvcml0aG09R09PRzQtUlNBLVNIQTI1Nlx1MDAyNlgtR29vZy1DcmVkZW50aWFsPWNvbXB1dGUtZ2NzLXN2Y2FjYyU0MHBsYW5ldC1jb21wdXRlLXByb2QuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20lMkYyMDIyMTEzMCUyRmF1dG8lMkZzdG9yYWdlJTJGZ29vZzRfcmVxdWVzdFx1MDAyNlgtR29vZy1EYXRlPTIwMjIxMTMwVDAxMDUwNlpcdTAwMjZYLUdvb2ctRXhwaXJlcz04NjM5OVx1MDAyNlgtR29vZy1TaWduYXR1cmU9YTExNGE3Mjk3ZTNhZmEwYzRmNmU2ZDQxYjRkNzgxMWQ1YTkwNTcxNjI0MmMxMDUzZWI2OGYxZjE3NjhiY2E3NjNlNzg5ZmViZjAwMzYxYzI1NjgxN2FjMDU2MWY5NTQxMWU0OTI1MmEyMzBkZDQyNDUxNjcyYThlOWRhZDFmNDQwODE1NDVjZDlkYzYxNzI5MTFjZTAyYjkyMmE1OGM3OTJlYWI0NzdlMjY5MjU3ZTM1MWM3ZWVlM2Q0YWI5MjdkZjFjNjg0YWVmM2Q0OTc0NGEzODg1MWRhOTcxMTc2MTZlYjM3ZWM1NGZjMWE4MGIwZTU5MGJkNGUzZWFiMzEyYTY5MmIwZTg2ZmY0OWY0MzYxMjJmODBiZDFlYjIwYTgxZDdhYzMzYTY5YmY3OGExYmIwOWIzZGQ1YTE3MGYyYjE1YzJiZjM0MDk0NjJlY2IwYjIyNThhMjZkY2FkODlkMGExNDkyY2I5MGI1ZjViMmYwN2YyM2Q4MTY0YTljMDRhN2Q4ZWY0M2EzNTJjYTRlN2YwZDQ3MWYzNTZhNjQyMTU2Yzg1NTY3NDY0MDQ3MDUwZDc0NDgyMmU1MjgxZjkzZTM5ZWQ3NmU5YzdlYWZiZmVlY2QyMDgyNTE0MmQ0YmQ2OGRjMmZhNjc1NzNlZmU2ODc0ODk4M2I1YzZjM2MwNTNcdTAwMjZYLUdvb2ctU2lnbmVkSGVhZGVycz1ob3N0Iiwic291cmNlIjoiT3JkZXJzIFNlcnZpY2UifQ.cohH8ih049_CQF3NIEy-yAqAt6Vc_taEnXK5gn4Hwe6W3D3RqJAgoxyC7ZG3UJW0zmCdnq0653JKeAyScK94JQ', 'name': '20200925_161029_69_2223_3B_udm2_clip.tif'}\n" |
| 289 | + ] |
| 290 | + } |
| 291 | + ], |
| 292 | + "source": [ |
| 293 | + "print(order_details['_links']['results'][0])" |
| 294 | + ] |
| 295 | + } |
| 296 | + ], |
| 297 | + "metadata": { |
| 298 | + "kernelspec": { |
| 299 | + "display_name": "Python 3.9.6 64-bit ('3.9.6')", |
| 300 | + "language": "python", |
| 301 | + "name": "python3" |
| 302 | + }, |
| 303 | + "language_info": { |
| 304 | + "codemirror_mode": { |
| 305 | + "name": "ipython", |
| 306 | + "version": 3 |
| 307 | + }, |
| 308 | + "file_extension": ".py", |
| 309 | + "mimetype": "text/x-python", |
| 310 | + "name": "python", |
| 311 | + "nbconvert_exporter": "python", |
| 312 | + "pygments_lexer": "ipython3", |
| 313 | + "version": "3.9.6" |
| 314 | + }, |
| 315 | + "orig_nbformat": 4, |
| 316 | + "vscode": { |
| 317 | + "interpreter": { |
| 318 | + "hash": "1bedda3fce59fa236ffac8164c02851c562f094c6d8f95a48784416ec3bbb813" |
| 319 | + } |
| 320 | + } |
| 321 | + }, |
| 322 | + "nbformat": 4, |
| 323 | + "nbformat_minor": 2 |
| 324 | +} |
0 commit comments