From 9879d4e1ceb8261f78dfe916b5079f8d06f86d52 Mon Sep 17 00:00:00 2001 From: grobson Date: Wed, 12 Oct 2022 16:11:12 +0200 Subject: [PATCH 1/4] Added a couple packages to requirements, added PV subscriptions API notebook, added geojson for demo field --- ...lanetary Variables Subscriptions API.ipynb | 688 ++++++++++++++++++ .../demo_field_DE_v2.geojson | 8 + requirements.txt | 4 +- 3 files changed, 699 insertions(+), 1 deletion(-) create mode 100644 Planetary_Variables_API/Planetary Variables Subscriptions API.ipynb create mode 100644 Planetary_Variables_API/demo_field_DE_v2.geojson diff --git a/Planetary_Variables_API/Planetary Variables Subscriptions API.ipynb b/Planetary_Variables_API/Planetary Variables Subscriptions API.ipynb new file mode 100644 index 0000000..2e8e44c --- /dev/null +++ b/Planetary_Variables_API/Planetary Variables Subscriptions API.ipynb @@ -0,0 +1,688 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "59a2ce51", + "metadata": {}, + "source": [ + "# Using the Planetary Variables Subscriptions API\n", + "\n", + "This Jupyter notebook goes over the useage of the Planetary Variables API. As a demonstration, the example of creating a subscription for Biomass Proxy and downloading some of the resulting TIFs is shown.\n", + "\n", + "For more detailed information, you can see the [Planetary Variables API user guide](https://docs.vandersat.com/data_access/api_user_guide.html#data-subscriptions).\n", + "\n", + "Created October 2022" + ] + }, + { + "cell_type": "markdown", + "id": "ea672af9", + "metadata": {}, + "source": [ + "# Part 0 - Getting set up" + ] + }, + { + "cell_type": "markdown", + "id": "7dc5afde", + "metadata": {}, + "source": [ + "### 0.1 Install the necessary packages using pip and the requirements.txt file" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "afdf24ad", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Looking in indexes: https://pypi.org/simple, https://__token__:****@gitlab.vandersat.com/api/v4/projects/178/packages/pypi/simple\n", + "Requirement already satisfied: planet in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 1)) (1.5.2)\n", + "Requirement already satisfied: requests in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 2)) (2.28.1)\n", + "Requirement already satisfied: numpy in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 3)) (1.21.6)\n", + "Requirement already satisfied: geojson in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 4)) (2.5.0)\n", + "Requirement already satisfied: pandas in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 5)) (1.3.5)\n", + "Requirement already satisfied: geopandas in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 6)) (0.10.2)\n", + "Requirement already satisfied: rasterio in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 7)) (1.2.10)\n", + "Requirement already satisfied: shapely in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 8)) (1.8.4)\n", + "Requirement already satisfied: geojsonio in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 9)) (0.0.3)\n", + "Requirement already satisfied: matplotlib in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 10)) (3.5.3)\n", + "Requirement already satisfied: mercantile in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 11)) (1.2.1)\n", + "Requirement already satisfied: scikit-image in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 12)) (0.19.3)\n", + "Requirement already satisfied: scikit-learn in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 13)) (1.0.2)\n", + "Requirement already satisfied: click in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from planet->-r requirements.txt (line 1)) (8.1.3)\n", + "Requirement already satisfied: requests-futures<1.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from planet->-r requirements.txt (line 1)) (0.9.9)\n", + "Requirement already satisfied: idna<4,>=2.5 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests->-r requirements.txt (line 2)) (3.4)\n", + "Requirement already satisfied: urllib3<1.27,>=1.21.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests->-r requirements.txt (line 2)) (1.26.12)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests->-r requirements.txt (line 2)) (2022.9.24)\n", + "Requirement already satisfied: charset-normalizer<3,>=2 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests->-r requirements.txt (line 2)) (2.1.1)\n", + "Requirement already satisfied: python-dateutil>=2.7.3 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from pandas->-r requirements.txt (line 5)) (2.8.2)\n", + "Requirement already satisfied: pytz>=2017.3 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from pandas->-r requirements.txt (line 5)) (2022.4)\n", + "Requirement already satisfied: fiona>=1.8 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from geopandas->-r requirements.txt (line 6)) (1.8.21)\n", + "Requirement already satisfied: pyproj>=2.2.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from geopandas->-r requirements.txt (line 6)) (3.2.1)\n", + "Requirement already satisfied: affine in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio->-r requirements.txt (line 7)) (2.3.1)\n", + "Requirement already satisfied: cligj>=0.5 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio->-r requirements.txt (line 7)) (0.7.2)\n", + "Requirement already satisfied: setuptools in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio->-r requirements.txt (line 7)) (59.8.0)\n", + "Requirement already satisfied: click-plugins in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio->-r requirements.txt (line 7)) (1.1.1)\n", + "Requirement already satisfied: attrs in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio->-r requirements.txt (line 7)) (22.1.0)\n", + "Requirement already satisfied: snuggs>=1.4.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio->-r requirements.txt (line 7)) (1.4.7)\n", + "Requirement already satisfied: github3.py in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from geojsonio->-r requirements.txt (line 9)) (3.2.0)\n", + "Requirement already satisfied: six in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from geojsonio->-r requirements.txt (line 9)) (1.16.0)\n", + "Requirement already satisfied: packaging>=20.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from matplotlib->-r requirements.txt (line 10)) (21.3)\n", + "Requirement already satisfied: kiwisolver>=1.0.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from matplotlib->-r requirements.txt (line 10)) (1.4.4)\n", + "Requirement already satisfied: pillow>=6.2.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from matplotlib->-r requirements.txt (line 10)) (9.2.0)\n", + "Requirement already satisfied: cycler>=0.10 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from matplotlib->-r requirements.txt (line 10)) (0.11.0)\n", + "Requirement already satisfied: fonttools>=4.22.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from matplotlib->-r requirements.txt (line 10)) (4.37.4)\n", + "Requirement already satisfied: pyparsing>=2.2.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from matplotlib->-r requirements.txt (line 10)) (3.0.9)\n", + "Requirement already satisfied: networkx>=2.2 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from scikit-image->-r requirements.txt (line 12)) (2.6.3)\n", + "Requirement already satisfied: scipy>=1.4.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from scikit-image->-r requirements.txt (line 12)) (1.7.3)\n", + "Requirement already satisfied: tifffile>=2019.7.26 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from scikit-image->-r requirements.txt (line 12)) (2021.11.2)\n", + "Requirement already satisfied: imageio>=2.4.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from scikit-image->-r requirements.txt (line 12)) (2.22.1)\n", + "Requirement already satisfied: PyWavelets>=1.1.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from scikit-image->-r requirements.txt (line 12)) (1.3.0)\n", + "Requirement already satisfied: joblib>=0.11 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from scikit-learn->-r requirements.txt (line 13)) (1.2.0)\n", + "Requirement already satisfied: threadpoolctl>=2.0.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from scikit-learn->-r requirements.txt (line 13)) (3.1.0)\n", + "Requirement already satisfied: importlib-metadata in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from click->planet->-r requirements.txt (line 1)) (5.0.0)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: munch in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from fiona>=1.8->geopandas->-r requirements.txt (line 6)) (2.5.0)\n", + "Requirement already satisfied: typing-extensions in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from kiwisolver>=1.0.1->matplotlib->-r requirements.txt (line 10)) (4.4.0)\n", + "Requirement already satisfied: uritemplate>=3.0.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from github3.py->geojsonio->-r requirements.txt (line 9)) (4.1.1)\n", + "Requirement already satisfied: PyJWT[crypto]>=2.3.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from github3.py->geojsonio->-r requirements.txt (line 9)) (2.5.0)\n", + "Requirement already satisfied: cryptography>=3.3.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from PyJWT[crypto]>=2.3.0->github3.py->geojsonio->-r requirements.txt (line 9)) (38.0.1)\n", + "Requirement already satisfied: types-cryptography>=3.3.21 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from PyJWT[crypto]>=2.3.0->github3.py->geojsonio->-r requirements.txt (line 9)) (3.3.23)\n", + "Requirement already satisfied: zipp>=0.5 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from importlib-metadata->click->planet->-r requirements.txt (line 1)) (3.9.0)\n", + "Requirement already satisfied: cffi>=1.12 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from cryptography>=3.3.1->PyJWT[crypto]>=2.3.0->github3.py->geojsonio->-r requirements.txt (line 9)) (1.15.1)\n", + "Requirement already satisfied: pycparser in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from cffi>=1.12->cryptography>=3.3.1->PyJWT[crypto]>=2.3.0->github3.py->geojsonio->-r requirements.txt (line 9)) (2.21)\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "pip install -r requirements.txt\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "d7fb05ab", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Looking in indexes: https://pypi.org/simple, https://__token__:****@gitlab.vandersat.com/api/v4/projects/178/packages/pypi/simple\n", + "Requirement already satisfied: requests_toolbelt in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (0.10.0)\n", + "Requirement already satisfied: requests<3.0.0,>=2.0.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests_toolbelt) (2.28.1)\n", + "Requirement already satisfied: urllib3<1.27,>=1.21.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests<3.0.0,>=2.0.1->requests_toolbelt) (1.26.12)\n", + "Requirement already satisfied: idna<4,>=2.5 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests<3.0.0,>=2.0.1->requests_toolbelt) (3.4)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests<3.0.0,>=2.0.1->requests_toolbelt) (2022.9.24)\n", + "Requirement already satisfied: charset-normalizer<3,>=2 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests<3.0.0,>=2.0.1->requests_toolbelt) (2.1.1)\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "pip install requests_toolbelt" + ] + }, + { + "cell_type": "markdown", + "id": "bb951a3f", + "metadata": {}, + "source": [ + "### 0.2 Import the necessary packages for this notebook" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4d73cf03", + "metadata": {}, + "outputs": [], + "source": [ + "import glob\n", + "import logging\n", + "import math\n", + "import os\n", + "from typing import Iterator, List\n", + "import geopandas as gpd\n", + "import json\n", + "\n", + "from requests import Response\n", + "from requests_toolbelt.downloadutils import stream\n", + "from requests_toolbelt.exceptions import StreamingError\n", + "from requests_toolbelt.sessions import BaseUrlSession\n" + ] + }, + { + "cell_type": "markdown", + "id": "9925217b", + "metadata": {}, + "source": [ + "### 0.3 API Functions that Run in the Background" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "7229a9e4", + "metadata": {}, + "outputs": [], + "source": [ + "def response_hook(response: Response, *_args, **_kwargs):\n", + " \"\"\"Hook to get detailed error details from the response body.\"\"\"\n", + " if response.status_code >= 400:\n", + " logging.error(\n", + " f\"Error invoking API: url={response.url}; code={response.status_code}; \"\n", + " f\"reason={response.reason}; message={response.text}\"\n", + " )\n", + "\n", + " exit(response.status_code)" + ] + }, + { + "cell_type": "markdown", + "id": "c026623e", + "metadata": {}, + "source": [ + "### 0.4 Enter your credentials for the Planetary Variables API\n", + "It is recommended you do this via the use of environment variables" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "8aeac846", + "metadata": {}, + "outputs": [], + "source": [ + "AUTH = (\"\", \"\")" + ] + }, + { + "cell_type": "markdown", + "id": "13b2a2fb", + "metadata": {}, + "source": [ + "# Part 1 - Creating a new subscription" + ] + }, + { + "cell_type": "markdown", + "id": "2bb3c760", + "metadata": {}, + "source": [ + "### 1.1 Specify the desired dates, product and geometry for your new subscription\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "12b1e069", + "metadata": {}, + "outputs": [], + "source": [ + "# full API name of the desired product, in this case for Biomass Proxy v2.0\n", + "product = \"BIOMASS-PROXY_V2.0_10\"\n", + "\n", + "# between these dates your subscription will be active. the end_date can be in the future\n", + "start_date = \"2022-03-15\"\n", + "end_date = \"2022-09-01\"\n", + "\n", + "# what you would like the same of your data to be\n", + "subscription_name = \"BP Test Data Germany Field 2\"\n", + "\n", + "#path to the geometry of your field in .geojson format\n", + "field_geom_path = \"\"\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "5627bfc9", + "metadata": {}, + "source": [ + "### 1.2 Extract geometry out of geojson file\n", + "This part extracts the geometry of the geojson file provided above so that it is in the correct format for the API to handle." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "88955f74", + "metadata": {}, + "outputs": [], + "source": [ + "geodf = gpd.read_file(field_geom_path)\n", + "feature = json.loads(gpd.GeoSeries(geodf.geometry).to_json())\n", + "feature_geometry = feature['features'][0]['geometry']" + ] + }, + { + "cell_type": "markdown", + "id": "f1a3e658", + "metadata": {}, + "source": [ + "### 1.3 Configure the API session" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "85894c39", + "metadata": {}, + "outputs": [], + "source": [ + "logging.basicConfig(\n", + " level=logging.INFO, format=\"%(asctime)s %(levelname)s %(message)s\"\n", + " )\n", + "session = BaseUrlSession(base_url=\"https://maps.vandersat.com/api/v2/\")\n", + "session.hooks[\"response\"] = [response_hook]\n", + "session.auth = AUTH" + ] + }, + { + "cell_type": "markdown", + "id": "2bb7972a", + "metadata": {}, + "source": [ + "### 1.4 Create a new subscription\n", + "\n", + "Once run, you will see see from the response from the API that a subscription has been created which has a specific unique id (uuid). You should make a note of this uuid as you will need to use it to retreive the data you have requested.\n", + "#### Note if you are requesting a non-field based product (e.g. soil water content or land surface temperature, the data dictionary must contain the extra \"api_requests_type\" argument\") - see below" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "4e5b0c09", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2022-10-12 13:22:53,277 INFO Created subscription: {'uuid': 'e6dbff7f-64c6-427a-b69f-650493c1e8cb', 'created_dt': '2022-10-12T11:22:30.456760', 'modified_dt': '2022-10-12T11:22:30.294933', 'cancelled_dt': None, 'area': 263960.36, 'api_name': 'SM-SMAP-L-DESC_V4.0_100', 'api_request_type': 'gridded-data', 'name': 'BP Test Data Germany Field 2', 'start_date': '2022-03-15', 'end_date': '2022-09-01', 'geojson': {'type': 'MultiPolygon', 'coordinates': [[[[10.932636126, 51.905095484], [10.930368181, 51.912999918], [10.931490742, 51.913195921], [10.933575497, 51.912946463], [10.935428612, 51.912429729], [10.936658083, 51.912376273], [10.937557554, 51.912395783], [10.93770049, 51.911776397], [10.937843425, 51.911228478], [10.937902981, 51.910442335], [10.936914346, 51.909453699], [10.933526452, 51.905965668], [10.932636126, 51.905095484]]]]}, 'arguments': {'min_coverage': 80, 'format': 'gtiff'}, 'http_notify': {'url': None}}\n" + ] + } + ], + "source": [ + "# build a dictionary of the parameters for the subscription which can be passed to the API\n", + "\n", + "# use this one if creating a subscription for a field-based product (e.g. biomass proxy)\n", + "data = {\n", + " \"name\": subscription_name,\n", + " \"api_name\": product,\n", + " \"start_date\": start_date,\n", + " \"end_date\": end_date,\n", + " \"geojson\": feature_geometry,\n", + " }\n", + "\n", + "#use this one if creating a subscription for a non- field-based product (e.g. soil water content, land surface temperature)\n", + "data = {\n", + " \"name\": subscription_name,\n", + " \"api_name\": product,\n", + " \"api_request_type\": \"gridded-data\",\n", + " \"arguments\": {\n", + " \"format\": \"gtiff\",\n", + " \"min_coverage\": 80\n", + " },\n", + " \"start_date\": start_date, \n", + " \"end_date\": end_date,\n", + " \"geojson\": feature_geometry,\n", + " }\n", + "\n", + "result = session.post(url=\"subscriptions\", json=data).json()\n", + "logging.info(f\"Created subscription: {result}\")\n", + "\n", + "# (might take a short while before the response shows below)\n" + ] + }, + { + "cell_type": "markdown", + "id": "62d47140", + "metadata": {}, + "source": [ + "#### Important note: only once a subscription has been made will data processing for the Biomass Proxy begin. Depending on the size of the field, subscription length, and the current processing queue, you will typically have to wait 15 mins + before the data is ready for you to download." + ] + }, + { + "cell_type": "markdown", + "id": "cc5bf013", + "metadata": {}, + "source": [ + "# Part 2 - Downloading data for an exisiting subscription" + ] + }, + { + "cell_type": "markdown", + "id": "0d392af0", + "metadata": {}, + "source": [ + "### 2.1 Configure the API session" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "id": "eabb207e", + "metadata": {}, + "outputs": [], + "source": [ + "logging.basicConfig(\n", + " level=logging.INFO, format=\"%(asctime)s %(levelname)s %(message)s\"\n", + " )\n", + "session = BaseUrlSession(base_url=\"https://maps.vandersat.com/api/v2/\")\n", + "session.hooks[\"response\"] = [response_hook]\n", + "session.auth = AUTH" + ] + }, + { + "cell_type": "markdown", + "id": "3b3b3947", + "metadata": {}, + "source": [ + "### 2.2 Functions needed to download via the API\n", + "Ensure this block is ran before proceeding" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "id": "411ba6ba", + "metadata": {}, + "outputs": [], + "source": [ + "def download_files(session: BaseUrlSession, urls: List[str], output_folder: str):\n", + " \"\"\"Save URL(s) using the Content-Disposition header's file name.\"\"\"\n", + " os.makedirs(output_folder, exist_ok=True)\n", + " for url in urls:\n", + " # Find existing files: assume the Content-Disposition header\n", + " # uses the same name as the URL or at most adds a prefix, so a\n", + " # wildcard search suffices. A real application should not rely\n", + " # on that: use the fulfillment date or UUID to track handling.\n", + " name = url.split(\"/\")[-2]\n", + " existing = glob.glob(os.path.join(output_folder, f\"*{name}\"))\n", + " if existing:\n", + " logging.info(f\"Skipped existing file: name={existing[0]}; url={url}\")\n", + " continue\n", + "\n", + " r = session.get(url=url, stream=True)\n", + " try:\n", + " filename = stream.stream_response_to_file(r, path=output_folder)\n", + " logging.info(f\"Downloaded file: name={filename}\")\n", + " except StreamingError as e:\n", + " logging.error(f\"Failed to download file; error={str(e)}; url={url}\")\n", + "\n", + "\n", + "def get_all_pages(\n", + " session: BaseUrlSession, url: str, page_size: int = 50\n", + ") -> Iterator[dict]:\n", + " \"\"\"Get a generator to fetch paginated API results page by page.\"\"\"\n", + " params = {\"page\": 1, \"limit\": page_size}\n", + " first_page = session.get(url=url, params=params).json()\n", + " yield first_page\n", + "\n", + " page_count = math.ceil(first_page[\"total_items\"] / page_size)\n", + " for params[\"page\"] in range(2, page_count + 1):\n", + " next_page = session.get(url=url, params=params).json()\n", + " yield next_page\n", + " \n", + "\n", + "def handle_fulfillment(\n", + " session: BaseUrlSession, subscription_uuid: str, fulfillment: dict\n", + ") -> bool:\n", + " \"\"\"Handle a single fulfillment, like from an HTTP notification.\"\"\"\n", + " if fulfillment[\"status\"] == \"Ready\":\n", + " output_folder = os.path.join(dir_for_data_download, subscription_uuid)\n", + "\n", + " download_files(session, urls=fulfillment[\"files\"], output_folder=output_folder)\n", + "\n", + " return fulfillment[\"status\"] in (\"Ready\", \"Error\")\n", + "\n", + "\n", + "def get_subscription_fulfillments(\n", + " session: BaseUrlSession, subscription_uuid: str\n", + ") -> bool:\n", + " \"\"\"Get fulfillments; not needed when using HTTP notifications.\"\"\"\n", + " url = f\"subscriptions/{subscription_uuid}/fulfillments\"\n", + " pending = None\n", + " for page in get_all_pages(session, url=url):\n", + " logging.info(f\"Fetched page of fulfillments: result={page}\")\n", + " for fulfillment in page[\"fulfillments\"]:\n", + " pending = pending or not handle_fulfillment(\n", + " session, subscription_uuid=subscription_uuid, fulfillment=fulfillment\n", + " )\n", + " # True if fulfillment(s) found and all were handled, False otherwise\n", + " return not pending\n" + ] + }, + { + "cell_type": "markdown", + "id": "1f444777", + "metadata": {}, + "source": [ + "### 2.3 Download the tif files of your subscription " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e098b5e0", + "metadata": {}, + "outputs": [], + "source": [ + "# the uuid of the subscription you want to download the data for\n", + "uuid = \"cd6d6afa-983e-4dda-b7ee-daa4507a759c\"\n", + "\n", + "# the directory where the data should be saved\n", + "dir_for_data_download = \"\"\n", + "\n", + "while True:\n", + " # Get the fulfillments and download the resulting files\n", + " if get_subscription_fulfillments(session, subscription_uuid=uuid):\n", + " break\n", + " logging.info(\"Not done yet; sleeping 10 minutes\")\n", + " time.sleep(10 * 60)\n", + " \n", + "session.close()" + ] + }, + { + "cell_type": "markdown", + "id": "b13f5412", + "metadata": {}, + "source": [ + "# Part 3 - Visualize a Subscription TIF" + ] + }, + { + "cell_type": "markdown", + "id": "f1cb00ad", + "metadata": {}, + "source": [ + "### 3.0.1 Install required package - rasterio for plotting" + ] + }, + { + "cell_type": "code", + "execution_count": 141, + "id": "c1a863c7", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Looking in indexes: https://pypi.org/simple, https://__token__:****@gitlab.vandersat.com/api/v4/projects/178/packages/pypi/simple\n", + "Requirement already satisfied: rasterio in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (1.2.10)\n", + "Requirement already satisfied: numpy in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (1.21.6)\n", + "Requirement already satisfied: affine in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (2.3.1)\n", + "Requirement already satisfied: certifi in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (2022.9.24)\n", + "Requirement already satisfied: cligj>=0.5 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (0.7.2)\n", + "Requirement already satisfied: snuggs>=1.4.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (1.4.7)\n", + "Requirement already satisfied: setuptools in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (59.8.0)\n", + "Requirement already satisfied: click-plugins in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (1.1.1)\n", + "Requirement already satisfied: click>=4.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (8.1.3)\n", + "Requirement already satisfied: attrs in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (22.1.0)\n", + "Requirement already satisfied: importlib-metadata in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from click>=4.0->rasterio) (5.0.0)\n", + "Requirement already satisfied: pyparsing>=2.1.6 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from snuggs>=1.4.1->rasterio) (3.0.9)\n", + "Requirement already satisfied: zipp>=0.5 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from importlib-metadata->click>=4.0->rasterio) (3.9.0)\n", + "Requirement already satisfied: typing-extensions>=3.6.4 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from importlib-metadata->click>=4.0->rasterio) (4.4.0)\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "pip install rasterio" + ] + }, + { + "cell_type": "markdown", + "id": "5e2f58ac", + "metadata": {}, + "source": [ + "### 3.0.2 Import required packages" + ] + }, + { + "cell_type": "code", + "execution_count": 140, + "id": "d3300a92", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "from rasterio.plot import show" + ] + }, + { + "cell_type": "markdown", + "id": "cf48f278", + "metadata": {}, + "source": [ + "### 3.1 Specify parameters for the plot" + ] + }, + { + "cell_type": "code", + "execution_count": 159, + "id": "26ce277b", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# where your tifs are saved\n", + "path_to_saved_tifs = \"\"\n", + "\n", + "# the uuid of the subscription you would like to visualize\n", + "uuid_to_visualize = \"\"\n", + "\n", + "# the product associated with this subscription that you will plot\n", + "product = \"BIOMASS-PROXY_V2.0_10\"\n", + "\n", + "# the date you would like to visualize\n", + "date_to_visualize = \"2021-07-01\"" + ] + }, + { + "cell_type": "markdown", + "id": "9838642f", + "metadata": {}, + "source": [ + "### 3.2 Visualize a Single TIF with Colorbar using Matplotlib" + ] + }, + { + "cell_type": "code", + "execution_count": 162, + "id": "78e6d282", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 162, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "path_to_tif = os.path.join(path_to_saved_tifs, uuid_to_visualize, \"{}_{}_{}.tif\".format(product, uuid_to_visualize, date_to_visualize))\n", + "\n", + "fig, ax = plt.subplots(figsize=(4, 4))\n", + "ax.set_xlabel(\"Degrees Longitude\")\n", + "ax.set_ylabel(\"Degrees Latitude\")\n", + "ax.ticklabel_format(useOffset=False)\n", + "\n", + "# open the tif file using Rasterio\n", + "img = rasterio.open(path_to_tif)\n", + "\n", + "# plot the opened tif\n", + "plot = show(img, \n", + " ax=ax, \n", + " cmap='Greens')\n", + "\n", + "# add colorbar\n", + "im = image.get_images()[0]\n", + "fig.colorbar(im, ax=ax, label=product, fraction=0.046, pad=0.04)\n", + "\n", + "\n" + ] + } + ], + "metadata": { + "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.7.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Planetary_Variables_API/demo_field_DE_v2.geojson b/Planetary_Variables_API/demo_field_DE_v2.geojson new file mode 100644 index 0000000..32aec93 --- /dev/null +++ b/Planetary_Variables_API/demo_field_DE_v2.geojson @@ -0,0 +1,8 @@ +{ +"type": "FeatureCollection", +"name": "demo_field_DE_v2", +"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, +"features": [ +{ "type": "Feature", "properties": { "id": 1 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 10.932636125734303, 51.905095483725994 ], [ 10.930368181413462, 51.912999917943779 ], [ 10.931490741782236, 51.913195920547849 ], [ 10.933575496752816, 51.912946462688119 ], [ 10.935428612282221, 51.912429728550116 ], [ 10.936658083162307, 51.912376273294456 ], [ 10.937557554450162, 51.912395782941978 ], [ 10.937700489692149, 51.911776396893366 ], [ 10.937843424934137, 51.911228478465745 ], [ 10.937902981284966, 51.910442334634816 ], [ 10.936914345861219, 51.90945369921107 ], [ 10.933526451955526, 51.90596566834023 ], [ 10.932636125734303, 51.905095483725994 ] ] ] ] } } +] +} diff --git a/requirements.txt b/requirements.txt index 32817b0..6f2a15a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,6 @@ geojsonio matplotlib mercantile scikit-image -scikit-learn \ No newline at end of file +scikit-learn +requests_toolbelt +rasterio From 6539e6d5f81707267741be277278435fc5bce780 Mon Sep 17 00:00:00 2001 From: grobson Date: Wed, 12 Oct 2022 16:46:21 +0200 Subject: [PATCH 2/4] cleared output of notebook --- ...riables Subscriptions API-checkpoint.ipynb | 552 ++++++++++++++++++ ...lanetary Variables Subscriptions API.ipynb | 178 +----- 2 files changed, 573 insertions(+), 157 deletions(-) create mode 100644 Planetary_Variables_API/.ipynb_checkpoints/Planetary Variables Subscriptions API-checkpoint.ipynb diff --git a/Planetary_Variables_API/.ipynb_checkpoints/Planetary Variables Subscriptions API-checkpoint.ipynb b/Planetary_Variables_API/.ipynb_checkpoints/Planetary Variables Subscriptions API-checkpoint.ipynb new file mode 100644 index 0000000..46f6c2c --- /dev/null +++ b/Planetary_Variables_API/.ipynb_checkpoints/Planetary Variables Subscriptions API-checkpoint.ipynb @@ -0,0 +1,552 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "59a2ce51", + "metadata": {}, + "source": [ + "# Using the Planetary Variables Subscriptions API\n", + "\n", + "This Jupyter notebook goes over the useage of the Planetary Variables API. As a demonstration, the example of creating a subscription for Biomass Proxy and downloading some of the resulting TIFs is shown.\n", + "\n", + "For more detailed information, you can see the [Planetary Variables API user guide](https://docs.vandersat.com/data_access/api_user_guide.html#data-subscriptions).\n", + "\n", + "Created October 2022" + ] + }, + { + "cell_type": "markdown", + "id": "ea672af9", + "metadata": {}, + "source": [ + "# Part 0 - Getting set up" + ] + }, + { + "cell_type": "markdown", + "id": "7dc5afde", + "metadata": {}, + "source": [ + "### 0.1 Install the necessary packages using pip and the requirements.txt file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "afdf24ad", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "pip install -r requirements.txt\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d7fb05ab", + "metadata": {}, + "outputs": [], + "source": [ + "pip install requests_toolbelt" + ] + }, + { + "cell_type": "markdown", + "id": "bb951a3f", + "metadata": {}, + "source": [ + "### 0.2 Import the necessary packages for this notebook" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4d73cf03", + "metadata": {}, + "outputs": [], + "source": [ + "import glob\n", + "import logging\n", + "import math\n", + "import os\n", + "from typing import Iterator, List\n", + "import geopandas as gpd\n", + "import json\n", + "\n", + "from requests import Response\n", + "from requests_toolbelt.downloadutils import stream\n", + "from requests_toolbelt.exceptions import StreamingError\n", + "from requests_toolbelt.sessions import BaseUrlSession\n" + ] + }, + { + "cell_type": "markdown", + "id": "9925217b", + "metadata": {}, + "source": [ + "### 0.3 API Functions that Run in the Background" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7229a9e4", + "metadata": {}, + "outputs": [], + "source": [ + "def response_hook(response: Response, *_args, **_kwargs):\n", + " \"\"\"Hook to get detailed error details from the response body.\"\"\"\n", + " if response.status_code >= 400:\n", + " logging.error(\n", + " f\"Error invoking API: url={response.url}; code={response.status_code}; \"\n", + " f\"reason={response.reason}; message={response.text}\"\n", + " )\n", + "\n", + " exit(response.status_code)" + ] + }, + { + "cell_type": "markdown", + "id": "c026623e", + "metadata": {}, + "source": [ + "### 0.4 Enter your credentials for the Planetary Variables API\n", + "It is recommended you do this via the use of environment variables" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8aeac846", + "metadata": {}, + "outputs": [], + "source": [ + "AUTH = (\"\", \"\")" + ] + }, + { + "cell_type": "markdown", + "id": "13b2a2fb", + "metadata": {}, + "source": [ + "# Part 1 - Creating a new subscription" + ] + }, + { + "cell_type": "markdown", + "id": "2bb3c760", + "metadata": {}, + "source": [ + "### 1.1 Specify the desired dates, product and geometry for your new subscription\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12b1e069", + "metadata": {}, + "outputs": [], + "source": [ + "# full API name of the desired product, in this case for Biomass Proxy v2.0\n", + "product = \"BIOMASS-PROXY_V2.0_10\"\n", + "\n", + "# between these dates your subscription will be active. the end_date can be in the future\n", + "start_date = \"2022-03-15\"\n", + "end_date = \"2022-09-01\"\n", + "\n", + "# what you would like the same of your data to be\n", + "subscription_name = \"BP Test Data Germany Field 2\"\n", + "\n", + "#path to the geometry of your field in .geojson format\n", + "field_geom_path = \"\"\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "5627bfc9", + "metadata": {}, + "source": [ + "### 1.2 Extract geometry out of geojson file\n", + "This part extracts the geometry of the geojson file provided above so that it is in the correct format for the API to handle." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "88955f74", + "metadata": {}, + "outputs": [], + "source": [ + "geodf = gpd.read_file(field_geom_path)\n", + "feature = json.loads(gpd.GeoSeries(geodf.geometry).to_json())\n", + "feature_geometry = feature['features'][0]['geometry']" + ] + }, + { + "cell_type": "markdown", + "id": "f1a3e658", + "metadata": {}, + "source": [ + "### 1.3 Configure the API session" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "85894c39", + "metadata": {}, + "outputs": [], + "source": [ + "logging.basicConfig(\n", + " level=logging.INFO, format=\"%(asctime)s %(levelname)s %(message)s\"\n", + " )\n", + "session = BaseUrlSession(base_url=\"https://maps.vandersat.com/api/v2/\")\n", + "session.hooks[\"response\"] = [response_hook]\n", + "session.auth = AUTH" + ] + }, + { + "cell_type": "markdown", + "id": "2bb7972a", + "metadata": {}, + "source": [ + "### 1.4 Create a new subscription\n", + "\n", + "Once run, you will see see from the response from the API that a subscription has been created which has a specific unique id (uuid). You should make a note of this uuid as you will need to use it to retreive the data you have requested.\n", + "#### Note if you are requesting a non-field based product (e.g. soil water content or land surface temperature, the data dictionary must contain the extra \"api_requests_type\" argument\") - see below" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4e5b0c09", + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "# build a dictionary of the parameters for the subscription which can be passed to the API\n", + "\n", + "# use this one if creating a subscription for a field-based product (e.g. biomass proxy)\n", + "data = {\n", + " \"name\": subscription_name,\n", + " \"api_name\": product,\n", + " \"start_date\": start_date,\n", + " \"end_date\": end_date,\n", + " \"geojson\": feature_geometry,\n", + " }\n", + "\n", + "#use this one if creating a subscription for a non- field-based product (e.g. soil water content, land surface temperature)\n", + "data = {\n", + " \"name\": subscription_name,\n", + " \"api_name\": product,\n", + " \"api_request_type\": \"gridded-data\",\n", + " \"arguments\": {\n", + " \"format\": \"gtiff\",\n", + " \"min_coverage\": 80\n", + " },\n", + " \"start_date\": start_date, \n", + " \"end_date\": end_date,\n", + " \"geojson\": feature_geometry,\n", + " }\n", + "\n", + "result = session.post(url=\"subscriptions\", json=data).json()\n", + "logging.info(f\"Created subscription: {result}\")\n", + "\n", + "# (might take a short while before the response shows below)\n" + ] + }, + { + "cell_type": "markdown", + "id": "62d47140", + "metadata": {}, + "source": [ + "#### Important note: only once a subscription has been made will data processing for the Biomass Proxy begin. Depending on the size of the field, subscription length, and the current processing queue, you will typically have to wait 15 mins + before the data is ready for you to download." + ] + }, + { + "cell_type": "markdown", + "id": "cc5bf013", + "metadata": {}, + "source": [ + "# Part 2 - Downloading data for an exisiting subscription" + ] + }, + { + "cell_type": "markdown", + "id": "0d392af0", + "metadata": {}, + "source": [ + "### 2.1 Configure the API session" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eabb207e", + "metadata": {}, + "outputs": [], + "source": [ + "logging.basicConfig(\n", + " level=logging.INFO, format=\"%(asctime)s %(levelname)s %(message)s\"\n", + " )\n", + "session = BaseUrlSession(base_url=\"https://maps.vandersat.com/api/v2/\")\n", + "session.hooks[\"response\"] = [response_hook]\n", + "session.auth = AUTH" + ] + }, + { + "cell_type": "markdown", + "id": "3b3b3947", + "metadata": {}, + "source": [ + "### 2.2 Functions needed to download via the API\n", + "Ensure this block is ran before proceeding" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "411ba6ba", + "metadata": {}, + "outputs": [], + "source": [ + "def download_files(session: BaseUrlSession, urls: List[str], output_folder: str):\n", + " \"\"\"Save URL(s) using the Content-Disposition header's file name.\"\"\"\n", + " os.makedirs(output_folder, exist_ok=True)\n", + " for url in urls:\n", + " # Find existing files: assume the Content-Disposition header\n", + " # uses the same name as the URL or at most adds a prefix, so a\n", + " # wildcard search suffices. A real application should not rely\n", + " # on that: use the fulfillment date or UUID to track handling.\n", + " name = url.split(\"/\")[-2]\n", + " existing = glob.glob(os.path.join(output_folder, f\"*{name}\"))\n", + " if existing:\n", + " logging.info(f\"Skipped existing file: name={existing[0]}; url={url}\")\n", + " continue\n", + "\n", + " r = session.get(url=url, stream=True)\n", + " try:\n", + " filename = stream.stream_response_to_file(r, path=output_folder)\n", + " logging.info(f\"Downloaded file: name={filename}\")\n", + " except StreamingError as e:\n", + " logging.error(f\"Failed to download file; error={str(e)}; url={url}\")\n", + "\n", + "\n", + "def get_all_pages(\n", + " session: BaseUrlSession, url: str, page_size: int = 50\n", + ") -> Iterator[dict]:\n", + " \"\"\"Get a generator to fetch paginated API results page by page.\"\"\"\n", + " params = {\"page\": 1, \"limit\": page_size}\n", + " first_page = session.get(url=url, params=params).json()\n", + " yield first_page\n", + "\n", + " page_count = math.ceil(first_page[\"total_items\"] / page_size)\n", + " for params[\"page\"] in range(2, page_count + 1):\n", + " next_page = session.get(url=url, params=params).json()\n", + " yield next_page\n", + " \n", + "\n", + "def handle_fulfillment(\n", + " session: BaseUrlSession, subscription_uuid: str, fulfillment: dict\n", + ") -> bool:\n", + " \"\"\"Handle a single fulfillment, like from an HTTP notification.\"\"\"\n", + " if fulfillment[\"status\"] == \"Ready\":\n", + " output_folder = os.path.join(dir_for_data_download, subscription_uuid)\n", + "\n", + " download_files(session, urls=fulfillment[\"files\"], output_folder=output_folder)\n", + "\n", + " return fulfillment[\"status\"] in (\"Ready\", \"Error\")\n", + "\n", + "\n", + "def get_subscription_fulfillments(\n", + " session: BaseUrlSession, subscription_uuid: str\n", + ") -> bool:\n", + " \"\"\"Get fulfillments; not needed when using HTTP notifications.\"\"\"\n", + " url = f\"subscriptions/{subscription_uuid}/fulfillments\"\n", + " pending = None\n", + " for page in get_all_pages(session, url=url):\n", + " logging.info(f\"Fetched page of fulfillments: result={page}\")\n", + " for fulfillment in page[\"fulfillments\"]:\n", + " pending = pending or not handle_fulfillment(\n", + " session, subscription_uuid=subscription_uuid, fulfillment=fulfillment\n", + " )\n", + " # True if fulfillment(s) found and all were handled, False otherwise\n", + " return not pending\n" + ] + }, + { + "cell_type": "markdown", + "id": "1f444777", + "metadata": {}, + "source": [ + "### 2.3 Download the tif files of your subscription " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e098b5e0", + "metadata": {}, + "outputs": [], + "source": [ + "# the uuid of the subscription you want to download the data for\n", + "uuid = \"cd6d6afa-983e-4dda-b7ee-daa4507a759c\"\n", + "\n", + "# the directory where the data should be saved\n", + "dir_for_data_download = \"\"\n", + "\n", + "while True:\n", + " # Get the fulfillments and download the resulting files\n", + " if get_subscription_fulfillments(session, subscription_uuid=uuid):\n", + " break\n", + " logging.info(\"Not done yet; sleeping 10 minutes\")\n", + " time.sleep(10 * 60)\n", + " \n", + "session.close()" + ] + }, + { + "cell_type": "markdown", + "id": "b13f5412", + "metadata": {}, + "source": [ + "# Part 3 - Visualize a Subscription TIF" + ] + }, + { + "cell_type": "markdown", + "id": "f1cb00ad", + "metadata": {}, + "source": [ + "### 3.0.1 Install required package - rasterio for plotting" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c1a863c7", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "pip install rasterio" + ] + }, + { + "cell_type": "markdown", + "id": "5e2f58ac", + "metadata": {}, + "source": [ + "### 3.0.2 Import required packages" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d3300a92", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "from rasterio.plot import show" + ] + }, + { + "cell_type": "markdown", + "id": "cf48f278", + "metadata": {}, + "source": [ + "### 3.1 Specify parameters for the plot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "26ce277b", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# where your tifs are saved\n", + "path_to_saved_tifs = \"\"\n", + "\n", + "# the uuid of the subscription you would like to visualize\n", + "uuid_to_visualize = \"\"\n", + "\n", + "# the product associated with this subscription that you will plot\n", + "product = \"BIOMASS-PROXY_V2.0_10\"\n", + "\n", + "# the date you would like to visualize\n", + "date_to_visualize = \"2021-07-01\"" + ] + }, + { + "cell_type": "markdown", + "id": "9838642f", + "metadata": {}, + "source": [ + "### 3.2 Visualize a Single TIF with Colorbar using Matplotlib" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "78e6d282", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "path_to_tif = os.path.join(path_to_saved_tifs, uuid_to_visualize, \"{}_{}_{}.tif\".format(product, uuid_to_visualize, date_to_visualize))\n", + "\n", + "fig, ax = plt.subplots(figsize=(4, 4))\n", + "ax.set_xlabel(\"Degrees Longitude\")\n", + "ax.set_ylabel(\"Degrees Latitude\")\n", + "ax.ticklabel_format(useOffset=False)\n", + "\n", + "# open the tif file using Rasterio\n", + "img = rasterio.open(path_to_tif)\n", + "\n", + "# plot the opened tif\n", + "plot = show(img, \n", + " ax=ax, \n", + " cmap='Greens')\n", + "\n", + "# add colorbar\n", + "im = image.get_images()[0]\n", + "fig.colorbar(im, ax=ax, label=product, fraction=0.046, pad=0.04)\n", + "\n", + "\n" + ] + } + ], + "metadata": { + "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.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Planetary_Variables_API/Planetary Variables Subscriptions API.ipynb b/Planetary_Variables_API/Planetary Variables Subscriptions API.ipynb index 2e8e44c..46f6c2c 100644 --- a/Planetary_Variables_API/Planetary Variables Subscriptions API.ipynb +++ b/Planetary_Variables_API/Planetary Variables Subscriptions API.ipynb @@ -32,106 +32,22 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "afdf24ad", "metadata": { "scrolled": true }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Looking in indexes: https://pypi.org/simple, https://__token__:****@gitlab.vandersat.com/api/v4/projects/178/packages/pypi/simple\n", - "Requirement already satisfied: planet in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 1)) (1.5.2)\n", - "Requirement already satisfied: requests in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 2)) (2.28.1)\n", - "Requirement already satisfied: numpy in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 3)) (1.21.6)\n", - "Requirement already satisfied: geojson in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 4)) (2.5.0)\n", - "Requirement already satisfied: pandas in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 5)) (1.3.5)\n", - "Requirement already satisfied: geopandas in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 6)) (0.10.2)\n", - "Requirement already satisfied: rasterio in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 7)) (1.2.10)\n", - "Requirement already satisfied: shapely in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 8)) (1.8.4)\n", - "Requirement already satisfied: geojsonio in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 9)) (0.0.3)\n", - "Requirement already satisfied: matplotlib in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 10)) (3.5.3)\n", - "Requirement already satisfied: mercantile in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 11)) (1.2.1)\n", - "Requirement already satisfied: scikit-image in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 12)) (0.19.3)\n", - "Requirement already satisfied: scikit-learn in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from -r requirements.txt (line 13)) (1.0.2)\n", - "Requirement already satisfied: click in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from planet->-r requirements.txt (line 1)) (8.1.3)\n", - "Requirement already satisfied: requests-futures<1.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from planet->-r requirements.txt (line 1)) (0.9.9)\n", - "Requirement already satisfied: idna<4,>=2.5 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests->-r requirements.txt (line 2)) (3.4)\n", - "Requirement already satisfied: urllib3<1.27,>=1.21.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests->-r requirements.txt (line 2)) (1.26.12)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests->-r requirements.txt (line 2)) (2022.9.24)\n", - "Requirement already satisfied: charset-normalizer<3,>=2 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests->-r requirements.txt (line 2)) (2.1.1)\n", - "Requirement already satisfied: python-dateutil>=2.7.3 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from pandas->-r requirements.txt (line 5)) (2.8.2)\n", - "Requirement already satisfied: pytz>=2017.3 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from pandas->-r requirements.txt (line 5)) (2022.4)\n", - "Requirement already satisfied: fiona>=1.8 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from geopandas->-r requirements.txt (line 6)) (1.8.21)\n", - "Requirement already satisfied: pyproj>=2.2.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from geopandas->-r requirements.txt (line 6)) (3.2.1)\n", - "Requirement already satisfied: affine in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio->-r requirements.txt (line 7)) (2.3.1)\n", - "Requirement already satisfied: cligj>=0.5 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio->-r requirements.txt (line 7)) (0.7.2)\n", - "Requirement already satisfied: setuptools in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio->-r requirements.txt (line 7)) (59.8.0)\n", - "Requirement already satisfied: click-plugins in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio->-r requirements.txt (line 7)) (1.1.1)\n", - "Requirement already satisfied: attrs in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio->-r requirements.txt (line 7)) (22.1.0)\n", - "Requirement already satisfied: snuggs>=1.4.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio->-r requirements.txt (line 7)) (1.4.7)\n", - "Requirement already satisfied: github3.py in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from geojsonio->-r requirements.txt (line 9)) (3.2.0)\n", - "Requirement already satisfied: six in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from geojsonio->-r requirements.txt (line 9)) (1.16.0)\n", - "Requirement already satisfied: packaging>=20.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from matplotlib->-r requirements.txt (line 10)) (21.3)\n", - "Requirement already satisfied: kiwisolver>=1.0.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from matplotlib->-r requirements.txt (line 10)) (1.4.4)\n", - "Requirement already satisfied: pillow>=6.2.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from matplotlib->-r requirements.txt (line 10)) (9.2.0)\n", - "Requirement already satisfied: cycler>=0.10 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from matplotlib->-r requirements.txt (line 10)) (0.11.0)\n", - "Requirement already satisfied: fonttools>=4.22.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from matplotlib->-r requirements.txt (line 10)) (4.37.4)\n", - "Requirement already satisfied: pyparsing>=2.2.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from matplotlib->-r requirements.txt (line 10)) (3.0.9)\n", - "Requirement already satisfied: networkx>=2.2 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from scikit-image->-r requirements.txt (line 12)) (2.6.3)\n", - "Requirement already satisfied: scipy>=1.4.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from scikit-image->-r requirements.txt (line 12)) (1.7.3)\n", - "Requirement already satisfied: tifffile>=2019.7.26 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from scikit-image->-r requirements.txt (line 12)) (2021.11.2)\n", - "Requirement already satisfied: imageio>=2.4.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from scikit-image->-r requirements.txt (line 12)) (2.22.1)\n", - "Requirement already satisfied: PyWavelets>=1.1.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from scikit-image->-r requirements.txt (line 12)) (1.3.0)\n", - "Requirement already satisfied: joblib>=0.11 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from scikit-learn->-r requirements.txt (line 13)) (1.2.0)\n", - "Requirement already satisfied: threadpoolctl>=2.0.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from scikit-learn->-r requirements.txt (line 13)) (3.1.0)\n", - "Requirement already satisfied: importlib-metadata in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from click->planet->-r requirements.txt (line 1)) (5.0.0)\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: munch in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from fiona>=1.8->geopandas->-r requirements.txt (line 6)) (2.5.0)\n", - "Requirement already satisfied: typing-extensions in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from kiwisolver>=1.0.1->matplotlib->-r requirements.txt (line 10)) (4.4.0)\n", - "Requirement already satisfied: uritemplate>=3.0.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from github3.py->geojsonio->-r requirements.txt (line 9)) (4.1.1)\n", - "Requirement already satisfied: PyJWT[crypto]>=2.3.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from github3.py->geojsonio->-r requirements.txt (line 9)) (2.5.0)\n", - "Requirement already satisfied: cryptography>=3.3.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from PyJWT[crypto]>=2.3.0->github3.py->geojsonio->-r requirements.txt (line 9)) (38.0.1)\n", - "Requirement already satisfied: types-cryptography>=3.3.21 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from PyJWT[crypto]>=2.3.0->github3.py->geojsonio->-r requirements.txt (line 9)) (3.3.23)\n", - "Requirement already satisfied: zipp>=0.5 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from importlib-metadata->click->planet->-r requirements.txt (line 1)) (3.9.0)\n", - "Requirement already satisfied: cffi>=1.12 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from cryptography>=3.3.1->PyJWT[crypto]>=2.3.0->github3.py->geojsonio->-r requirements.txt (line 9)) (1.15.1)\n", - "Requirement already satisfied: pycparser in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from cffi>=1.12->cryptography>=3.3.1->PyJWT[crypto]>=2.3.0->github3.py->geojsonio->-r requirements.txt (line 9)) (2.21)\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], + "outputs": [], "source": [ "pip install -r requirements.txt\n" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "d7fb05ab", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Looking in indexes: https://pypi.org/simple, https://__token__:****@gitlab.vandersat.com/api/v4/projects/178/packages/pypi/simple\n", - "Requirement already satisfied: requests_toolbelt in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (0.10.0)\n", - "Requirement already satisfied: requests<3.0.0,>=2.0.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests_toolbelt) (2.28.1)\n", - "Requirement already satisfied: urllib3<1.27,>=1.21.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests<3.0.0,>=2.0.1->requests_toolbelt) (1.26.12)\n", - "Requirement already satisfied: idna<4,>=2.5 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests<3.0.0,>=2.0.1->requests_toolbelt) (3.4)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests<3.0.0,>=2.0.1->requests_toolbelt) (2022.9.24)\n", - "Requirement already satisfied: charset-normalizer<3,>=2 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from requests<3.0.0,>=2.0.1->requests_toolbelt) (2.1.1)\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], + "outputs": [], "source": [ "pip install requests_toolbelt" ] @@ -146,7 +62,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "4d73cf03", "metadata": {}, "outputs": [], @@ -175,7 +91,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "7229a9e4", "metadata": {}, "outputs": [], @@ -202,7 +118,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "8aeac846", "metadata": {}, "outputs": [], @@ -228,7 +144,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "id": "12b1e069", "metadata": {}, "outputs": [], @@ -259,7 +175,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "id": "88955f74", "metadata": {}, "outputs": [], @@ -279,7 +195,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "id": "85894c39", "metadata": {}, "outputs": [], @@ -305,20 +221,12 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "id": "4e5b0c09", "metadata": { "scrolled": false }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2022-10-12 13:22:53,277 INFO Created subscription: {'uuid': 'e6dbff7f-64c6-427a-b69f-650493c1e8cb', 'created_dt': '2022-10-12T11:22:30.456760', 'modified_dt': '2022-10-12T11:22:30.294933', 'cancelled_dt': None, 'area': 263960.36, 'api_name': 'SM-SMAP-L-DESC_V4.0_100', 'api_request_type': 'gridded-data', 'name': 'BP Test Data Germany Field 2', 'start_date': '2022-03-15', 'end_date': '2022-09-01', 'geojson': {'type': 'MultiPolygon', 'coordinates': [[[[10.932636126, 51.905095484], [10.930368181, 51.912999918], [10.931490742, 51.913195921], [10.933575497, 51.912946463], [10.935428612, 51.912429729], [10.936658083, 51.912376273], [10.937557554, 51.912395783], [10.93770049, 51.911776397], [10.937843425, 51.911228478], [10.937902981, 51.910442335], [10.936914346, 51.909453699], [10.933526452, 51.905965668], [10.932636126, 51.905095484]]]]}, 'arguments': {'min_coverage': 80, 'format': 'gtiff'}, 'http_notify': {'url': None}}\n" - ] - } - ], + "outputs": [], "source": [ "# build a dictionary of the parameters for the subscription which can be passed to the API\n", "\n", @@ -377,7 +285,7 @@ }, { "cell_type": "code", - "execution_count": 85, + "execution_count": null, "id": "eabb207e", "metadata": {}, "outputs": [], @@ -401,7 +309,7 @@ }, { "cell_type": "code", - "execution_count": 86, + "execution_count": null, "id": "411ba6ba", "metadata": {}, "outputs": [], @@ -519,35 +427,12 @@ }, { "cell_type": "code", - "execution_count": 141, + "execution_count": null, "id": "c1a863c7", "metadata": { "scrolled": true }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Looking in indexes: https://pypi.org/simple, https://__token__:****@gitlab.vandersat.com/api/v4/projects/178/packages/pypi/simple\n", - "Requirement already satisfied: rasterio in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (1.2.10)\n", - "Requirement already satisfied: numpy in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (1.21.6)\n", - "Requirement already satisfied: affine in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (2.3.1)\n", - "Requirement already satisfied: certifi in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (2022.9.24)\n", - "Requirement already satisfied: cligj>=0.5 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (0.7.2)\n", - "Requirement already satisfied: snuggs>=1.4.1 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (1.4.7)\n", - "Requirement already satisfied: setuptools in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (59.8.0)\n", - "Requirement already satisfied: click-plugins in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (1.1.1)\n", - "Requirement already satisfied: click>=4.0 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (8.1.3)\n", - "Requirement already satisfied: attrs in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from rasterio) (22.1.0)\n", - "Requirement already satisfied: importlib-metadata in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from click>=4.0->rasterio) (5.0.0)\n", - "Requirement already satisfied: pyparsing>=2.1.6 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from snuggs>=1.4.1->rasterio) (3.0.9)\n", - "Requirement already satisfied: zipp>=0.5 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from importlib-metadata->click>=4.0->rasterio) (3.9.0)\n", - "Requirement already satisfied: typing-extensions>=3.6.4 in /home/grobson/anaconda3/envs/grobson_training_notebooks/lib/python3.7/site-packages (from importlib-metadata->click>=4.0->rasterio) (4.4.0)\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], + "outputs": [], "source": [ "pip install rasterio" ] @@ -562,7 +447,7 @@ }, { "cell_type": "code", - "execution_count": 140, + "execution_count": null, "id": "d3300a92", "metadata": { "scrolled": true @@ -583,7 +468,7 @@ }, { "cell_type": "code", - "execution_count": 159, + "execution_count": null, "id": "26ce277b", "metadata": { "scrolled": true @@ -613,33 +498,12 @@ }, { "cell_type": "code", - "execution_count": 162, + "execution_count": null, "id": "78e6d282", "metadata": { "scrolled": true }, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 162, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "path_to_tif = os.path.join(path_to_saved_tifs, uuid_to_visualize, \"{}_{}_{}.tif\".format(product, uuid_to_visualize, date_to_visualize))\n", "\n", @@ -680,7 +544,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.12" + "version": "3.9.7" } }, "nbformat": 4, From cc650348c626758186cfdd9226dcba62ddd59869 Mon Sep 17 00:00:00 2001 From: grobson Date: Wed, 1 Feb 2023 16:52:31 +0100 Subject: [PATCH 3/4] changes to PV subscriptions API demo, added a test field --- ...lanetary Variables Subscriptions API.ipynb | 76 ++++++++++--------- .../demo_field_DE_v2.geojson | 8 -- 2 files changed, 40 insertions(+), 44 deletions(-) delete mode 100644 Planetary_Variables_API/demo_field_DE_v2.geojson diff --git a/Planetary_Variables_API/Planetary Variables Subscriptions API.ipynb b/Planetary_Variables_API/Planetary Variables Subscriptions API.ipynb index 46f6c2c..6df4cc9 100644 --- a/Planetary_Variables_API/Planetary Variables Subscriptions API.ipynb +++ b/Planetary_Variables_API/Planetary Variables Subscriptions API.ipynb @@ -27,7 +27,7 @@ "id": "7dc5afde", "metadata": {}, "source": [ - "### 0.1 Install the necessary packages using pip and the requirements.txt file" + "### 0.1 Create an environment and install the necessary packages using pip and the requirements.txt file:" ] }, { @@ -42,16 +42,6 @@ "pip install -r requirements.txt\n" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "d7fb05ab", - "metadata": {}, - "outputs": [], - "source": [ - "pip install requests_toolbelt" - ] - }, { "cell_type": "markdown", "id": "bb951a3f", @@ -74,6 +64,8 @@ "from typing import Iterator, List\n", "import geopandas as gpd\n", "import json\n", + "import time\n", + "import sys\n", "\n", "from requests import Response\n", "from requests_toolbelt.downloadutils import stream\n", @@ -123,7 +115,7 @@ "metadata": {}, "outputs": [], "source": [ - "AUTH = (\"\", \"\")" + "AUTH = (os.getenv(\"PV_DEMO_USER\"), os.getenv(\"PV_DEMO_PASS\"))" ] }, { @@ -157,10 +149,11 @@ "end_date = \"2022-09-01\"\n", "\n", "# what you would like the same of your data to be\n", - "subscription_name = \"BP Test Data Germany Field 2\"\n", + "subscription_name = \"Demo Subscription Biomass Proxy Scotland 1\"\n", "\n", "#path to the geometry of your field in .geojson format\n", - "field_geom_path = \"\"\n", + "\n", + "field_geom_path = open(os.path.join(sys.path[0], \"Files_for_subscription_demo\", \"demo_field_1.geojson\"))\n", "\n" ] }, @@ -239,20 +232,13 @@ " \"geojson\": feature_geometry,\n", " }\n", "\n", - "#use this one if creating a subscription for a non- field-based product (e.g. soil water content, land surface temperature)\n", - "data = {\n", - " \"name\": subscription_name,\n", - " \"api_name\": product,\n", - " \"api_request_type\": \"gridded-data\",\n", - " \"arguments\": {\n", - " \"format\": \"gtiff\",\n", - " \"min_coverage\": 80\n", - " },\n", - " \"start_date\": start_date, \n", - " \"end_date\": end_date,\n", - " \"geojson\": feature_geometry,\n", - " }\n", + "# IMPORTANT NOTE -- \n", + "# if you are creating a subscription for a non-field-based product (i.e. soil water content or land surface temp.)\n", + "# then you need to add an additional entry to the above dictionary e.g.\n", + "\n", + " # \"arguments\": {\"format\": \"gtiff\", \"min_coverage\": 80}\n", "\n", + " \n", "result = session.post(url=\"subscriptions\", json=data).json()\n", "logging.info(f\"Created subscription: {result}\")\n", "\n", @@ -383,7 +369,9 @@ "id": "1f444777", "metadata": {}, "source": [ - "### 2.3 Download the tif files of your subscription " + "### 2.3 Define which subscription you would like to download data for\n", + "\n", + "Since it takes some time for the Biomass Proxy to actually process after a field is submitted and be ready for download, here is a uuid I prepared earlier for use here:" ] }, { @@ -394,10 +382,26 @@ "outputs": [], "source": [ "# the uuid of the subscription you want to download the data for\n", - "uuid = \"cd6d6afa-983e-4dda-b7ee-daa4507a759c\"\n", - "\n", + "uuid = \"401d528b-053b-45ba-b3d1-3cecc5aeb650\"" + ] + }, + { + "cell_type": "markdown", + "id": "efb7f0c1", + "metadata": {}, + "source": [ + "### 2.4 Download the tif files of your subscription " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c91a3752", + "metadata": {}, + "outputs": [], + "source": [ "# the directory where the data should be saved\n", - "dir_for_data_download = \"\"\n", + "dir_for_data_download = os.path.join(sys.path[0], \"bp_tifs_output\")\n", "\n", "while True:\n", " # Get the fulfillments and download the resulting files\n", @@ -414,7 +418,7 @@ "id": "b13f5412", "metadata": {}, "source": [ - "# Part 3 - Visualize a Subscription TIF" + "# Bonus Part - Visualize a Subscription Geotiff File" ] }, { @@ -476,16 +480,16 @@ "outputs": [], "source": [ "# where your tifs are saved\n", - "path_to_saved_tifs = \"\"\n", + "path_to_saved_tifs = os.path.join(sys.path[0], \"bp_tifs_output\")\n", "\n", "# the uuid of the subscription you would like to visualize\n", - "uuid_to_visualize = \"\"\n", + "uuid_to_visualize = \"401d528b-053b-45ba-b3d1-3cecc5aeb650\"\n", "\n", "# the product associated with this subscription that you will plot\n", "product = \"BIOMASS-PROXY_V2.0_10\"\n", "\n", "# the date you would like to visualize\n", - "date_to_visualize = \"2021-07-01\"" + "date_to_visualize = \"2022-05-01\"" ] }, { @@ -544,7 +548,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.7" + "version": "3.11.0" } }, "nbformat": 4, diff --git a/Planetary_Variables_API/demo_field_DE_v2.geojson b/Planetary_Variables_API/demo_field_DE_v2.geojson deleted file mode 100644 index 32aec93..0000000 --- a/Planetary_Variables_API/demo_field_DE_v2.geojson +++ /dev/null @@ -1,8 +0,0 @@ -{ -"type": "FeatureCollection", -"name": "demo_field_DE_v2", -"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, -"features": [ -{ "type": "Feature", "properties": { "id": 1 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 10.932636125734303, 51.905095483725994 ], [ 10.930368181413462, 51.912999917943779 ], [ 10.931490741782236, 51.913195920547849 ], [ 10.933575496752816, 51.912946462688119 ], [ 10.935428612282221, 51.912429728550116 ], [ 10.936658083162307, 51.912376273294456 ], [ 10.937557554450162, 51.912395782941978 ], [ 10.937700489692149, 51.911776396893366 ], [ 10.937843424934137, 51.911228478465745 ], [ 10.937902981284966, 51.910442334634816 ], [ 10.936914345861219, 51.90945369921107 ], [ 10.933526451955526, 51.90596566834023 ], [ 10.932636125734303, 51.905095483725994 ] ] ] ] } } -] -} From 49c08ad1e9f8c438933d9e38ae4902ae2852d8fd Mon Sep 17 00:00:00 2001 From: grobson Date: Wed, 1 Feb 2023 17:20:42 +0100 Subject: [PATCH 4/4] changes to PV subscriptions API demo, added a test field --- ...riables Subscriptions API-checkpoint.ipynb | 76 ++++++++++--------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/Planetary_Variables_API/.ipynb_checkpoints/Planetary Variables Subscriptions API-checkpoint.ipynb b/Planetary_Variables_API/.ipynb_checkpoints/Planetary Variables Subscriptions API-checkpoint.ipynb index 46f6c2c..6df4cc9 100644 --- a/Planetary_Variables_API/.ipynb_checkpoints/Planetary Variables Subscriptions API-checkpoint.ipynb +++ b/Planetary_Variables_API/.ipynb_checkpoints/Planetary Variables Subscriptions API-checkpoint.ipynb @@ -27,7 +27,7 @@ "id": "7dc5afde", "metadata": {}, "source": [ - "### 0.1 Install the necessary packages using pip and the requirements.txt file" + "### 0.1 Create an environment and install the necessary packages using pip and the requirements.txt file:" ] }, { @@ -42,16 +42,6 @@ "pip install -r requirements.txt\n" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "d7fb05ab", - "metadata": {}, - "outputs": [], - "source": [ - "pip install requests_toolbelt" - ] - }, { "cell_type": "markdown", "id": "bb951a3f", @@ -74,6 +64,8 @@ "from typing import Iterator, List\n", "import geopandas as gpd\n", "import json\n", + "import time\n", + "import sys\n", "\n", "from requests import Response\n", "from requests_toolbelt.downloadutils import stream\n", @@ -123,7 +115,7 @@ "metadata": {}, "outputs": [], "source": [ - "AUTH = (\"\", \"\")" + "AUTH = (os.getenv(\"PV_DEMO_USER\"), os.getenv(\"PV_DEMO_PASS\"))" ] }, { @@ -157,10 +149,11 @@ "end_date = \"2022-09-01\"\n", "\n", "# what you would like the same of your data to be\n", - "subscription_name = \"BP Test Data Germany Field 2\"\n", + "subscription_name = \"Demo Subscription Biomass Proxy Scotland 1\"\n", "\n", "#path to the geometry of your field in .geojson format\n", - "field_geom_path = \"\"\n", + "\n", + "field_geom_path = open(os.path.join(sys.path[0], \"Files_for_subscription_demo\", \"demo_field_1.geojson\"))\n", "\n" ] }, @@ -239,20 +232,13 @@ " \"geojson\": feature_geometry,\n", " }\n", "\n", - "#use this one if creating a subscription for a non- field-based product (e.g. soil water content, land surface temperature)\n", - "data = {\n", - " \"name\": subscription_name,\n", - " \"api_name\": product,\n", - " \"api_request_type\": \"gridded-data\",\n", - " \"arguments\": {\n", - " \"format\": \"gtiff\",\n", - " \"min_coverage\": 80\n", - " },\n", - " \"start_date\": start_date, \n", - " \"end_date\": end_date,\n", - " \"geojson\": feature_geometry,\n", - " }\n", + "# IMPORTANT NOTE -- \n", + "# if you are creating a subscription for a non-field-based product (i.e. soil water content or land surface temp.)\n", + "# then you need to add an additional entry to the above dictionary e.g.\n", + "\n", + " # \"arguments\": {\"format\": \"gtiff\", \"min_coverage\": 80}\n", "\n", + " \n", "result = session.post(url=\"subscriptions\", json=data).json()\n", "logging.info(f\"Created subscription: {result}\")\n", "\n", @@ -383,7 +369,9 @@ "id": "1f444777", "metadata": {}, "source": [ - "### 2.3 Download the tif files of your subscription " + "### 2.3 Define which subscription you would like to download data for\n", + "\n", + "Since it takes some time for the Biomass Proxy to actually process after a field is submitted and be ready for download, here is a uuid I prepared earlier for use here:" ] }, { @@ -394,10 +382,26 @@ "outputs": [], "source": [ "# the uuid of the subscription you want to download the data for\n", - "uuid = \"cd6d6afa-983e-4dda-b7ee-daa4507a759c\"\n", - "\n", + "uuid = \"401d528b-053b-45ba-b3d1-3cecc5aeb650\"" + ] + }, + { + "cell_type": "markdown", + "id": "efb7f0c1", + "metadata": {}, + "source": [ + "### 2.4 Download the tif files of your subscription " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c91a3752", + "metadata": {}, + "outputs": [], + "source": [ "# the directory where the data should be saved\n", - "dir_for_data_download = \"\"\n", + "dir_for_data_download = os.path.join(sys.path[0], \"bp_tifs_output\")\n", "\n", "while True:\n", " # Get the fulfillments and download the resulting files\n", @@ -414,7 +418,7 @@ "id": "b13f5412", "metadata": {}, "source": [ - "# Part 3 - Visualize a Subscription TIF" + "# Bonus Part - Visualize a Subscription Geotiff File" ] }, { @@ -476,16 +480,16 @@ "outputs": [], "source": [ "# where your tifs are saved\n", - "path_to_saved_tifs = \"\"\n", + "path_to_saved_tifs = os.path.join(sys.path[0], \"bp_tifs_output\")\n", "\n", "# the uuid of the subscription you would like to visualize\n", - "uuid_to_visualize = \"\"\n", + "uuid_to_visualize = \"401d528b-053b-45ba-b3d1-3cecc5aeb650\"\n", "\n", "# the product associated with this subscription that you will plot\n", "product = \"BIOMASS-PROXY_V2.0_10\"\n", "\n", "# the date you would like to visualize\n", - "date_to_visualize = \"2021-07-01\"" + "date_to_visualize = \"2022-05-01\"" ] }, { @@ -544,7 +548,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.7" + "version": "3.11.0" } }, "nbformat": 4,