diff --git a/jupyter-notebooks/workflows/publish-to-arcgis-online/Planet to ArcGIS Image using Requests.ipynb b/jupyter-notebooks/workflows/publish-to-arcgis-online/Planet to ArcGIS Image using Requests.ipynb
deleted file mode 100644
index 1a790851..00000000
--- a/jupyter-notebooks/workflows/publish-to-arcgis-online/Planet to ArcGIS Image using Requests.ipynb
+++ /dev/null
@@ -1,266 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "131cc667",
- "metadata": {},
- "outputs": [],
- "source": [
- "from arcgis.raster.analytics import copy_raster\n",
- "from os import path, listdir, mkdir\n",
- "from zipfile import ZipFile\n",
- "import azure.storage.blob\n",
- "import requests\n",
- "import datetime\n",
- "import pathlib\n",
- "import shutil\n",
- "import arcgis\n",
- "import config #local python file which is storing credentials to ArcGIS Online and Planet's Platform\n",
- "import glob\n",
- "import sys\n",
- "import os\n",
- "\n",
- "arcgis.env.verbose = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "727d826b",
- "metadata": {},
- "outputs": [],
- "source": [
- "planet_api_key = config.planet_api_key"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "c8abec8c",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Provide an order ID. \n",
- "my_order_id = \"INSERT ORDER ID HERE\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "d350f06d",
- "metadata": {},
- "outputs": [],
- "source": [
- "orders_api = 'https://api.planet.com/compute/ops/orders/v2'"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "34fe3f80",
- "metadata": {},
- "outputs": [],
- "source": [
- "def create_planet_session(planet_api_key):\n",
- " \n",
- " session = requests.Session()\n",
- " session.auth = (planet_api_key, \"\")\n",
- " \n",
- " response = session.get(orders_api)\n",
- " \n",
- " try:\n",
- " \n",
- " response = session.get(orders_api)\n",
- " \n",
- " if response.status_code == 200:\n",
- " print(\"Connected to Planet API\")\n",
- " return(session)\n",
- " \n",
- " else:\n",
- " print(\"Failed to connect to Planet API\")\n",
- " return\n",
- " \n",
- " except:\n",
- " e = sys.exc_info()[0]\n",
- " print(\"Error: %s\" % e)\n",
- " \n",
- "\n",
- "def get_order_details(session, order_id):\n",
- " \n",
- " order_url = orders_api + '/' + order_id\n",
- " \n",
- " try:\n",
- " response = session.get(order_url)\n",
- " return response.json()\n",
- " except:\n",
- " e = sys.exc_info()[0]\n",
- " print(\"Error: %s\" % e)\n",
- " \n",
- "def validate_order(order_json):\n",
- "\n",
- " #check if the order has been successfully completed, if not, exit the function\n",
- " if order_json['state'] != 'success':\n",
- " print(\"Order isn't completed yet\")\n",
- " return False\n",
- " \n",
- " #also check that this is 8 band PlanetScope imagery\n",
- " if order_json[\"products\"][0][\"product_bundle\"] != \"analytic_8b_sr_udm2\":\n",
- " print(\"Order is not 8 band PlanetScope Imagery\")\n",
- " return False\n",
- " \n",
- " return True\n",
- "\n",
- "def download_results(results, overwrite=False):\n",
- " results_urls = [r['location'] for r in results['_links']['results']]\n",
- " results_names = [r['name'] for r in results['_links']['results']]\n",
- " print('{} items to download'.format(len(results_urls)))\n",
- " paths=[]\n",
- " \n",
- " for url, name in zip(results_urls, results_names):\n",
- " path = pathlib.Path(os.path.join('home', 'PlanetDownloads', name))\n",
- " \n",
- " paths.append(path)\n",
- " \n",
- " if overwrite or not path.exists():\n",
- " print('downloading {} to {}'.format(name, path))\n",
- " r = requests.get(url, allow_redirects=True)\n",
- " path.parent.mkdir(parents=True, exist_ok=True)\n",
- " open(path, 'wb').write(r.content)\n",
- " else:\n",
- " print('{} already exists, skipping {}'.format(path, name))\n",
- " \n",
- " zip_files = [x.__str__() for x in paths if x.suffix == \".zip\" ]\n",
- " \n",
- " unzipped_data_directory = pathlib.Path(os.path.join('home', 'unzipped_data'))#\"/arcgis/home/unzipped_data\"\n",
- " \n",
- " for zip_file in zip_files:\n",
- " z = ZipFile(zip_file)\n",
- " z.extractall(path=unzipped_data_directory)\n",
- "\n",
- " tiff_files = glob.glob(os.path.join(unzipped_data_directory, \"**\\*_SR_*.tif\"), recursive = True)\n",
- " return(tiff_files)\n",
- " \n",
- "def publish_to_arcgis_online(tiff_paths, order_name, gis):\n",
- " \n",
- " # Create a unique timestamp\n",
- " timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')\n",
- "\n",
- " # Use timestamp and order name to create a unique name for the image service\n",
- " layer_name = \"PlanetLabs_\" + order_name[:8] + \"_\" + timestamp\n",
- " \n",
- " # Publish your images as an image service to ArcGIS Online\n",
- " # Note that this can take significant time with large datasets\n",
- "\n",
- " published_rasters = copy_raster(input_raster=tiff_paths,\n",
- " outpute_cellsize = {\"distance\":3.5,\"units\":\"meters\"},\n",
- " output_name=layer_name,\n",
- " raster_type_name=\"Raster Dataset\",\n",
- " context={\"outSR\":{\"wkid\":3857},\n",
- " \"resamplingMethod\":\"BILINEAR\",\n",
- " \"compression\":\"LERC 0\",\n",
- " \"bandMapping\":[{\"bandName\":\"coastal_blue\",\"wavelengthMin\":431,\"wavelengthMax\":452},\n",
- " {\"bandName\":\"blue\",\"wavelengthMin\":465,\"wavelengthMax\":515},\n",
- " {\"bandName\":\"green_i\",\"wavelengthMin\":513,\"wavelengthMax\":549},\n",
- " {\"bandName\":\"green\",\"wavelengthMin\":547,\"wavelengthMax\":583},\n",
- " {\"bandName\":\"yellow\",\"wavelengthMin\":600,\"wavelengthMax\":620},\n",
- " {\"bandName\":\"red\",\"wavelengthMin\":650,\"wavelengthMax\":680},\n",
- " {\"bandName\":\"rededge\",\"wavelengthMin\":697,\"wavelengthMax\":713},\n",
- " {\"bandName\":\"nir\",\"wavelengthMin\":845,\"wavelengthMax\":885}\n",
- " ],\n",
- " \"buildFootprints\":False,\n",
- " \"defineNodata\":True,\n",
- " \"noDataArguments\":{\"noDataValues\":[0],\n",
- " \"compositeValue\":True}\n",
- " },\n",
- " gis=gis)\n",
- " \n",
- " return(published_rasters)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "bfb5a5a7",
- "metadata": {},
- "outputs": [],
- "source": [
- "#Create a requests session with Planet API key \n",
- "planet_session = create_planet_session(planet_api_key)\n",
- "\n",
- "#Retrieve order details as JSON\n",
- "order_json = get_order_details(planet_session, my_order_id)\n",
- "\n",
- "#Check if there are zip archives in the order delivery\n",
- "zip_archives = [r['name'] for r in order_json['_links']['results'] if r['name'].endswith(\".zip\")]\n",
- "\n",
- "#if the order meets criteria (8 band planetscope & a completed order)\n",
- "if validate_order(order_json) is True:\n",
- " \n",
- " #if there are zips, unzip and extract\n",
- " #then return the tiff file paths\n",
- " if len(zip_archives)>0:\n",
- " download_paths = download_results(order_json)\n",
- " tiff_paths = extract_zip(download_paths)\n",
- " \n",
- " #else return the tiff paths as URLs to cloud storage\n",
- " else:\n",
- " tiff_paths = [r['location'] for r in order_json['_links']['results'] if '_SR_' in r['name']]\n",
- "\n",
- "\n",
- "#publish to ArcGIS Online\n",
- "gis = arcgis.gis.GIS(url=\"https://www.arcgis.com\", username = config.arcgis_online_username, password = config.arcgis_online_password)\n",
- "image_service = publish_to_arcgis_online(tiff_paths, order_json['name'], gis)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "98597e4b",
- "metadata": {},
- "outputs": [],
- "source": [
- "# view the new imagery layer on an arcgis map\n",
- "# this layer can now be added to other maps, analyzed with ArcGIS Raster Analytics tools, and more\n",
- "\n",
- "my_map = gis.map(location = image_service.extent, zoomlevel = 11)\n",
- "my_map.basemap = \"imagery\"\n",
- "my_map.add_layer(image_service)\n",
- "my_map"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "0ec9e1c6",
- "metadata": {},
- "outputs": [],
- "source": [
- "#delete files after publishing\n",
- "!rm -R /home/PlanetDownloads\n",
- "!rm -R /home/unzipped_data"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.7.13"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/jupyter-notebooks/workflows/publish-to-arcgis-online/Planet to ArcGIS Image using SDKv2.ipynb b/jupyter-notebooks/workflows/publish-to-arcgis-online/Planet to ArcGIS Image using SDKv2.ipynb
deleted file mode 100644
index 6104ee86..00000000
--- a/jupyter-notebooks/workflows/publish-to-arcgis-online/Planet to ArcGIS Image using SDKv2.ipynb
+++ /dev/null
@@ -1,428 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "5b2ce989",
- "metadata": {},
- "source": [
- "# Publish PlanetScope Imagery to ArcGIS Image for ArcGIS Online\n",
- "\n",
- "This script takes activated Planet orders and publishes them as Image Services with ArcGIS Online. With Planet imagery published in ArcGIS Online, you are able to:\n",
- "\n",
- "* Use the imagery in analytics workflows using raster functions or raster analytics\n",
- "* Access full bit-depth imagery for custom stretching or band combinations performed on the fly\n",
- "* Securely share imagery with your end-users since it is hosted inside of ArcGIS Online\n",
- "\n",
- "This script specifically works with PlanetScope 8-band analytics surface reflectance assets, but could be modified to work with additional asset types. For example, this could be extended to support Planet Basemaps or SkySat imagery.\n",
- "\n",
- "### Prerequisites\n",
- "\n",
- "* Access to the Planet API's (Don't have access? ([Sign up for our Developer Trial to get access!](https://developers.planet.com/devtrial/))\n",
- "* Access to ArcGIS Online with an [ArcGIS Image for ArcGIS Online license](https://www.esri.com/en-us/arcgis/products/arcgis-image/options/arcgis-online)\n",
- "* A previously placed order for PlanetScope 8-band imagery, either through our [Order's API](https://developers.planet.com/docs/orders/), [ArcGIS Pro Integration](https://developers.planet.com/docs/integrations/arcgis/), or [Explorer](https://www.planet.com/explorer)\n",
- "* Edit the config.py file in this notebooks folder which is used to store credentials for ArcGIS Online and Planet's platform.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "b8616126",
- "metadata": {},
- "outputs": [],
- "source": [
- "from arcgis.raster.analytics import copy_raster\n",
- "from zipfile import ZipFile\n",
- "import azure.storage.blob\n",
- "import datetime\n",
- "import shutil\n",
- "import arcgis\n",
- "import planet\n",
- "import config #local python file which is storing credentials to ArcGIS Online and Planet's Platform\n",
- "import glob\n",
- "import os\n",
- "\n",
- "arcgis.env.verbose = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "2bc129b7",
- "metadata": {},
- "outputs": [],
- "source": [
- "planet_auth = planet.auth.APIKeyAuth(config.planet_api_key)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "dec189be",
- "metadata": {},
- "source": [
- "First, you need to provide an order ID to publish. You could get the order ID from:\n",
- "\n",
- "* Manually from [Planet Explorer](https://www.planet.com/explorer) or your [planet.com account orders page](https://www.planet.com/account/#/orders)\n",
- "* Or programatically from Planet's Orders API\n",
- "\n",
- "For example, a script could be used to search for orders from with the last 24 hours to be published to ArcGIS Online.\n",
- "\n",
- "For this script, choose an order for the asset type analytic_8b_sr_udm2
and which was not delivered to hosted data."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "id": "b0fcd186",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Provide an order ID. \n",
- "my_order_id = \"INSERT ORDER ID HERE\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "4aa7f645",
- "metadata": {},
- "outputs": [],
- "source": [
- "async def get_images(my_order_id):\n",
- " \"\"\"This function returns either a list tiff URLs or file paths for an order id that is provided as input.\n",
- " \n",
- " The input order is limited to PlanetScope 8-band assets.\"\"\"\n",
- " \n",
- " #create an async Planet API session\n",
- " async with planet.Session() as ps:\n",
- " \n",
- " #create a Planet API client\n",
- " client = planet.OrdersClient(ps)\n",
- " \n",
- " #get the orders details and name\n",
- " order_details = await client.get_order(order_id=my_order_id)\n",
- " order_name = order_details['name']\n",
- "\n",
- " #check if the order has been successfully completed, if not, exit the function\n",
- " if order_details['state'] != 'success':\n",
- " print(\"Order isn't completed yet\")\n",
- " return\n",
- " #also check that this is 8 band PlanetScope imagery\n",
- " if order_details[\"products\"][0][\"product_bundle\"] != \"analytic_8b_sr_udm2\":\n",
- " print(\"Order is not 8 band PlanetScope Imagery\")\n",
- " return\n",
- " \n",
- " #check if the order is zip archives or tiffs\n",
- " #zip archives are the default delivery option for orders placed from GIS integrations and Explorer\n",
- " zip_archives = [r['name'] for r in order_details['_links']['results'] if r['name'].endswith(\".zip\")]\n",
- " \n",
- " #if order is zip archives:\n",
- " # extract zips and get list of tiff file paths\n",
- " #else:\n",
- " # get list tiff urls\n",
- " if len(zip_archives)>0:\n",
- " \n",
- " #download the assets, including zip archives\n",
- " download_results = await client.download_order(my_order_id)\n",
- " \n",
- " #create a list of all zip files that were downloaded\n",
- " zip_files = [x for x in download_results if x.suffix == \".zip\" ]\n",
- " \n",
- " #for each zip file downloaded, extract the files\n",
- " for zip_file in zip_files:\n",
- " #get the folder\n",
- " folder = zip_file.parent.__str__()\n",
- " z = ZipFile(zip_file)\n",
- " z.extractall(os.path.join(os.getcwd(), folder))\n",
- " \n",
- " #create a list of file paths to the downloaded and unzipped tiff file\n",
- " #looking for tiff files using search term *_SR_*.tif to exclude UDMs and metadata files\n",
- " tiff_paths = glob.glob(os.path.join(os.getcwd(), \"**\\\\*_SR_*.tif\"), recursive = True)\n",
- " \n",
- " #return the order name and list of file paths to tiffs\n",
- " return [order_name, tiff_paths]\n",
- " \n",
- " #if the order is not zip archives, but just tiffs\n",
- " #this is the default option when ordering through Planet's API\n",
- " else:\n",
- " \n",
- " #create a list of the URLs directly to tiffs\n",
- " tiff_urls = [r['location'] for r in order_details['_links']['results'] if '_SR_' in r['name']]\n",
- " \n",
- " #return the order name and list of URLs to tiffs\n",
- " return [order_name, tiff_urls]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "id": "4930783b",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "--- Order Name ---\n",
- "wildfire - AGOL Jupyter Notebook test\n",
- "\n",
- "--- TIFF Paths ---\n",
- "['https://api.planet.com/compute/ops/download/?token', 'https://api.planet.com/compute/ops/download/?token']\n"
- ]
- }
- ],
- "source": [
- "# From the above function, we get the order name and the paths to our TIFF files to publish\n",
- "tiffs = await get_images(my_order_id)\n",
- "print(\"--- Order Name ---\")\n",
- "print(tiffs[0])\n",
- "print(\"\\n--- TIFF Paths ---\")\n",
- "print([path[:50] for path in tiffs[1]])"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "13a0ea08",
- "metadata": {},
- "source": [
- "## Publish to ArcGIS Online\n",
- "\n",
- "Now the imagery can be published to ArcGIS Online! Simply authenticate to ArcGIS Online, create a unique name for your imagery layer, and publish the imagery layer."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "id": "50703e4a",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "GIS @ https://PlanetLabs.maps.arcgis.com"
- ],
- "text/plain": [
- "GIS @ https://PlanetLabs.maps.arcgis.com version:10.1"
- ]
- },
- "execution_count": 14,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# Connect to ArcGIS Online\n",
- "gis = arcgis.gis.GIS(url=\"https://www.arcgis.com\", username = config.arcgis_online_username, password = config.arcgis_online_password)\n",
- "gis"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "id": "4c507dd7",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "PlanetLabs_Queretaro_20220613203606\n"
- ]
- }
- ],
- "source": [
- "# Create a unique timestamp\n",
- "timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')\n",
- "\n",
- "# Use timestamp and order name to create a unique name for the image service\n",
- "layer_name = \"PlanetLabs_\" + str(tiffs[0])[:8] + \"_\" + timestamp\n",
- "\n",
- "print(layer_name)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "id": "45991944",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Submitted.\n",
- "Executing...\n",
- "Start Time: Tuesday, June 14, 2022 1:36:20 AM\n",
- "Hosted Imagery Privilege Check: OK\n",
- "Image service {'name': 'PlanetLabs_Queretaro_20220613203606', 'serviceUrl': 'https://tiledimageservices8.arcgis.com/12345/arcgis/rest/services/PlanetLabs_Queretaro_20220613203606/ImageServer'} already existed.\n",
- "Output item id is: 123432542351\n",
- "Output image service url is: https://tiledimageservices8.arcgis.com/12345/arcgis/rest/services/PlanetLabs_Queretaro_20220613203606/ImageServer\n",
- "Output cloud raster name is: PlanetLabs_Queretaro_20220613203606\n",
- "Input raster is: []\n",
- "Org ID is: \n",
- "Org ID is: \n",
- "Hosted data folder is: /cloudStores//\n",
- "Finished creating empty mosaic dataset.\n",
- "Create empty image collection successfully.\n",
- "Add image data to mosaic dataset.\n",
- "Define Nodata pixels...\n",
- "Finished define nodata value.\n",
- "Set mosaic dataset default properties.\n",
- "Publishing Raster...\n",
- "/cloudStores/12345/123432542351/PlanetLabs_Queretaro_20220613203606.crf\n",
- "Updating image service...\n",
- "Updating service with data store URI.\n",
- "Getting image service info...\n",
- "Updating service: https://tiledimageservices8.arcgis.com/12345/arcgis/rest/admin/services/PlanetLabs_Queretaro_20220613203606/ImageServer/edit\n",
- "{'success': True}\n",
- "Portal item refreshed.\n",
- "CopyRaster GP Job: 1234142412 finished successfully.\n"
- ]
- }
- ],
- "source": [
- "# Publish your images as an image service to ArcGIS Online\n",
- "# Note that this can take significant time with large datasets.\n",
- "\n",
- "published_rasters = copy_raster(input_raster=tiffs[1],\n",
- " outpute_cellsize = {\"distance\":3.5,\"units\":\"meters\"},\n",
- " output_name=layer_name,\n",
- " raster_type_name=\"Raster Dataset\",\n",
- " context={\"outSR\":{\"wkid\":3857},\n",
- " \"resamplingMethod\":\"BILINEAR\",\n",
- " \"compression\":\"LERC 0\",\n",
- " \"bandMapping\":[{\"bandName\":\"coastal_blue\",\"wavelengthMin\":431,\"wavelengthMax\":452},\n",
- " {\"bandName\":\"blue\",\"wavelengthMin\":465,\"wavelengthMax\":515},\n",
- " {\"bandName\":\"green_i\",\"wavelengthMin\":513,\"wavelengthMax\":549},\n",
- " {\"bandName\":\"green\",\"wavelengthMin\":547,\"wavelengthMax\":583},\n",
- " {\"bandName\":\"yellow\",\"wavelengthMin\":600,\"wavelengthMax\":620},\n",
- " {\"bandName\":\"red\",\"wavelengthMin\":650,\"wavelengthMax\":680},\n",
- " {\"bandName\":\"rededge\",\"wavelengthMin\":697,\"wavelengthMax\":713},\n",
- " {\"bandName\":\"nir\",\"wavelengthMin\":845,\"wavelengthMax\":885}\n",
- " ],\n",
- " \"buildFootprints\":False,\n",
- " \"defineNodata\":True,\n",
- " \"noDataArguments\":{\"noDataValues\":[0],\n",
- " \"compositeValue\":True}\n",
- " },\n",
- " gis=gis)"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "07122317",
- "metadata": {},
- "source": [
- "## View the New Image Service and Clean Up Folders\n",
- "Now we can view the Image Service by drawing it on a map directly in this notebook! Or you can view it in your ArcGIS Online environment.\n",
- "\n",
- "#### Want to see the data now? [Check out this map here.](https://planetlabs.maps.arcgis.com/apps/instant/basic/index.html?appid=eaeaa5cf78694c63b9955ff7c87e479f)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 24,
- "id": "998c0ed0",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "application/vnd.jupyter.widget-view+json": {
- "model_id": "3c819e6cbaa64666bb64260c161b982f",
- "version_major": 2,
- "version_minor": 0
- },
- "text/plain": [
- "MapView(layout=Layout(height='400px', width='100%'))"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "
analytic_8b_sr_udm2
and which was not delivered to hosted data."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "cb4371ee",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Collect all orders\n",
+ "all_orders = []\n",
+ "\n",
+ "# Get the generator from list_orders\n",
+ "orders_generator = pl.orders.list_orders()\n",
+ "\n",
+ "# Iterate through the generator to get each order\n",
+ "for order in orders_generator:\n",
+ " all_orders.append(order)\n",
+ "\n",
+ "# Extract relevant fields into a list of dictionaries\n",
+ "orders_data = []\n",
+ "for order in all_orders:\n",
+ " # Extract product details if available\n",
+ " item_type = \"N/A\"\n",
+ " product_bundle = \"N/A\"\n",
+ " if order.get('products') and len(order['products']) > 0:\n",
+ " item_type = order['products'][0].get('item_type', 'N/A')\n",
+ " product_bundle = order['products'][0].get('product_bundle', 'N/A')\n",
+ " \n",
+ " # Create a simplified dictionary with just the fields we want\n",
+ " order_info = {\n",
+ " 'ID': order.get('id', 'N/A'),\n",
+ " 'Created': order.get('created_on', 'N/A'),\n",
+ " 'Name': order.get('name', 'N/A'),\n",
+ " 'State': order.get('state', 'N/A'),\n",
+ " 'Item Type': item_type,\n",
+ " 'Product Bundle': product_bundle\n",
+ " }\n",
+ " orders_data.append(order_info)\n",
+ "\n",
+ "# Create and display DataFrame\n",
+ "orders_df = pd.DataFrame(orders_data)\n",
+ "orders_df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "959592a8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Select the first order ID to use in the next steps, or specify your own\n",
+ "my_order_id = orders_df.iloc[0].ID\n",
+ "# my_order_id = \"your-planet-order-id\"\n",
+ "my_order_name = pl.orders.get_order(my_order_id)['name']\n",
+ "\n",
+ "print(f'Order to be published: {my_order_name} - id: {my_order_id}')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "89dff08b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Create download directory if it doesn't exist\n",
+ "download_dir = Path(\"./planet_downloads\")\n",
+ "download_dir.mkdir(exist_ok=True)\n",
+ "\n",
+ "# Create order-specific directory\n",
+ "order_dir = download_dir / my_order_id\n",
+ "order_dir.mkdir(exist_ok=True)\n",
+ "\n",
+ "# Array to store local file paths\n",
+ "local_tiff_files = []\n",
+ "\n",
+ "# Create an async Planet API session\n",
+ "async with planet.Session() as ps:\n",
+ " \n",
+ " # Create a Planet API client using the modern method\n",
+ " client = ps.client('orders')\n",
+ " \n",
+ " # Get the order details and name\n",
+ " order_details = await client.get_order(order_id=my_order_id)\n",
+ " order_name = order_details['name']\n",
+ " print(f\"Processing order: {order_name}\")\n",
+ " print(f\"All files will be stored in: {order_dir}\")\n",
+ "\n",
+ " # Check if the order has been successfully completed\n",
+ " if order_details['state'] != 'success':\n",
+ " print(\"Order isn't completed yet\")\n",
+ " raise Exception(\"Order not ready for download\")\n",
+ "\n",
+ " # Check if the order contains zip archives or direct file links\n",
+ " zip_archives = [r['name'] for r in order_details['_links']['results'] if r['name'].endswith(\".zip\")]\n",
+ " \n",
+ " if len(zip_archives) > 0:\n",
+ " print(\"Order contains zip archives - downloading and extracting...\")\n",
+ " \n",
+ " # Create subfolders for organization\n",
+ " raw_dir = order_dir / \"raw_downloads\"\n",
+ " extracted_dir = order_dir / \"extracted\"\n",
+ " raw_dir.mkdir(exist_ok=True)\n",
+ " extracted_dir.mkdir(exist_ok=True)\n",
+ " \n",
+ " # Download all assets including zip archives to the raw downloads folder within order directory\n",
+ " download_results = await client.download_order(\n",
+ " my_order_id, \n",
+ " directory=raw_dir, # Download to raw folder within order directory\n",
+ " overwrite=True,\n",
+ " progress_bar=True\n",
+ " )\n",
+ " \n",
+ " # Create a list of all zip files that were downloaded\n",
+ " zip_files = [x for x in download_results if x.suffix == \".zip\"]\n",
+ " \n",
+ " # Extract each zip file to the extracted folder\n",
+ " for zip_file in zip_files:\n",
+ " print(f\"Extracting {zip_file.name}...\")\n",
+ " with ZipFile(zip_file) as z:\n",
+ " z.extractall(extracted_dir) # Extract to extracted folder\n",
+ " \n",
+ " # Find all relevant tiff files in the extracted directory\n",
+ " local_tiff_files = [file for file in extracted_dir.glob(\"**/*.tif\") if \"udm\" not in file.name.lower()]\n",
+ "\n",
+ " else:\n",
+ " print(\"Order contains direct file links - downloading individual files...\")\n",
+ " \n",
+ " # Download each tiff file individually to the order directory\n",
+ " for result in order_details['_links']['results']:\n",
+ " filename = result['name']\n",
+ " location = result['location']\n",
+ " \n",
+ " print(f\"Downloading {filename}...\")\n",
+ " downloaded_file = await client.download_asset(\n",
+ " location=location,\n",
+ " filename=filename,\n",
+ " directory=download_dir, # Download directly to order directory\n",
+ " overwrite=True,\n",
+ " progress_bar=True\n",
+ " )\n",
+ " \n",
+ " # Find all relevant tiff files in the extracted directory\n",
+ " local_tiff_files = [file for file in order_dir.glob(\"**/*.tif\") if \"udm\" not in file.name.lower()]\n",
+ " \n",
+ "print(f\"\\nDownload complete! Found {len(local_tiff_files)} SR tiff files:\")\n",
+ "for file_path in local_tiff_files:\n",
+ " print(f\" {file_path}\")\n",
+ "\n",
+ "print(f\"\\nAll files stored in: {order_dir}\")\n",
+ "print(f\"File paths available in 'local_tiff_files' array\")\n",
+ "\n",
+ "# The local_tiff_files array now contains Path objects for all downloaded tiff files\n",
+ "# You can use these for processing and delete them later when done"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a21ed3e0",
+ "metadata": {},
+ "source": [
+ "## Publish to ArcGIS Online\n",
+ "\n",
+ "Now the imagery can be published to ArcGIS Online! Simply authenticate to ArcGIS Online, create a unique name for your imagery layer, and publish the imagery layer."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ee80307f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Connect to ArcGIS Online\n",
+ "gis = arcgis.gis.GIS(url=\"https://www.arcgis.com\", client_id=\"your-arcgis-client-id\")\n",
+ "gis"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "847b1ca8",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if not local_tiff_files:\n",
+ " print(\"No tiff files found. Make sure to run the Planet download code first.\")\n",
+ "else:\n",
+ " # Create a unique timestamp\n",
+ " timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')\n",
+ " \n",
+ " # Use timestamp and order name to create a unique name for the image collection\n",
+ " # Extract a meaningful identifier from the first file name\n",
+ " first_file_stem = local_tiff_files[0].stem\n",
+ " scene_id = first_file_stem.split('_')[0] # Get the scene ID part\n",
+ " layer_name = f\"PlanetLabs_{scene_id}_{timestamp}\"\n",
+ " \n",
+ " print(f\"Creating image collection: {layer_name}\")\n",
+ " print(f\"Processing {len(local_tiff_files)} Planet images...\")\n",
+ " \n",
+ " # Convert Path objects to strings for the API\n",
+ " # Use the order directory directly since everything is now flat\n",
+ " order_dir = download_dir / my_order_id\n",
+ " input_folder = str(order_dir) # Use the order-specific folder containing all images\n",
+ " \n",
+ " # Create the image collection using Planet imagery\n",
+ " # Note: This can take significant time with large datasets\n",
+ " try:\n",
+ " published_imagery_layer = create_image_collection(\n",
+ " image_collection=layer_name,\n",
+ " input_rasters=input_folder,\n",
+ " raster_type_name=\"Raster Dataset\", # Generic raster type - ArcGIS will detect metadata\n",
+ " context={\n",
+ " \"outSR\": {\"wkid\": 3857}, # Web Mercator projection\n",
+ " \"defineNodata\": True,\n",
+ " \"noDataArguments\": {\n",
+ " \"noDataValues\": [0], # Planet uses 0 for nodata\n",
+ " \"compositeValue\": True\n",
+ " },\n",
+ " \"buildFootprints\": True, # Enable footprints for better mosaicking\n",
+ " \"buildOverview\": True,\n",
+ " \"image_collection_properties\": {\n",
+ " \"imageCollectionType\": \"Satellite\"\n",
+ " }\n",
+ " },\n",
+ " gis=gis\n",
+ " )\n",
+ " \n",
+ " print(f\"✅ Successfully created image collection: {layer_name}\")\n",
+ " print(f\"📍 Image service URL: {published_imagery_layer.url}\")\n",
+ " print(f\"🆔 Item ID: {published_imagery_layer.itemid}\")\n",
+ " \n",
+ " # Store the result for later use\n",
+ " planet_image_collection = published_imagery_layer\n",
+ " \n",
+ " except Exception as e:\n",
+ " print(f\"❌ Error creating image collection: {str(e)}\")\n",
+ " print(\"This might be due to:\")\n",
+ " print(\"- Insufficient ArcGIS Online privileges\")\n",
+ " print(\"- Raster analysis not configured properly\")\n",
+ " print(\"- Large dataset size (try with fewer images first)\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9839139d",
+ "metadata": {},
+ "source": [
+ "## View the New Image Service and Clean Up Folders\n",
+ "Now we can view the Image Service by drawing it on a map directly in this notebook! Or you can view it in your ArcGIS Online environment.\n",
+ "\n",
+ "#### Want to see the data now? [Check out this map here.](https://planetlabs.maps.arcgis.com/apps/instant/basic/index.html?appid=eaeaa5cf78694c63b9955ff7c87e479f)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "8a2a7608",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# view the new imagery layer on an arcgis map\n",
+ "# this layer can now be added to other maps, analyzed with ArcGIS Raster Analytics tools, and more\n",
+ "\n",
+ "my_map = gis.map(location = planet_image_collection.extent, zoomlevel = 11)\n",
+ "my_map.basemap = \"imagery\"\n",
+ "my_map.add_layer(planet_image_collection)\n",
+ "my_map"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "sentinel-hub",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.8"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/jupyter-notebooks/workflows/publish-to-arcgis-online/readme.md b/jupyter-notebooks/workflows/publish-to-arcgis-online/readme.md
index 254791e0..7be6b7db 100644
--- a/jupyter-notebooks/workflows/publish-to-arcgis-online/readme.md
+++ b/jupyter-notebooks/workflows/publish-to-arcgis-online/readme.md
@@ -6,16 +6,8 @@ These notebooks contain samples for publishing PlanetScope imagery as image serv
* Access full bit-depth imagery for custom stretching or band combinations performed on the fly
* Securely share imagery with your end-users using the ArcGIS identity, named users, in ArcGIS Online
-These scripts specifically work with PlanetScope 8-band surface reflectance analytic assets, but could be modified to work with additional asset types and sensors. For example, this could be extended to support Planet Basemaps or SkySat imagery.
-
### Prerequisites
-* An account to access Planet APIs (Don't have access? [Contact Us](https://www.planet.com/contact-sales/))
* Access to ArcGIS Online with an [ArcGIS Image for ArcGIS Online license](https://www.esri.com/en-us/arcgis/products/arcgis-image/options/arcgis-online)
-* A previously placed order for PlanetScope 8-band imagery, either through our [Order's API](https://developers.planet.com/docs/orders/), [ArcGIS Pro Integration](https://developers.planet.com/docs/integrations/arcgis/), or [Explorer](https://www.planet.com/explorer)
-* Edit the config.py file in this notebooks folder which is used to store credentials for ArcGIS Online and Planet's platform.
-
-### Multiple Notebook Versions
+* A previously placed order for PlanetScope imagery, either through our [Order's API](https://developers.planet.com/docs/orders/), [ArcGIS Pro Integration](https://developers.planet.com/docs/integrations/arcgis/), or [Explorer](https://www.planet.com/explorer)
-* Planet to ArcGIS Image using SDKv2 - This notebook uses Planet's new Python SDK for faster and easier access to our API's. In order to use this, you need to install the SDK: [How to install the Planet SDK for Python v2](https://planet-sdk-for-python-v2.readthedocs.io/en/latest/python/sdk-guide/).
-* Planet to ArcGIS Image using Requests - This notebook uses the python library Requests to make the API calls to Planet's platform. It will work when run inside of ArcGIS Notebooks, a hosted Jupyter notebook in ArcGIS Online.