{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "e06a27bf",
   "metadata": {},
   "source": [
    "# PySTAC-Client Introduction\n",
    "\n",
    "This notebook shows basic use of pystac-client to open an API, iterate through Collections and Items, and perform simple spatio-temporal searches."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b65de617",
   "metadata": {},
   "outputs": [],
   "source": [
    "# set pystac_client logger to DEBUG to see API calls\n",
    "import logging\n",
    "\n",
    "from pystac_client import Client\n",
    "\n",
    "logging.basicConfig()\n",
    "logger = logging.getLogger(\"pystac_client\")\n",
    "logger.setLevel(logging.DEBUG)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e16077c",
   "metadata": {},
   "source": [
    "# Client\n",
    "\n",
    "We first connect to an API by retrieving the root catalog, or landing page, of the API with the `Client.open` function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "98942e75",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# STAC API root URL\n",
    "URL = \"https://planetarycomputer.microsoft.com/api/stac/v1\"\n",
    "\n",
    "# custom headers\n",
    "headers = []\n",
    "\n",
    "cat = Client.open(URL, headers=headers)\n",
    "cat"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f6efbb86",
   "metadata": {},
   "source": [
    "# CollectionClient\n",
    "\n",
    "As with a static catalog the `get_collections` function will iterate through the Collections in the Catalog. Notice that because this is an API it can get all the Collections through a single call, rather than having to fetch each one individually."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bb7693fb",
   "metadata": {},
   "outputs": [],
   "source": [
    "for collection in cat.get_collections():\n",
    "    print(collection)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ebab2724-cab3-4fba-b25b-fdfb4e537014",
   "metadata": {},
   "source": [
    "# Collection Search\n",
    "\n",
    "Sometimes, it can be challenging to identify which collection you want to work with. The `collection_search` method allows you to discover collections by applying search filters that will help you find the specific collection(s) you need. Since many STAC APIs have not implemented the collection search extension, `pystac-client` will perform a limited client-side filter if the API does not conform to the collection search spec."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a23a53ec-5b5f-421d-9f0e-01dbde8c3697",
   "metadata": {},
   "outputs": [],
   "source": [
    "collection_search = cat.collection_search(\n",
    "    q=\"ASTER\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "90b3d014-9c8f-4c5b-a94e-bfb7f17380ad",
   "metadata": {},
   "source": [
    "The `collections` method lets you iterate through the results of the search so you can inspect the details of matching collections."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "006f13fd-5e58-4f3f-bd5a-707cd830caa1",
   "metadata": {},
   "outputs": [],
   "source": [
    "for result in collection_search.collections():\n",
    "    print(result.id, f\"{collection.description}\", sep=\"\\n\")\n",
    "    print(\"\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fef20a46",
   "metadata": {},
   "outputs": [],
   "source": [
    "collection = cat.get_collection(\"aster-l1t\")\n",
    "collection"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "47a540fe",
   "metadata": {},
   "source": [
    "# Items\n",
    "\n",
    "The main functions for getting items return iterators, where pystac-client will handle retrieval of additional pages when needed. Note that one request is made for the first ten items, then a second request for the next ten."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "17d6de4b",
   "metadata": {},
   "outputs": [],
   "source": [
    "items = collection.get_items()\n",
    "\n",
    "\n",
    "# flush stdout so we can see the exact order that things happen\n",
    "def get_ten_items(items):\n",
    "    for i, item in enumerate(items):\n",
    "        print(f\"{i}: {item}\", flush=True)\n",
    "        if i == 9:\n",
    "            return\n",
    "\n",
    "\n",
    "print(\"First page\", flush=True)\n",
    "get_ten_items(items)\n",
    "\n",
    "print(\"Second page\", flush=True)\n",
    "get_ten_items(items)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "62e26114",
   "metadata": {},
   "source": [
    "# API Search\n",
    "\n",
    "If the Catalog is an API, we have the ability to search for items based on spatio-temporal properties."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d8af6334",
   "metadata": {},
   "outputs": [],
   "source": [
    "# AOI around Delfzijl, in northern Netherlands\n",
    "geom = {\n",
    "    \"type\": \"Polygon\",\n",
    "    \"coordinates\": [\n",
    "        [\n",
    "            [6.42425537109375, 53.174765470134616],\n",
    "            [7.344360351562499, 53.174765470134616],\n",
    "            [7.344360351562499, 53.67393435835391],\n",
    "            [6.42425537109375, 53.67393435835391],\n",
    "            [6.42425537109375, 53.174765470134616],\n",
    "        ]\n",
    "    ],\n",
    "}\n",
    "\n",
    "# limit sets the # of items per page so we can see multiple pages getting fetched\n",
    "search = cat.search(\n",
    "    max_items=15,\n",
    "    limit=5,\n",
    "    collections=\"aster-l1t\",\n",
    "    intersects=geom,\n",
    "    datetime=\"2000-01-01/2010-12-31\",\n",
    ")\n",
    "\n",
    "items = list(search.items())\n",
    "\n",
    "len(items)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "275f316f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# note that this will work in JupyterLab, but not in a Jupyter Notebook\n",
    "\n",
    "import IPython.display\n",
    "\n",
    "IPython.display.JSON([i.to_dict() for i in items])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "68bf65f2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# this cell can be used in Jupyter Notebook. Use above if using JupyterLab\n",
    "\n",
    "import json\n",
    "import uuid\n",
    "\n",
    "from IPython.display import display_html, display_javascript\n",
    "\n",
    "\n",
    "class RenderJSON(object):\n",
    "    def __init__(self, json_data):\n",
    "        if isinstance(json_data, dict) or isinstance(json_data, list):\n",
    "            self.json_str = json.dumps(json_data)\n",
    "        else:\n",
    "            self.json_str = json_data\n",
    "        self.uuid = str(uuid.uuid4())\n",
    "\n",
    "    def _ipython_display_(self):\n",
    "        display_html(\n",
    "            '<div id=\"{}\" style=\"height: 600px; width:100%;font: 12px/18px monospace '\n",
    "            '!important;\"></div>'.format(self.uuid),\n",
    "            raw=True,\n",
    "        )\n",
    "        display_javascript(\n",
    "            \"\"\"\n",
    "        require([\"https://rawgit.com/caldwell/renderjson/master/renderjson.js\"],\n",
    "            function() {\n",
    "                renderjson.set_show_to_level(2);\n",
    "                document.getElementById('%s').appendChild(renderjson(%s))\n",
    "        });\n",
    "      \"\"\"\n",
    "            % (self.uuid, self.json_str),\n",
    "            raw=True,\n",
    "        )\n",
    "\n",
    "\n",
    "RenderJSON([i.to_dict() for i in items])"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "6b6313dbab648ff537330b996f33bf845c0da10ea77ae70864d6ca8e2699c7ea"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
