diff --git a/tuto_greenit.ipynb b/tuto_greenit.ipynb new file mode 100644 index 0000000..0f792d2 --- /dev/null +++ b/tuto_greenit.ipynb @@ -0,0 +1,3897 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "1d86416d-9940-4b33-a82f-a93a7a6e138f", + "metadata": {}, + "source": [ + "# Best practices for Green IT coding in python\n", + "\n", + "In this tutorial, we’ll explore best practices for a Green IT approach to coding an efficient image processing pipeline. The notebook is structured into three parts, progressing from beginner to advanced levels:\n", + "\n", + "* Good practices in Python code for image processing\n", + "* Optimisation of an NDVI computing on a Sentinel-2 image and a Pleiades image\n", + "* Image compression for performance optimisation\n", + "* Comparison of performances between parallelisation methods and conclusions\n", + "\n", + "In this notebook we will cover two use cases for NDVI computing:\n", + "\n", + "* the first uses a Sentinel 2 image with two single band files (~450 Mo of Data).\n", + "* The second one will use a Pleiades image which is a big multiband file (13 Go of Data).\n", + "\n", + "In each of these use cases we will start from a basic NDVI calculation in standard python code, and optimize this code in different ways to see where you can have performance problems depending on your problematics.\n", + "\n", + "Let's first define everything needed along this notebook." + ] + }, + { + "cell_type": "markdown", + "id": "9a7fe0ae-0549-47cb-af0c-04a83d27324e", + "metadata": {}, + "source": [ + "## Necessary imports for the notebook" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "8966e0c9-d03f-4edf-b1b0-abbb4c4c2c34", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "import rasterio\n", + "import xarray\n", + "import rioxarray as rxr\n", + "from numba import jit,njit\n", + "from xarray import DataArray \n", + "from pathlib import Path\n", + "from typing import List, Tuple, Union, Dict\n", + "from dask import delayed\n", + "from dask.distributed import Client, LocalCluster, Lock\n", + "import dask.array as da\n", + "from rasterio.transform import Affine\n", + "import time\n", + "import os\n", + "import subprocess\n", + "from timeit import timeit" + ] + }, + { + "cell_type": "markdown", + "id": "4c610ea3-563e-4409-9225-1566ae822f3c", + "metadata": {}, + "source": [ + "## Work directories for the notebook\n", + "\n", + "Here we define the directories and the image files used along the notebook. \n", + "* The first use case uses a Sentinel 2 image with 2 files only: the two interesting bands to compute the NDVI B4 (red) and B8 (NIR),\n", + "* The second use case uses a Pleiades image with 1 multiband file, we will compress it and write it as a COG." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "5d7f7644-d20f-4b63-8fa9-76cb1a5c5e4a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "input_dir = \"/work/CAMPUS/DATA/PLUTO/greenIT\"\n", + "output_dir = f\"/work/scratch/data/{os.environ['USER']}/output_greenit\"\n", + "tmp_dir = os.environ['TMPDIR']\n", + "perf_results_dir = f\"{output_dir}/perfos_greenit\"\n", + "s2_b4 = f\"{input_dir}/SENTINEL2B_20240822-105857-973_L2A_T31TCJ_C_V3-1/SENTINEL2B_20240822-105857-973_L2A_T31TCJ_C_V3-1_FRE_B4.tif\"\n", + "s2_b8 = f\"{input_dir}/SENTINEL2B_20240822-105857-973_L2A_T31TCJ_C_V3-1/SENTINEL2B_20240822-105857-973_L2A_T31TCJ_C_V3-1_FRE_B8.tif\"\n", + "phr_product = f\"{input_dir}/IMG_PHR1A_PMS_202304151100243_SEN_6967638101-1_R1C1_wnodata.tif\"\n", + "phr_product_cog = f\"{tmp_dir}/phr_cog.tif\"\n", + "phr_product_lzw = f\"{tmp_dir}/phr_lzw.tif\"" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "2e54c5a1-e9cc-49a8-8e8b-48353177101e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "!mkdir -p {perf_results_dir}" + ] + }, + { + "cell_type": "markdown", + "id": "3c6a05a0-c506-43e1-a352-c5e8e0d6f36e", + "metadata": { + "tags": [] + }, + "source": [ + "# Good pratices for general python coding\n", + "\n", + "## Avoir For loops : benefits of using numpy\n", + "\n", + "Don't use for loops on your data, numpy is made for this use case and provides a big performance difference compared to standard python code. Here is a code snippet that shows the big performance difference to apply a square on 250 000 elements.\n", + "\n", + "For an in-depth comparison of how much numpy is faster than for and while loops, this link provides a complete performance comparison : https://www.blog.duomly.com/loops-in-python-comparison-and-performance/." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "764e50d5-816a-4228-8ae5-9c60efca8c26", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "90.4 ms ± 409 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" + ] + } + ], + "source": [ + "%%timeit\n", + "\n", + "# Calculate square with for loop\n", + "array_forloop = []\n", + "for i in range(0,500):\n", + " for j in range(0,500):\n", + " array_forloop.append((i * j) ** 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "cbc29586-c920-4f27-babc-7273f42e8d49", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "80.9 ms ± 246 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" + ] + } + ], + "source": [ + "%%timeit\n", + "\n", + "# Using list comprehension instead of a for loop is a nice optimisation\n", + "array_forloop = [(i * j)**2 for j in range(0,500) for i in range(0,500)]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "cecef79a-2ada-4df8-bde5-abb60db8a037", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "179 μs ± 1.05 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n" + ] + } + ], + "source": [ + "%%timeit\n", + " \n", + "# Using numpy\n", + "arr = np.arange(250000).reshape((500,500))\n", + "squared_arr = np.square(arr)" + ] + }, + { + "cell_type": "markdown", + "id": "1b0b3e1a-d31c-43c3-a662-720b0e603f14", + "metadata": {}, + "source": [ + "## Searching information in your data\n", + "\n", + "If your code needs to search elements in an image, for example looking at NoData pixels, here again using Numpy is much more performant:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "35d9ffa0-a498-4ab5-ae73-47cb3fb70eb1", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "nd_list = [i for i in range(0,10000)]\n", + "nd_array = np.arange(0,10000)\n", + "\n", + "#Look at an element\n", + "def search_list():\n", + " if 8950 in nd_list:\n", + " pass\n", + "\n", + "def search_numpy():\n", + " if np.where(nd_array==8950):\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "8c0d14ed-2f32-481f-9500-826e57e5aeb8", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "45 μs ± 262 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)\n" + ] + } + ], + "source": [ + "%%timeit\n", + "search_list()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "2b4f8190-fa24-438f-9e8d-d3226a92ad1a", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "6.76 μs ± 37.9 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n" + ] + } + ], + "source": [ + "%%timeit\n", + "search_numpy()" + ] + }, + { + "cell_type": "markdown", + "id": "0d276261-97a0-4123-8b69-b28aca357328", + "metadata": { + "tags": [] + }, + "source": [ + "## Conclusion\n", + "\n", + "* Don't try to reinvent the wheel, use standard and well performing python libraries like numpy\n", + "* Don't use for loops to apply a computing on a bunch of pixels, use numpy instead\n", + "* Use list comprehension as much as possible if you really need a for loop, it is very well documented \n", + "* Use numpy to lookup for data in your dataset\n" + ] + }, + { + "cell_type": "markdown", + "id": "dd8d3604-62d5-42b9-9fd8-01db87528de5", + "metadata": {}, + "source": [ + "# A Green IT approach for coding image processing chains\n", + "\n", + "Now, say we have a use case of image processing calculation, like a NDVI (Normalized Difference Vegetation Index) computation on any compatible satellite product (Sentinel 2, Pleiades). No matter the sensor, or even the real calculation, you usally want to:\n", + "\n", + "1. Read the data from the disk and stack them.\n", + "2. Calculate the associated NDVI, which combines multi-band information into a single band.\n", + "3. Write the resulting image to the disk (or visualize it)\n", + "\n", + "We'll discribe below good pratices and tooling to perform this kind of operations efficiently considering the input product (mainly its size) you have.\n", + "\n", + "In this notebook we will look at a green IT approach of coding, via good pratices in Python. We will have a look at Dask, RioXarray, rasterio, numpy... all these libraries that are widely used in the satellite image processing chains. \n" + ] + }, + { + "cell_type": "markdown", + "id": "94bd1ed8-f2e6-47b9-9b82-94fd0d40ec59", + "metadata": { + "tags": [], + "toc-hr-collapsed": true + }, + "source": [ + "## Creating the Dask Cluster\n", + "\n", + "In order to use dask we first need to create a [LocalCluster](https://docs.dask.org/en/stable/deploying-python.html#localcluster) which allow us to create workers and use [dask's dashboard](https://docs.dask.org/en/latest/dashboard.html).\n", + "\n", + "A indiquer : La parallélisation est simplement activée par l'usage des chunks, et le type de distribution en fonction du cluster Dask ou des paramètres de scheduling (threads vs multiprocess vs Distributed)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "f89bb471-bf40-404a-82e1-ce4e77b14e21", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.10/dist-packages/distributed/node.py:187: UserWarning: Port 8787 is already in use.\n", + "Perhaps you already have a cluster running?\n", + "Hosting the HTTP server on port 38389 instead\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Dask Dashboard: http://127.0.0.1:38389/status\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "
\n", + "
\n", + "

Client

\n", + "

Client-7c734cec-3185-11f0-bf0d-84160c1e7634

\n", + " \n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "
Connection method: Cluster objectCluster type: distributed.LocalCluster
\n", + " Dashboard: http://127.0.0.1:38389/status\n", + "
\n", + "\n", + " \n", + " \n", + " \n", + "\n", + " \n", + "
\n", + "

Cluster Info

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

LocalCluster

\n", + "

fb53dca9

\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "\n", + " \n", + "
\n", + " Dashboard: http://127.0.0.1:38389/status\n", + " \n", + " Workers: 4\n", + "
\n", + " Total threads: 8\n", + " \n", + " Total memory: 56.00 GiB\n", + "
Status: runningUsing processes: True
\n", + "\n", + "
\n", + " \n", + "

Scheduler Info

\n", + "
\n", + "\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

Scheduler

\n", + "

Scheduler-1a5ffc55-29b0-40d2-a7a7-bd31735f7c9b

\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " Comm: tcp://127.0.0.1:36655\n", + " \n", + " Workers: 4\n", + "
\n", + " Dashboard: http://127.0.0.1:38389/status\n", + " \n", + " Total threads: 8\n", + "
\n", + " Started: Just now\n", + " \n", + " Total memory: 56.00 GiB\n", + "
\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "

Workers

\n", + "
\n", + "\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 0

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:33405\n", + " \n", + " Total threads: 2\n", + "
\n", + " Dashboard: http://127.0.0.1:44881/status\n", + " \n", + " Memory: 14.00 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:36553\n", + "
\n", + " Local directory: /tmp/slurm-37316783/dask-scratch-space/worker-rxxjjdmw\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 1

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:46745\n", + " \n", + " Total threads: 2\n", + "
\n", + " Dashboard: http://127.0.0.1:41441/status\n", + " \n", + " Memory: 14.00 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:34339\n", + "
\n", + " Local directory: /tmp/slurm-37316783/dask-scratch-space/worker-9iz3rqy4\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 2

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:37419\n", + " \n", + " Total threads: 2\n", + "
\n", + " Dashboard: http://127.0.0.1:44757/status\n", + " \n", + " Memory: 14.00 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:33795\n", + "
\n", + " Local directory: /tmp/slurm-37316783/dask-scratch-space/worker-arijb96k\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 3

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:33041\n", + " \n", + " Total threads: 2\n", + "
\n", + " Dashboard: http://127.0.0.1:35135/status\n", + " \n", + " Memory: 14.00 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:42175\n", + "
\n", + " Local directory: /tmp/slurm-37316783/dask-scratch-space/worker-62942pym\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "\n", + "
\n", + "
\n", + "\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "\n", + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cluster = LocalCluster()\n", + "client = Client(cluster)\n", + "\n", + "print(\"Dask Dashboard: \", client.dashboard_link)\n", + "client" + ] + }, + { + "cell_type": "markdown", + "id": "2a86c2ad-975b-4ed5-a8b0-8add6c8714d4", + "metadata": {}, + "source": [ + "Dask return an url where the dashboard is availaible (usually http://127.0.0.1:8787/status). This is not a tutorial on how to use this dashboard, but we recommend using it in a separate window while using this notebook." + ] + }, + { + "cell_type": "markdown", + "id": "0e86755c-f505-4d6b-830e-396485e12054", + "metadata": {}, + "source": [ + "# Use Case 1 : Calculation of the Average NDVI on a Sentinel 2 image\n", + "\n", + "In this example, we will use standard python libraries to: \n", + "\n", + "1. Read the data from the disk and stack them.\n", + "2. Calculate the associated NDVI, which combines multi-band information into a single band.\n", + "4. Write the resulting image to the disk.\n", + "\n", + "First, let's read the data we need to perform the NDVI with RasterIO." + ] + }, + { + "cell_type": "markdown", + "id": "fc56a7e0-edb5-4635-b5a2-0b274d08ce38", + "metadata": {}, + "source": [ + "### Basic python code for NDVI\n", + "\n", + "Here we are going to open the raster data required for this tutorial, the Red and NIR bands from a Sentinel-2 acquisition. To do this, we're going to use rasterio which loads the entire product in memory, without using parallelisation." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "b49ad5b8-5e20-4fd0-80e8-117b8a655769", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 155 ms, sys: 813 ms, total: 968 ms\n", + "Wall time: 1.05 s\n" + ] + } + ], + "source": [ + "%%time\n", + "# Open the two rasters we will use for NDVI\n", + "with rasterio.open(s2_b4, 'r') as ds:\n", + " red_band = ds.read()\n", + "\n", + "with rasterio.open(s2_b8, 'r') as ds:\n", + " nir_band = ds.read()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "6c96d32d-4569-4148-bab9-6fb413eb23b5", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 311 ms, sys: 1.15 s, total: 1.46 s\n", + "Wall time: 1.41 s\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "# Compute NDVI with NIR and RED bands\n", + "ndvi_array = (nir_band - red_band) / (nir_band + red_band)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "aa97a310-cb35-498d-8b3a-6e9406cced31", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.10/dist-packages/rasterio/__init__.py:366: NotGeoreferencedWarning: Dataset has no geotransform, gcps, or rpcs. The identity matrix will be returned.\n", + " dataset = writer(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 193 ms, sys: 945 ms, total: 1.14 s\n", + "Wall time: 1.06 s\n" + ] + } + ], + "source": [ + "%%time\n", + "# Write the NDVI product\n", + "output_file = Path(f\"{tmp_dir}/ndvi_basic.tif\")\n", + "with rasterio.open(\n", + " output_file, \"w\",\n", + " driver=\"GTiff\",\n", + " height=ndvi_array.shape[1],\n", + " width=ndvi_array.shape[2],\n", + " count=ndvi_array.shape[0],\n", + " dtype=ndvi_array.dtype\n", + " ) as dst:\n", + " dst.write(ndvi_array)" + ] + }, + { + "cell_type": "markdown", + "id": "402fa1b6-2135-4929-bb3a-93a1228725b5", + "metadata": {}, + "source": [ + "We noticed that the write part was the more consuming in time, it depends on where you write :\n", + "\n", + "* Writing in TMPDIR (available in each user session) directory can improve write time\n", + "* scratch and work use GPFS which involves some caches, which could make the write time randomly longer\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "2dad7fe0-23bc-40b2-b27e-4c7cb0f8dc0e", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 630 ms, sys: 3 s, total: 3.63 s\n", + "Wall time: 3.86 s\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "# Open the two rasters we will use for NDVI\n", + "with rasterio.open(s2_b4, 'r') as ds:\n", + " red_band = ds.read() \n", + "\n", + "with rasterio.open(s2_b8, 'r') as ds:\n", + " nir_band = ds.read()\n", + "\n", + "# Compute NDVI with NIR and RED bands\n", + "ndvi_array = (nir_band - red_band) / (nir_band + red_band)\n", + "\n", + "# Write the NDVI product\n", + "output_file = Path(f\"{output_dir}/ndvi_basic.tif\")\n", + "with rasterio.open(\n", + " output_file, \"w\",\n", + " driver=\"GTiff\",\n", + " height=ndvi_array.shape[1],\n", + " width=ndvi_array.shape[2],\n", + " count=ndvi_array.shape[0],\n", + " dtype=ndvi_array.dtype\n", + " ) as dst:\n", + " dst.write(ndvi_array)" + ] + }, + { + "cell_type": "markdown", + "id": "c867e7a7-ccc1-4387-9dce-712938b282e7", + "metadata": {}, + "source": [ + "## Comparing performance of a basic python code for NDVI with Orfeotoolbox NDVI computing\n", + "\n", + "For comparison purposes, we will use the OrfeoToolbox project, developed by CNES which uses streaming to improve performances.\n", + "OTB provides a python interface to use its applications (coded in C++ internally for performance purpose). We will see that in this case, the **streaming does not really make sense because of the size of the data**" + ] + }, + { + "cell_type": "markdown", + "id": "7f5d09f0-cf39-4e3b-afcb-6db0bccc877a", + "metadata": { + "tags": [] + }, + "source": [ + "### Calculate NDVI With OTB in python" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "d83fde75-d936-4372-b7c6-412c9b2d5bf7", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Warning 1: Invalid value for NUM_THREADS: \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing /work/scratch/data/romaint/output_greenit/img_ndvi_otb_py.tif...: 100% [**************************************************] (2s)\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import otbApplication as otb\n", + "\n", + "#Compute NDVI with OTB in python\n", + "out_ndvi_otb_py=f\"{output_dir}/img_ndvi_otb_py.tif\"\n", + "app_ndvi_otb = otb.Registry.CreateApplication(\"BandMath\")\n", + "app_ndvi_otb.SetParameterStringList(\"il\",[s2_b4,s2_b8])\n", + "app_ndvi_otb.SetParameterString(\"exp\",\"(im2b1-im1b1)/(im2b1+im1b1)\")\n", + "app_ndvi_otb.SetParameterString(\"out\",out_ndvi_otb_py)\n", + "app_ndvi_otb.SetParameterInt(\"ram\",2048)\n", + "app_ndvi_otb.ExecuteAndWriteOutput()" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "d3a17da8-fa8f-4019-938f-de59830cf3f9", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Export varialbles to use them when calling otbcli in bash\n", + "os.environ['OTB_INPUT_DIR'] = input_dir\n", + "os.environ['OTB_OUTPUT_DIR'] = output_dir" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "2c7e73eb-836c-4b53-80dd-dc7d4418bc4f", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "bash: load: No such file or directory\n", + "Warning 1: Invalid value for NUM_THREADS: \n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing /work/scratch/data/romaint/output_greenit/img_ndvi_otb_cpp.tif...: 100% [**************************************************] (2s)\n", + "CPU times: user 220 ms, sys: 76.4 ms, total: 296 ms\n", + "Wall time: 3.87 s\n" + ] + } + ], + "source": [ + "%%time\n", + "%%bash\n", + "\n", + "module load otb\n", + "otbcli_BandMath -il \"${OTB_INPUT_DIR}/SENTINEL2B_20240822-105857-973_L2A_T31TCJ_C_V3-1/SENTINEL2B_20240822-105857-973_L2A_T31TCJ_C_V3-1_FRE_B4.tif\" \"${OTB_INPUT_DIR}/SENTINEL2B_20240822-105857-973_L2A_T31TCJ_C_V3-1/SENTINEL2B_20240822-105857-973_L2A_T31TCJ_C_V3-1_FRE_B8.tif\" -exp \"( im2b1 - im1b1 ) / ( im2b1 + im1b1 )\" -out \"${OTB_OUTPUT_DIR}/img_ndvi_otb_cpp.tif\" " + ] + }, + { + "cell_type": "markdown", + "id": "c1b01381-b598-4e69-9389-255da7cc72cf", + "metadata": {}, + "source": [ + "## Conclusion\n", + "\n", + "The compute time with OTB for a simple NDVI computing is approximatly the same as the standard python computing (when using appropriate libraries), this is mainly due to the size of the data, the streaming functionality of OTB is not relevant as the computing takes a couple of seconds.\n", + "\n", + "Now let's see how to optimize our initial code, to determine when using dask becomes important." + ] + }, + { + "cell_type": "markdown", + "id": "e7c62deb-08a1-4a39-8c5d-ebe0d0e28386", + "metadata": {}, + "source": [ + "# Trying to optimize NDVI calculation for 450Mo of data with parallelisation methods\n", + "\n", + "Let's see if we can improve the computing time with well known python libraries, with a Sentinel 2 product (size of about 450Mo if you include the bands you need only), every file is single band" + ] + }, + { + "cell_type": "markdown", + "id": "f4fd2a83-fdc3-4401-80b8-597e72eaf957", + "metadata": {}, + "source": [ + "In order to optimize the computation, we will first see than we can use higher level libraries (Xarray) to write the same code but more maintainable\n", + "\n", + "In this section we will see that numpy vs xarray vs dask gives approximatly the same results in terms of performance : parallelisation does not make sense here because computing takes around 2s, and memory usage is low.\n", + "\n", + "Remember that dask can be activated when you give the parameter \"chunks=...\" to open_rasterio." + ] + }, + { + "cell_type": "markdown", + "id": "4230eeca-a80b-4550-b781-c676b65643b7", + "metadata": { + "tags": [] + }, + "source": [ + "### Use RioXarray to compute the NDVI, with different data types\n", + "\n", + "First without dask, allowing to use Dask afterwards." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "c1947a87-87ce-4ae9-884d-bd648e0f0b9e", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 111 ms, sys: 632 ms, total: 743 ms\n", + "Wall time: 701 ms\n" + ] + } + ], + "source": [ + "%%time\n", + "red = rxr.open_rasterio(s2_b4).load()\n", + "nir = rxr.open_rasterio(s2_b8).load()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "5ad4f268-304a-42a1-b573-fbbf7e3805bd", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 284 ms, sys: 1.32 s, total: 1.61 s\n", + "Wall time: 1.55 s\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.DataArray (band: 1, y: 10980, x: 10980)> Size: 964MB\n",
+       "array([[[0.78292795, 0.78389445, 0.79118329, ..., 0.72767704,\n",
+       "         0.75805346, 0.73753095],\n",
+       "        [0.78426454, 0.78485876, 0.79041504, ..., 0.74560217,\n",
+       "         0.76595019, 0.74025974],\n",
+       "        [0.79659478, 0.79545455, 0.7962247 , ..., 0.76639344,\n",
+       "         0.77022434, 0.75886032],\n",
+       "        ...,\n",
+       "        [0.8984375 , 0.88953488, 0.88322663, ..., 0.42064234,\n",
+       "         0.44420131, 0.43883985],\n",
+       "        [0.89358941, 0.8807947 , 0.87941567, ..., 0.42838834,\n",
+       "         0.44197844, 0.44170053],\n",
+       "        [0.89290968, 0.89435439, 0.89619565, ..., 0.4375    ,\n",
+       "         0.42103591, 0.42776382]]])\n",
+       "Coordinates:\n",
+       "  * band         (band) int64 8B 1\n",
+       "  * x            (x) float64 88kB 3e+05 3e+05 3e+05 ... 4.098e+05 4.098e+05\n",
+       "  * y            (y) float64 88kB 4.9e+06 4.9e+06 4.9e+06 ... 4.79e+06 4.79e+06\n",
+       "    spatial_ref  int64 8B 0
" + ], + "text/plain": [ + " Size: 964MB\n", + "array([[[0.78292795, 0.78389445, 0.79118329, ..., 0.72767704,\n", + " 0.75805346, 0.73753095],\n", + " [0.78426454, 0.78485876, 0.79041504, ..., 0.74560217,\n", + " 0.76595019, 0.74025974],\n", + " [0.79659478, 0.79545455, 0.7962247 , ..., 0.76639344,\n", + " 0.77022434, 0.75886032],\n", + " ...,\n", + " [0.8984375 , 0.88953488, 0.88322663, ..., 0.42064234,\n", + " 0.44420131, 0.43883985],\n", + " [0.89358941, 0.8807947 , 0.87941567, ..., 0.42838834,\n", + " 0.44197844, 0.44170053],\n", + " [0.89290968, 0.89435439, 0.89619565, ..., 0.4375 ,\n", + " 0.42103591, 0.42776382]]])\n", + "Coordinates:\n", + " * band (band) int64 8B 1\n", + " * x (x) float64 88kB 3e+05 3e+05 3e+05 ... 4.098e+05 4.098e+05\n", + " * y (y) float64 88kB 4.9e+06 4.9e+06 4.9e+06 ... 4.79e+06 4.79e+06\n", + " spatial_ref int64 8B 0" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%time\n", + "ndvi = (nir - red) / (nir + red)\n", + "ndvi" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "af16f517-1096-43ac-9fdd-aa78da0f59c3", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 504 ms, sys: 3.59 s, total: 4.09 s\n", + "Wall time: 3.95 s\n" + ] + } + ], + "source": [ + "%%time\n", + "ndvi.rio.to_raster(f\"{tmp_dir}/rxr.tif\")" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "dd98e879-be45-4b09-a066-3f9b98ae1bf5", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 406 ms, sys: 3.26 s, total: 3.66 s\n", + "Wall time: 3.54 s\n" + ] + } + ], + "source": [ + "%%time\n", + "ndvi.astype(np.float32).rio.to_raster(f\"{tmp_dir}/rxr.tif\")" + ] + }, + { + "cell_type": "markdown", + "id": "d228aa26-96b1-482a-a289-55e2c6a0b366", + "metadata": {}, + "source": [ + "### Use Dask\n", + "\n", + "Explain a bit how it works, chunkin, threading, distributed, etc.." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "c8771bca-7266-4264-9a5c-38271513e246", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 58.9 ms, sys: 13.1 ms, total: 72 ms\n", + "Wall time: 64.8 ms\n" + ] + } + ], + "source": [ + "%%time\n", + "red = rxr.open_rasterio(s2_b4, chunks=(-1,4096,4096))\n", + "nir = rxr.open_rasterio(s2_b8, chunks=(-1,4096,4096))" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "9639e292-715c-451d-a1bd-28e22dae09cb", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 6.48 ms, sys: 2.67 ms, total: 9.15 ms\n", + "Wall time: 8.58 ms\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.DataArray (band: 1, y: 10980, x: 10980)> Size: 964MB\n",
+       "dask.array<truediv, shape=(1, 10980, 10980), dtype=float64, chunksize=(1, 4096, 4096), chunktype=numpy.ndarray>\n",
+       "Coordinates:\n",
+       "  * band         (band) int64 8B 1\n",
+       "  * x            (x) float64 88kB 3e+05 3e+05 3e+05 ... 4.098e+05 4.098e+05\n",
+       "  * y            (y) float64 88kB 4.9e+06 4.9e+06 4.9e+06 ... 4.79e+06 4.79e+06\n",
+       "    spatial_ref  int64 8B 0
" + ], + "text/plain": [ + " Size: 964MB\n", + "dask.array\n", + "Coordinates:\n", + " * band (band) int64 8B 1\n", + " * x (x) float64 88kB 3e+05 3e+05 3e+05 ... 4.098e+05 4.098e+05\n", + " * y (y) float64 88kB 4.9e+06 4.9e+06 4.9e+06 ... 4.79e+06 4.79e+06\n", + " spatial_ref int64 8B 0" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%time\n", + "ndvi = (nir - red) / (nir + red)\n", + "ndvi" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "719ece90-962f-4a92-878f-55190c03cf7e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1.02 s, sys: 9.1 s, total: 10.1 s\n", + "Wall time: 13.3 s\n" + ] + } + ], + "source": [ + "%%time\n", + "ndvi.rio.to_raster(f\"{tmp_dir}/rxr_dask.tif\")" + ] + }, + { + "cell_type": "markdown", + "id": "c9229d23-c553-4c30-8ae0-b21cee07879e", + "metadata": {}, + "source": [ + "## Conclusion for a Sentinel 2 product with two single band files (450Mo of data)\n", + "\n", + "* Using **Parallelisaiton Dask on an amount of data that does not constrain your RAM is counter productive**.\n", + "* RioXarray provides another interface that you can use with or without Dask. It might be much higher level and provide code easier to read.\n", + "\n", + "**The use of parallelisation methods becomes necessary when you are RAM and/or CPU constrained which means the product size is a couple of Gigabytes** \n", + "\n", + "the RAM parameter is very important to take into account when developing your image processing chain, dasks memory management is decribed here :\n", + "https://docs.dask.org/en/stable/shared.html?highlight=memory\n" + ] + }, + { + "cell_type": "markdown", + "id": "34beb54a-84da-4051-a712-17b0c66e1eff", + "metadata": {}, + "source": [ + "**In the next use case, we will use a bigger product, to see the importance of parallelisation and data size reduction in that case. We will now use a PLEIADES image which is a multi band product of 13Go.**" + ] + }, + { + "cell_type": "markdown", + "id": "56e25516-3d90-4ee6-8c4b-085b94d3d096", + "metadata": { + "tags": [] + }, + "source": [ + "# Use case 2 : I have to use bigger products which average size is > 10Go\n", + "\n", + "In this example we will use a PLEIADES product (which original size is 13Go) which is composed of 41663x39844 pixels\n", + "\n", + "This is the typical use case where dask or rioxarray with parallel read and write support is necessary to speedup your processing. Let's see what are the recommended parameters to optimize your processing with big data" + ] + }, + { + "cell_type": "markdown", + "id": "807ff285-435b-4d82-aa67-bf9c32fd0f43", + "metadata": {}, + "source": [ + "## The importance of reducing the size of your data\n", + "\n", + "The most important thing to take into account when developing your image processing chain is the RAM and CPU.\n", + "\n", + "**The size of the data has a big impact on the RAM because the products can be loaded by chunks or even entirely in memory**\n", + "\n", + "Let's see how the size of your data can have an impact on your compute time" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "6e31fa02-b790-4795-a056-aa727e33e6ad", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'driver': 'GTiff', 'dtype': 'uint16', 'nodata': 0.0, 'width': 39844, 'height': 41663, 'count': 4, 'crs': None, 'transform': Affine(1.0, 0.0, 0.0,\n", + " 0.0, 1.0, 0.0), 'blockxsize': 39844, 'blockysize': 1, 'tiled': False, 'interleave': 'pixel'}" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "## Read the initial 13Go raster\n", + "\n", + "raster = rasterio.open(phr_product, 'r')\n", + "raster.profile" + ] + }, + { + "cell_type": "markdown", + "id": "7a95208c-4974-4c85-a09d-e7cd99fd09cd", + "metadata": {}, + "source": [ + "### Simple LZW Compression with RasterIO\n", + "\n", + "The LZW compression is lossless and standard in image processing, all libraries like rasterio, rioxarray etc supports this compression. It permits to **save a lot of disk space**, but we will see that this compression type **does not improve compute time**.\n", + "\n", + "An In-depth guide to have a better understanding of how compression works on TIFF images is available here :\n", + "\n", + "https://kokoalberti.com/articles/geotiff-compression-optimization-guide/\n", + "\n", + "**Warning: The file is 13Go you need at least 32Go memory on your session to avoid crashes of the kernel**" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "a09ab446-8e31-4c08-bc9b-788854c6fb23", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 3.08 s, sys: 13 s, total: 16.1 s\n", + "Wall time: 15.5 s\n" + ] + } + ], + "source": [ + "%%time\n", + "in_mem_raster = raster.read()" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "69b8bd27-926e-4373-86d1-4dafe7fdbeed", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.10/dist-packages/rasterio/__init__.py:366: NotGeoreferencedWarning: The given matrix is equal to Affine.identity or its flipped counterpart. GDAL may ignore this matrix and save no geotransform without raising an error. This behavior is somewhat driver-specific.\n", + " dataset = writer(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 2min 25s, sys: 9.5 s, total: 2min 35s\n", + "Wall time: 2min 29s\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "# Register GDAL format drivers and configuration options with a\n", + "# context manager.\n", + "with rasterio.Env():\n", + "\n", + " # Write an array as a raster band to a new 8-bit file. For\n", + " # the new file's profile, we start with the profile of the source\n", + " profile = raster.profile\n", + " \n", + " # specify LZW compression.\n", + " # BIGTIFF permits to output rasters > 4Go\n", + " profile.update(compress='lzw', BIGTIFF='YES')\n", + "\n", + " with rasterio.open(phr_product_lzw, 'w', **profile) as dst:\n", + " dst.write(in_mem_raster)" + ] + }, + { + "cell_type": "markdown", + "id": "9f77319c-80a1-4060-92ff-32a5040f834f", + "metadata": {}, + "source": [ + "### Create a CoG without overview\n", + "\n", + "CoG (Cloud Optimized Tiff) is an lzw compressed **tiled** product which optimizes the computing by allowing calculations by tile (allowing parallelisation), the **compute performance is greatly improved**, **but it does not improve the write speed**\n" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "906973ba-32f1-473c-93dd-302296177950", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 2min 30s, sys: 9.33 s, total: 2min 40s\n", + "Wall time: 2min 33s\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "with rasterio.Env():\n", + " profile = raster.profile\n", + " profile.update(tiled=True, compress='lzw', blockxsize=1024, blockysize=1024, BIGTIFF='YES')\n", + " with rasterio.open(phr_product_cog, 'w', **profile) as dst:\n", + " dst.write(in_mem_raster)" + ] + }, + { + "cell_type": "markdown", + "id": "be984817-d0df-4987-812f-738df5d6c261", + "metadata": {}, + "source": [ + "### Create Cog with overview\n", + "\n", + "A library exists to manipulate CoG with overviews: https://github.com/cogeotiff/rio-cogeo/\n", + "\n", + "TODO parler du driver CoG dans rasterio/GDAL" + ] + }, + { + "cell_type": "markdown", + "id": "a72ca70d-0b0f-49e4-9e7e-f291d1e8cd96", + "metadata": {}, + "source": [ + "### Size and compute time gain after compression\n", + "\n", + "In this section we compare the size on disk of the original product vs the compressed ones " + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "32241de3-aa3f-4fb5-84f6-0ebc977ed281", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "13G\t/work/CAMPUS/DATA/PLUTO/greenIT/IMG_PHR1A_PMS_202304151100243_SEN_6967638101-1_R1C1_wnodata.tif\n" + ] + } + ], + "source": [ + "# Size of the original product\n", + "!du -sh {phr_product}" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "1071ba31-2e9b-4da5-9d94-9e6ea9a5b1db", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5.4G\t/tmp/slurm-37316783/phr_cog.tif\n", + "5.4G\t/tmp/slurm-37316783/phr_lzw.tif\n" + ] + } + ], + "source": [ + "# Size of the compressed products\n", + "!du -sh {tmp_dir}/phr_*.tif" + ] + }, + { + "cell_type": "markdown", + "id": "3f2d0345-ee4b-4341-8444-7bd9f4fdbf48", + "metadata": { + "tags": [] + }, + "source": [ + "The CoG and Lzw files are weighing ~45% of the original product size, the difference between lzw and cog is negligeable, but the CoG is **tiled** this is very important for the parallelisation efficiency" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "5d755a06-c792-44d5-8926-af6188b797c4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#Clean unused variables\n", + "del in_mem_raster" + ] + }, + { + "cell_type": "markdown", + "id": "58483551-a29e-4435-bfe5-8737bf9ba7bb", + "metadata": {}, + "source": [ + "### Compute time with RIOXarray and compressed files" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "79191ff3-82b9-44c7-957d-20208d238cf3", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 40.9 ms, sys: 571 ms, total: 612 ms\n", + "Wall time: 643 ms\n" + ] + } + ], + "source": [ + "%%time\n", + "# Compute NDVI for the original product\n", + "reading_chunks = (-1,2048,2048)\n", + "data_array = rxr.open_rasterio(phr_product, chunks=reading_chunks, lock=False)\n", + "ndvi_array = (data_array[3] - data_array[0]) / (data_array[3] + data_array[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "a481e316-74ca-48a7-902f-9a1d8095e10d", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.10/dist-packages/rasterio/__init__.py:366: NotGeoreferencedWarning: The given matrix is equal to Affine.identity or its flipped counterpart. GDAL may ignore this matrix and save no geotransform without raising an error. This behavior is somewhat driver-specific.\n", + " dataset = writer(\n", + "/usr/local/lib/python3.10/dist-packages/dask/_task_spec.py:745: RuntimeWarning: invalid value encountered in divide\n", + " return self.func(*new_argspec)\n", + "/usr/local/lib/python3.10/dist-packages/dask/_task_spec.py:745: RuntimeWarning: invalid value encountered in divide\n", + " return self.func(*new_argspec)\n", + "/usr/local/lib/python3.10/dist-packages/dask/_task_spec.py:745: RuntimeWarning: invalid value encountered in divide\n", + " return self.func(*new_argspec)\n", + "/usr/local/lib/python3.10/dist-packages/dask/_task_spec.py:745: RuntimeWarning: invalid value encountered in divide\n", + " return self.func(*new_argspec)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 17.6 s, sys: 1min 54s, total: 2min 12s\n", + "Wall time: 2min 48s\n" + ] + } + ], + "source": [ + "%%time\n", + "output_file = Path(f\"{output_dir}/ndvi_orig.tif\")\n", + "ndvi_array.rio.to_raster(output_file)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "533fc7e1-9519-46aa-8020-5b3885a8bc57", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 43.6 ms, sys: 5.96 ms, total: 49.6 ms\n", + "Wall time: 44.1 ms\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.DataArray (y: 41663, x: 39844)> Size: 13GB\n",
+       "dask.array<truediv, shape=(41663, 39844), dtype=float64, chunksize=(2048, 2048), chunktype=numpy.ndarray>\n",
+       "Coordinates:\n",
+       "  * x            (x) float64 319kB 0.5 1.5 2.5 ... 3.984e+04 3.984e+04 3.984e+04\n",
+       "  * y            (y) float64 333kB 0.5 1.5 2.5 ... 4.166e+04 4.166e+04 4.166e+04\n",
+       "    spatial_ref  int64 8B 0
" + ], + "text/plain": [ + " Size: 13GB\n", + "dask.array\n", + "Coordinates:\n", + " * x (x) float64 319kB 0.5 1.5 2.5 ... 3.984e+04 3.984e+04 3.984e+04\n", + " * y (y) float64 333kB 0.5 1.5 2.5 ... 4.166e+04 4.166e+04 4.166e+04\n", + " spatial_ref int64 8B 0" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%time\n", + "\n", + "# Compute NDVI for the LZW compressed file\n", + "reading_chunks = (-1,2048,2048)\n", + "data_array_lzw = rxr.open_rasterio(phr_product_lzw, chunks=reading_chunks, lock=False)\n", + "ndvi_array = (data_array_lzw[3] - data_array_lzw[0]) / (data_array_lzw[3] + data_array_lzw[0] + 10e-6)\n", + "ndvi_array" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "7fd05234-5cd0-4e4f-b8e3-ea9ec3125562", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "ename": "ImportError", + "evalue": "The zarr package is required for working with Zarr stores but could not be imported. Please install it with your package manager (e.g. conda or pip).", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/xarray/core/utils.py:1243\u001b[0m, in \u001b[0;36mattempt_import\u001b[0;34m(module)\u001b[0m\n\u001b[1;32m 1242\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m-> 1243\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mimportlib\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mimport_module\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodule\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1244\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mImportError\u001b[39;00m, \u001b[38;5;167;01mModuleNotFoundError\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n", + "File \u001b[0;32m/usr/lib/python3.10/importlib/__init__.py:126\u001b[0m, in \u001b[0;36mimport_module\u001b[0;34m(name, package)\u001b[0m\n\u001b[1;32m 125\u001b[0m level \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[0;32m--> 126\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_bootstrap\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_gcd_import\u001b[49m\u001b[43m(\u001b[49m\u001b[43mname\u001b[49m\u001b[43m[\u001b[49m\u001b[43mlevel\u001b[49m\u001b[43m:\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpackage\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlevel\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m:1050\u001b[0m, in \u001b[0;36m_gcd_import\u001b[0;34m(name, package, level)\u001b[0m\n", + "File \u001b[0;32m:1027\u001b[0m, in \u001b[0;36m_find_and_load\u001b[0;34m(name, import_)\u001b[0m\n", + "File \u001b[0;32m:1004\u001b[0m, in \u001b[0;36m_find_and_load_unlocked\u001b[0;34m(name, import_)\u001b[0m\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'zarr'", + "\nThe above exception was the direct cause of the following exception:\n", + "\u001b[0;31mImportError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m:2\u001b[0m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/xarray/core/dataarray.py:4435\u001b[0m, in \u001b[0;36mDataArray.to_zarr\u001b[0;34m(self, store, chunk_store, mode, synchronizer, group, encoding, compute, consolidated, append_dim, region, safe_chunks, storage_options, zarr_version)\u001b[0m\n\u001b[1;32m 4431\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 4432\u001b[0m \u001b[38;5;66;03m# No problems with the name - so we're fine!\u001b[39;00m\n\u001b[1;32m 4433\u001b[0m dataset \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mto_dataset()\n\u001b[0;32m-> 4435\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mto_zarr\u001b[49m\u001b[43m(\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# type: ignore[call-overload,misc]\u001b[39;49;00m\n\u001b[1;32m 4436\u001b[0m \u001b[43m \u001b[49m\u001b[43mdataset\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4437\u001b[0m \u001b[43m \u001b[49m\u001b[43mstore\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstore\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4438\u001b[0m \u001b[43m \u001b[49m\u001b[43mchunk_store\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mchunk_store\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4439\u001b[0m \u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4440\u001b[0m \u001b[43m \u001b[49m\u001b[43msynchronizer\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msynchronizer\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4441\u001b[0m \u001b[43m \u001b[49m\u001b[43mgroup\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgroup\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4442\u001b[0m \u001b[43m \u001b[49m\u001b[43mencoding\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mencoding\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4443\u001b[0m \u001b[43m \u001b[49m\u001b[43mcompute\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcompute\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4444\u001b[0m \u001b[43m \u001b[49m\u001b[43mconsolidated\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mconsolidated\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4445\u001b[0m \u001b[43m \u001b[49m\u001b[43mappend_dim\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mappend_dim\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4446\u001b[0m \u001b[43m \u001b[49m\u001b[43mregion\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mregion\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4447\u001b[0m \u001b[43m \u001b[49m\u001b[43msafe_chunks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msafe_chunks\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4448\u001b[0m \u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstorage_options\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4449\u001b[0m \u001b[43m \u001b[49m\u001b[43mzarr_version\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mzarr_version\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4450\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/xarray/backends/api.py:2162\u001b[0m, in \u001b[0;36mto_zarr\u001b[0;34m(dataset, store, chunk_store, mode, synchronizer, group, encoding, compute, consolidated, append_dim, region, safe_chunks, storage_options, zarr_version, zarr_format, write_empty_chunks, chunkmanager_store_kwargs)\u001b[0m\n\u001b[1;32m 2159\u001b[0m already_consolidated \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 2160\u001b[0m consolidate_on_close \u001b[38;5;241m=\u001b[39m consolidated \u001b[38;5;129;01mor\u001b[39;00m consolidated \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m-> 2162\u001b[0m zstore \u001b[38;5;241m=\u001b[39m \u001b[43mbackends\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mZarrStore\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mopen_group\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 2163\u001b[0m \u001b[43m \u001b[49m\u001b[43mstore\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmapper\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 2164\u001b[0m \u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 2165\u001b[0m \u001b[43m \u001b[49m\u001b[43msynchronizer\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msynchronizer\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 2166\u001b[0m \u001b[43m \u001b[49m\u001b[43mgroup\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgroup\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 2167\u001b[0m \u001b[43m \u001b[49m\u001b[43mconsolidated\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43malready_consolidated\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 2168\u001b[0m \u001b[43m \u001b[49m\u001b[43mconsolidate_on_close\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mconsolidate_on_close\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 2169\u001b[0m \u001b[43m \u001b[49m\u001b[43mchunk_store\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mchunk_mapper\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 2170\u001b[0m \u001b[43m \u001b[49m\u001b[43mappend_dim\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mappend_dim\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 2171\u001b[0m \u001b[43m \u001b[49m\u001b[43mwrite_region\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mregion\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 2172\u001b[0m \u001b[43m \u001b[49m\u001b[43msafe_chunks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msafe_chunks\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 2173\u001b[0m \u001b[43m \u001b[49m\u001b[43mzarr_version\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mzarr_version\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 2174\u001b[0m \u001b[43m \u001b[49m\u001b[43mzarr_format\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mzarr_format\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 2175\u001b[0m \u001b[43m \u001b[49m\u001b[43mwrite_empty\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mwrite_empty_chunks\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 2176\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 2177\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 2179\u001b[0m dataset \u001b[38;5;241m=\u001b[39m zstore\u001b[38;5;241m.\u001b[39m_validate_and_autodetect_region(dataset)\n\u001b[1;32m 2180\u001b[0m zstore\u001b[38;5;241m.\u001b[39m_validate_encoding(encoding)\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/xarray/backends/zarr.py:693\u001b[0m, in \u001b[0;36mZarrStore.open_group\u001b[0;34m(cls, store, mode, synchronizer, group, consolidated, consolidate_on_close, chunk_store, storage_options, append_dim, write_region, safe_chunks, zarr_version, zarr_format, use_zarr_fill_value_as_mask, write_empty)\u001b[0m\n\u001b[1;32m 669\u001b[0m \u001b[38;5;129m@classmethod\u001b[39m\n\u001b[1;32m 670\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mopen_group\u001b[39m(\n\u001b[1;32m 671\u001b[0m \u001b[38;5;28mcls\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 686\u001b[0m write_empty: \u001b[38;5;28mbool\u001b[39m \u001b[38;5;241m|\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 687\u001b[0m ):\n\u001b[1;32m 688\u001b[0m (\n\u001b[1;32m 689\u001b[0m zarr_group,\n\u001b[1;32m 690\u001b[0m consolidate_on_close,\n\u001b[1;32m 691\u001b[0m close_store_on_close,\n\u001b[1;32m 692\u001b[0m use_zarr_fill_value_as_mask,\n\u001b[0;32m--> 693\u001b[0m ) \u001b[38;5;241m=\u001b[39m \u001b[43m_get_open_params\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 694\u001b[0m \u001b[43m \u001b[49m\u001b[43mstore\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstore\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 695\u001b[0m \u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 696\u001b[0m \u001b[43m \u001b[49m\u001b[43msynchronizer\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msynchronizer\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 697\u001b[0m \u001b[43m \u001b[49m\u001b[43mgroup\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mgroup\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 698\u001b[0m \u001b[43m \u001b[49m\u001b[43mconsolidated\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mconsolidated\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 699\u001b[0m \u001b[43m \u001b[49m\u001b[43mconsolidate_on_close\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mconsolidate_on_close\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 700\u001b[0m \u001b[43m \u001b[49m\u001b[43mchunk_store\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mchunk_store\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 701\u001b[0m \u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstorage_options\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 702\u001b[0m \u001b[43m \u001b[49m\u001b[43mzarr_version\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mzarr_version\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 703\u001b[0m \u001b[43m \u001b[49m\u001b[43muse_zarr_fill_value_as_mask\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43muse_zarr_fill_value_as_mask\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 704\u001b[0m \u001b[43m \u001b[49m\u001b[43mzarr_format\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mzarr_format\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 705\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 707\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mcls\u001b[39m(\n\u001b[1;32m 708\u001b[0m zarr_group,\n\u001b[1;32m 709\u001b[0m mode,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 716\u001b[0m use_zarr_fill_value_as_mask,\n\u001b[1;32m 717\u001b[0m )\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/xarray/backends/zarr.py:1669\u001b[0m, in \u001b[0;36m_get_open_params\u001b[0;34m(store, mode, synchronizer, group, consolidated, consolidate_on_close, chunk_store, storage_options, zarr_version, use_zarr_fill_value_as_mask, zarr_format)\u001b[0m\n\u001b[1;32m 1667\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01mzarr\u001b[39;00m\n\u001b[1;32m 1668\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 1669\u001b[0m zarr \u001b[38;5;241m=\u001b[39m \u001b[43mattempt_import\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mzarr\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1671\u001b[0m \u001b[38;5;66;03m# zarr doesn't support pathlib.Path objects yet. zarr-python#601\u001b[39;00m\n\u001b[1;32m 1672\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(store, os\u001b[38;5;241m.\u001b[39mPathLike):\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/xarray/core/utils.py:1245\u001b[0m, in \u001b[0;36mattempt_import\u001b[0;34m(module)\u001b[0m\n\u001b[1;32m 1243\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m importlib\u001b[38;5;241m.\u001b[39mimport_module(module)\n\u001b[1;32m 1244\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mImportError\u001b[39;00m, \u001b[38;5;167;01mModuleNotFoundError\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m-> 1245\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mImportError\u001b[39;00m(\n\u001b[1;32m 1246\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mThe \u001b[39m\u001b[38;5;132;01m{\u001b[39;00minstall_name\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m package is required \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mreason\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 1247\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m but could not be imported.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 1248\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m Please install it with your package manager (e.g. conda or pip).\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 1249\u001b[0m ) \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21;01me\u001b[39;00m\n", + "\u001b[0;31mImportError\u001b[0m: The zarr package is required for working with Zarr stores but could not be imported. Please install it with your package manager (e.g. conda or pip)." + ] + } + ], + "source": [ + "%%time\n", + "output_file = Path(f\"{tmp_dir}/ndvi_phr.zarr\")\n", + "ndvi_array.to_zarr(output_file)" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "74cc8f99-68d7-4723-a660-2bb3ae1df347", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.10/dist-packages/rasterio/__init__.py:366: NotGeoreferencedWarning: The given matrix is equal to Affine.identity or its flipped counterpart. GDAL may ignore this matrix and save no geotransform without raising an error. This behavior is somewhat driver-specific.\n", + " dataset = writer(\n" + ] + }, + { + "ename": "RasterioIOError", + "evalue": "Write failed. See previous exception for details.", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mCPLE_AppDefinedError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32mrasterio/_io.pyx:1833\u001b[0m, in \u001b[0;36mrasterio._io.DatasetWriterBase.write\u001b[0;34m()\u001b[0m\n", + "File \u001b[0;32mrasterio/_io.pyx:199\u001b[0m, in \u001b[0;36mrasterio._io.io_multi_band\u001b[0;34m()\u001b[0m\n", + "File \u001b[0;32mrasterio/_io.pyx:205\u001b[0m, in \u001b[0;36mrasterio._io.io_multi_band\u001b[0;34m()\u001b[0m\n", + "File \u001b[0;32mrasterio/_err.pyx:325\u001b[0m, in \u001b[0;36mrasterio._err.StackChecker.exc_wrap_int\u001b[0;34m()\u001b[0m\n", + "\u001b[0;31mCPLE_AppDefinedError\u001b[0m: TIFFAppendToStrip:Maximum TIFF file size exceeded. Use BIGTIFF=YES creation option.", + "\nThe above exception was the direct cause of the following exception:\n", + "\u001b[0;31mRasterioIOError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m:2\u001b[0m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/rioxarray/raster_array.py:1181\u001b[0m, in \u001b[0;36mRasterArray.to_raster\u001b[0;34m(self, raster_path, driver, dtype, tags, windowed, recalc_transform, lock, compute, **profile_kwargs)\u001b[0m\n\u001b[1;32m 1162\u001b[0m out_profile \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 1163\u001b[0m key: value\n\u001b[1;32m 1164\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m key, value \u001b[38;5;129;01min\u001b[39;00m out_profile\u001b[38;5;241m.\u001b[39mitems()\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1175\u001b[0m )\n\u001b[1;32m 1176\u001b[0m }\n\u001b[1;32m 1177\u001b[0m rio_nodata \u001b[38;5;241m=\u001b[39m (\n\u001b[1;32m 1178\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mencoded_nodata \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mencoded_nodata \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnodata\n\u001b[1;32m 1179\u001b[0m )\n\u001b[0;32m-> 1181\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mRasterioWriter\u001b[49m\u001b[43m(\u001b[49m\u001b[43mraster_path\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mraster_path\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mto_raster\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 1182\u001b[0m \u001b[43m \u001b[49m\u001b[43mxarray_dataarray\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_obj\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1183\u001b[0m \u001b[43m \u001b[49m\u001b[43mtags\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtags\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1184\u001b[0m \u001b[43m \u001b[49m\u001b[43mdriver\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdriver\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1185\u001b[0m \u001b[43m \u001b[49m\u001b[43mheight\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mheight\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1186\u001b[0m \u001b[43m \u001b[49m\u001b[43mwidth\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mwidth\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1187\u001b[0m \u001b[43m \u001b[49m\u001b[43mcount\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcount\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1188\u001b[0m \u001b[43m \u001b[49m\u001b[43mdtype\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdtype\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1189\u001b[0m \u001b[43m \u001b[49m\u001b[43mcrs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcrs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1190\u001b[0m \u001b[43m \u001b[49m\u001b[43mtransform\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtransform\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrecalc\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrecalc_transform\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1191\u001b[0m \u001b[43m \u001b[49m\u001b[43mgcps\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_gcps\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1192\u001b[0m \u001b[43m \u001b[49m\u001b[43mnodata\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrio_nodata\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1193\u001b[0m \u001b[43m \u001b[49m\u001b[43mwindowed\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mwindowed\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1194\u001b[0m \u001b[43m \u001b[49m\u001b[43mlock\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlock\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1195\u001b[0m \u001b[43m \u001b[49m\u001b[43mcompute\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcompute\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1196\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mout_profile\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1197\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/rioxarray/raster_writer.py:305\u001b[0m, in \u001b[0;36mRasterioWriter.to_raster\u001b[0;34m(self, xarray_dataarray, tags, windowed, lock, compute, **kwargs)\u001b[0m\n\u001b[1;32m 301\u001b[0m data \u001b[38;5;241m=\u001b[39m encode_cf_variable(out_data\u001b[38;5;241m.\u001b[39mvariable)\u001b[38;5;241m.\u001b[39mvalues\u001b[38;5;241m.\u001b[39mastype(\n\u001b[1;32m 302\u001b[0m numpy_dtype\n\u001b[1;32m 303\u001b[0m )\n\u001b[1;32m 304\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m data\u001b[38;5;241m.\u001b[39mndim \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m2\u001b[39m:\n\u001b[0;32m--> 305\u001b[0m \u001b[43mrds\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mwrite\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mwindow\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mwindow\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 306\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 307\u001b[0m rds\u001b[38;5;241m.\u001b[39mwrite(data, window\u001b[38;5;241m=\u001b[39mwindow)\n", + "File \u001b[0;32mrasterio/_io.pyx:1835\u001b[0m, in \u001b[0;36mrasterio._io.DatasetWriterBase.write\u001b[0;34m()\u001b[0m\n", + "\u001b[0;31mRasterioIOError\u001b[0m: Write failed. See previous exception for details." + ] + } + ], + "source": [ + "%%time\n", + "output_file = Path(f\"{tmp_dir}/ndvi_lzw.tif\")\n", + "ndvi_array.rio.to_raster(output_file, compress=\"lzw\", tiled=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "8e7a9fdb-3844-432a-bc43-fbcc2c5169cd", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/usr/local/lib/python3.10/dist-packages/rasterio/__init__.py:366: NotGeoreferencedWarning: The given matrix is equal to Affine.identity or its flipped counterpart. GDAL may ignore this matrix and save no geotransform without raising an error. This behavior is somewhat driver-specific.\n", + " dataset = writer(\n" + ] + }, + { + "ename": "CPLE_AppDefinedError", + "evalue": "ndvi_cog.tif: TIFFReadDirectory:Failed to read directory at offset 33014", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mCPLE_AppDefinedError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[37], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mget_ipython\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun_cell_magic\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mtimeit\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m# Compute NDVI for the Cog compressed file\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43mreading_chunks = (-1,2048,2048)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43mdata_array_cog = rxr.open_rasterio(phr_product_cog, chunks=reading_chunks, lock=False)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43mndvi_array = (data_array_cog[3] - data_array_cog[0]) / (data_array_cog[3] + data_array_cog[0])\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43moutput_file = Path(f\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;132;43;01m{output_dir}\u001b[39;49;00m\u001b[38;5;124;43m/ndvi_cog.tif\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43mndvi_array.rio.to_raster(output_file, driver=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mCoG\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m)\u001b[39;49m\u001b[38;5;130;43;01m\\n\u001b[39;49;00m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/IPython/core/interactiveshell.py:2543\u001b[0m, in \u001b[0;36mInteractiveShell.run_cell_magic\u001b[0;34m(self, magic_name, line, cell)\u001b[0m\n\u001b[1;32m 2541\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mbuiltin_trap:\n\u001b[1;32m 2542\u001b[0m args \u001b[38;5;241m=\u001b[39m (magic_arg_s, cell)\n\u001b[0;32m-> 2543\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 2545\u001b[0m \u001b[38;5;66;03m# The code below prevents the output from being displayed\u001b[39;00m\n\u001b[1;32m 2546\u001b[0m \u001b[38;5;66;03m# when using magics with decorator @output_can_be_silenced\u001b[39;00m\n\u001b[1;32m 2547\u001b[0m \u001b[38;5;66;03m# when the last Python token in the expression is a ';'.\u001b[39;00m\n\u001b[1;32m 2548\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mgetattr\u001b[39m(fn, magic\u001b[38;5;241m.\u001b[39mMAGIC_OUTPUT_CAN_BE_SILENCED, \u001b[38;5;28;01mFalse\u001b[39;00m):\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/IPython/core/magics/execution.py:1209\u001b[0m, in \u001b[0;36mExecutionMagics.timeit\u001b[0;34m(self, line, cell, local_ns)\u001b[0m\n\u001b[1;32m 1207\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m index \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m10\u001b[39m):\n\u001b[1;32m 1208\u001b[0m number \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m10\u001b[39m \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m index\n\u001b[0;32m-> 1209\u001b[0m time_number \u001b[38;5;241m=\u001b[39m \u001b[43mtimer\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtimeit\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnumber\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1210\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m time_number \u001b[38;5;241m>\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0.2\u001b[39m:\n\u001b[1;32m 1211\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/IPython/core/magics/execution.py:173\u001b[0m, in \u001b[0;36mTimer.timeit\u001b[0;34m(self, number)\u001b[0m\n\u001b[1;32m 171\u001b[0m gc\u001b[38;5;241m.\u001b[39mdisable()\n\u001b[1;32m 172\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 173\u001b[0m timing \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minner\u001b[49m\u001b[43m(\u001b[49m\u001b[43mit\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtimer\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 174\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 175\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m gcold:\n", + "File \u001b[0;32m:6\u001b[0m, in \u001b[0;36minner\u001b[0;34m(_it, _timer)\u001b[0m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/rioxarray/raster_array.py:1181\u001b[0m, in \u001b[0;36mRasterArray.to_raster\u001b[0;34m(self, raster_path, driver, dtype, tags, windowed, recalc_transform, lock, compute, **profile_kwargs)\u001b[0m\n\u001b[1;32m 1162\u001b[0m out_profile \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 1163\u001b[0m key: value\n\u001b[1;32m 1164\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m key, value \u001b[38;5;129;01min\u001b[39;00m out_profile\u001b[38;5;241m.\u001b[39mitems()\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1175\u001b[0m )\n\u001b[1;32m 1176\u001b[0m }\n\u001b[1;32m 1177\u001b[0m rio_nodata \u001b[38;5;241m=\u001b[39m (\n\u001b[1;32m 1178\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mencoded_nodata \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mencoded_nodata \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnodata\n\u001b[1;32m 1179\u001b[0m )\n\u001b[0;32m-> 1181\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mRasterioWriter\u001b[49m\u001b[43m(\u001b[49m\u001b[43mraster_path\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mraster_path\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mto_raster\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 1182\u001b[0m \u001b[43m \u001b[49m\u001b[43mxarray_dataarray\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_obj\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1183\u001b[0m \u001b[43m \u001b[49m\u001b[43mtags\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtags\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1184\u001b[0m \u001b[43m \u001b[49m\u001b[43mdriver\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdriver\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1185\u001b[0m \u001b[43m \u001b[49m\u001b[43mheight\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mheight\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1186\u001b[0m \u001b[43m \u001b[49m\u001b[43mwidth\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mwidth\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1187\u001b[0m \u001b[43m \u001b[49m\u001b[43mcount\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mint\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcount\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1188\u001b[0m \u001b[43m \u001b[49m\u001b[43mdtype\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdtype\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1189\u001b[0m \u001b[43m \u001b[49m\u001b[43mcrs\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcrs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1190\u001b[0m \u001b[43m \u001b[49m\u001b[43mtransform\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtransform\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrecalc\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrecalc_transform\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1191\u001b[0m \u001b[43m \u001b[49m\u001b[43mgcps\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_gcps\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1192\u001b[0m \u001b[43m \u001b[49m\u001b[43mnodata\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrio_nodata\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1193\u001b[0m \u001b[43m \u001b[49m\u001b[43mwindowed\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mwindowed\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1194\u001b[0m \u001b[43m \u001b[49m\u001b[43mlock\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlock\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1195\u001b[0m \u001b[43m \u001b[49m\u001b[43mcompute\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcompute\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1196\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mout_profile\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1197\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/rioxarray/raster_writer.py:286\u001b[0m, in \u001b[0;36mRasterioWriter.to_raster\u001b[0;34m(self, xarray_dataarray, tags, windowed, lock, compute, **kwargs)\u001b[0m\n\u001b[1;32m 278\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnodata\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 279\u001b[0m \u001b[38;5;66;03m# Ensure dtype of output data matches the expected dtype.\u001b[39;00m\n\u001b[1;32m 280\u001b[0m \u001b[38;5;66;03m# This check is added here as the dtype of the data is\u001b[39;00m\n\u001b[1;32m 281\u001b[0m \u001b[38;5;66;03m# converted right before writing.\u001b[39;00m\n\u001b[1;32m 282\u001b[0m kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnodata\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m _ensure_nodata_dtype(\n\u001b[1;32m 283\u001b[0m original_nodata\u001b[38;5;241m=\u001b[39mkwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnodata\u001b[39m\u001b[38;5;124m\"\u001b[39m], new_dtype\u001b[38;5;241m=\u001b[39mnumpy_dtype\n\u001b[1;32m 284\u001b[0m )\n\u001b[0;32m--> 286\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m rasterio\u001b[38;5;241m.\u001b[39mopen(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mraster_path, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mw\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs) \u001b[38;5;28;01mas\u001b[39;00m rds:\n\u001b[1;32m 287\u001b[0m _write_metatata_to_raster(\n\u001b[1;32m 288\u001b[0m raster_handle\u001b[38;5;241m=\u001b[39mrds, xarray_dataset\u001b[38;5;241m=\u001b[39mxarray_dataarray, tags\u001b[38;5;241m=\u001b[39mtags\n\u001b[1;32m 289\u001b[0m )\n\u001b[1;32m 290\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m (lock \u001b[38;5;129;01mand\u001b[39;00m is_dask_collection(xarray_dataarray\u001b[38;5;241m.\u001b[39mdata)):\n\u001b[1;32m 291\u001b[0m \u001b[38;5;66;03m# write data to raster immmediately if not dask array\u001b[39;00m\n", + "File \u001b[0;32mrasterio/_base.pyx:450\u001b[0m, in \u001b[0;36mrasterio._base.DatasetBase.__exit__\u001b[0;34m()\u001b[0m\n", + "File \u001b[0;32mrasterio/_base.pyx:439\u001b[0m, in \u001b[0;36mrasterio._base.DatasetBase.close\u001b[0;34m()\u001b[0m\n", + "File \u001b[0;32mrasterio/_io.pyx:2475\u001b[0m, in \u001b[0;36mrasterio._io.BufferedDatasetWriterBase.stop\u001b[0;34m()\u001b[0m\n", + "File \u001b[0;32mrasterio/_io.pyx:306\u001b[0m, in \u001b[0;36mrasterio._io._delete_dataset_if_exists\u001b[0;34m()\u001b[0m\n", + "File \u001b[0;32mrasterio/_io.pyx:307\u001b[0m, in \u001b[0;36mrasterio._io._delete_dataset_if_exists\u001b[0;34m()\u001b[0m\n", + "File \u001b[0;32mrasterio/_base.pyx:221\u001b[0m, in \u001b[0;36mrasterio._base.open_dataset\u001b[0;34m()\u001b[0m\n", + "File \u001b[0;32mrasterio/_err.pyx:359\u001b[0m, in \u001b[0;36mrasterio._err.exc_wrap_pointer\u001b[0;34m()\u001b[0m\n", + "\u001b[0;31mCPLE_AppDefinedError\u001b[0m: ndvi_cog.tif: TIFFReadDirectory:Failed to read directory at offset 33014" + ] + } + ], + "source": [ + "%%timeit\n", + "\n", + "# Compute NDVI for the Cog compressed file\n", + "reading_chunks = (-1,2048,2048)\n", + "data_array_cog = rxr.open_rasterio(phr_product_cog, chunks=reading_chunks, lock=False)\n", + "ndvi_array = (data_array_cog[3] - data_array_cog[0]) / (data_array_cog[3] + data_array_cog[0])\n", + "output_file = Path(f\"{output_dir}/ndvi_cog.tif\")\n", + "ndvi_array.rio.to_raster(output_file, driver=\"CoG\")" + ] + }, + { + "cell_type": "markdown", + "id": "64375b17-a757-4024-abf6-c9460ccec773", + "metadata": {}, + "source": [ + "### Optimize Compression with data typing\n", + "\n", + "\n", + "Here we write by default in float64 which is overkill for a simple NDVI. Let's see how we can change the data type when writing with to_raster\n", + "\n", + "By default dask is using multi-threaded mode" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c86e5db1-3892-4e3d-833d-076e2fd86382", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%%time\n", + "## Explain : par défaut, on est en multi threadé avec Dask en backend. Comprendre aussi pourquoi l'écriture est plus lente. Tester un autre format ? Là aussi étudier compression.\n", + "\n", + "ndvi.rio.to_raster(f\"{tmp_dir}/rxr.tif\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "40e85d11-a501-4586-b6c3-6a91d316dd7b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%%time\n", + "ndvi.rio.to_raster(f\"{tmp_dir}/rxr.tif\", tiled=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "da042348-acd5-4ea2-ab64-6163bcec1d26", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "!rm -rf {tmp_dir}/ndvi_s2.zarr" + ] + }, + { + "cell_type": "markdown", + "id": "e7e7dd0a-8dfa-4b99-a113-0495eefa322e", + "metadata": { + "tags": [] + }, + "source": [ + "Zarr format has been made with compression in mind, it can handle Tiff, netcdf ... write speed is highly improved" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a8a522f5-8906-4ba5-9279-18a2f5f0919a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%%time\n", + "\n", + "ndvi.to_zarr(f\"{tmp_dir}/ndvi_s2.zarr\")" + ] + }, + { + "cell_type": "markdown", + "id": "9f5a46ed-d9c0-47f4-baf4-b7039b45ba59", + "metadata": { + "tags": [] + }, + "source": [ + "### Changing the data type\n", + "\n", + "In this section we will compare TIF vs ZARR compressed format writing, we will also change the data type for NDVI calculation as float can be overkill.\n", + "\n", + "Remember that using Int16 instead of float will lose precision, but in simple cases as NDVI computing this is not a problem." + ] + }, + { + "cell_type": "markdown", + "id": "db54e575-e844-4be7-bd8f-f998c22d47c0", + "metadata": { + "tags": [] + }, + "source": [ + "#### Different data types with ZARR format" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b40a4b80-7e86-4261-9503-58d049ed75b8", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%%time\n", + "ndvi.astype(np.float32).to_zarr(f\"{tmp_dir}/ndvi_s2.zarr\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2953fbe7-2923-4d24-bda0-bb42a168772f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%%time\n", + "(ndvi*1000).astype(np.int16).to_zarr(f\"{tmp_dir}/ndvi_s2.zarr\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b54c57c7-e864-4817-8117-9b6e82656d19", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "!rm -rf {tmp_dir}/ndvi_s2.zarr" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dea91249-a293-4183-8557-2a3f9511b047", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%%time\n", + "ndvi.to_zarr(f\"{tmp_dir}/ndvi_s2.zarr\")" + ] + }, + { + "cell_type": "markdown", + "id": "54e0fdd8-f96d-4418-ba59-44402517de30", + "metadata": { + "tags": [] + }, + "source": [ + "#### Different types with compressed TIF" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5b6d40c0-e118-453f-a880-16c3d7f130d2", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%%time\n", + "ndvi.rio.to_raster(f\"{tmp_dir}/rxr.tif\", tiled=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4d56a18d-accd-4ddd-bec5-6d02e1aa06ad", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%%time\n", + "ndvi.astype(np.float32).rio.to_raster(f\"{tmp_dir}/rxr_deflate_float.tif\", compress=\"deflate\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "40da2177-a83a-445b-a617-776eb9c52e3b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%%time\n", + "(ndvi*1000).astype(np.int16).rio.to_raster(f\"{tmp_dir}/rxr_deflate_int16.tif\", compress=\"deflate\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "414f7a90-88fe-4dab-819f-cede96207f91", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%%time\n", + "(ndvi*1000).astype(np.int16).rio.to_raster(f\"{tmp_dir}/rxr_int16.tif\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f2a28a6b-331a-4ac1-8e70-c3ef3a752d29", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%%time\n", + "(ndvi*1000).astype(np.int16).rio.to_raster(f\"{tmp_dir}/rxr_cog.tif\", driver=\"CoG\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dbf6cbe7-cce4-4c57-8f67-7184f66af0a4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Display the size of each file and sort this list\n", + "!du -k --max-depth=1 {tmp_dir}/* | sort -nr | cut -f2 | xargs -d '\\n' du -sh" + ] + }, + { + "cell_type": "markdown", + "id": "d695aecb-9e65-4111-a7c4-845cb5c6914e", + "metadata": {}, + "source": [ + "## Conclusion\n", + "\n", + "* The float format can **take up to 3x the size of the same compressed files containing int16**, if you don't need the float precision don't use this to save disk space!\n", + "\n", + "* Depending on the needed precision for your output product, you can **improve the efficiency of the compression and the compute time** by modifying the written data type.\n", + "\n", + "* Using LZW or CoG does reduce the size of your data on disk and reduce the computing time, but **beware than in memory the product size will still be the original product's size**\n", + "\n", + "
\n", + " \n", + "* Using CoG is **way more efficient in computational time, you can gain up to 200%** with a simple NDVI indice computing. See the next chapter on how to optimize the disk write to gain more time.\n", + " \n", + "
\n" + ] + }, + { + "cell_type": "markdown", + "id": "d3ab5833-1672-478a-8b26-0ed2bc4d6ee1", + "metadata": {}, + "source": [ + "## Using dask and optimizing its parameters\n", + "\n", + "### Find the right chunk size for dask\n", + "\n", + "Chunk size is becoming very important when your data size grows. You can let chunks=True to dask which will automatically determine a chunk size\n", + "Most of the time this chunk size is coherent but users can tweak it to be more efficient.\n", + "\n", + "Also be careful about the compute() method, which is not recommended when your data size higher than RAM amount / 5" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "57ae950e-2ea3-48a9-87ba-3b8a91de7c93", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# First example letting dask compute the chunks\n", + "reading_chunks = True\n", + "data_array_autochunks = rxr.open_rasterio(phr_product_cog, chunks=reading_chunks,lock=False)\n", + "data_array_autochunks" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b8fb6e29-0a84-4ae0-882b-b973af22b054", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "start=time.perf_counter()\n", + "ndvi_array = (data_array_autochunks[3] - data_array_autochunks[0]) / (data_array_autochunks[3] + data_array_autochunks[0])\n", + "output_file = Path(f\"{output_dir}/ndvi_autochunks.tif\")\n", + "ndvi_array.rio.to_raster(output_file,tiled=True)\n", + "end=time.perf_counter()\n", + "print(\"Time to compute with automatic chunk size = {}s\".format((end - start)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8940e64c-1de7-4122-828b-e03a9f43a60b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "reading_chunks = (-1,2048,2048)\n", + "data_array_manualchunks = rxr.open_rasterio(phr_product_cog, chunks=reading_chunks, lock=False)\n", + "data_array_manualchunks" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "58bad330-9498-48ac-b3a0-cad211aaf998", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "start=time.perf_counter()\n", + "ndvi_array = (data_array_manualchunks[3] - data_array_manualchunks[0]) / (data_array_manualchunks[3] + data_array_manualchunks[0])\n", + "output_file = Path(f\"{output_dir}/ndvi_manualchunks.tif\")\n", + "ndvi_array.rio.to_raster(output_file,tiled=True)\n", + "end=time.perf_counter()\n", + "print(\"Time to compute with manual chunk size = {}s\".format((end - start)))" + ] + }, + { + "cell_type": "markdown", + "id": "8622d62f-a986-4893-a932-a44bc2e5c496", + "metadata": {}, + "source": [ + "### Conclusion\n", + "\n", + "With this example we demonstrated that using personalized chunk size can give you immediatly a 10% performance improvment, we highly encourage using chunks in coherence with your CoG size, using multi-band chunks.\n", + "\n", + "
\n", + "Prefer using rxr.to_raster() instead of dask.compute() when your product size is getting bigger as the later seems to be more RAM and CPU consuming\n", + "
\n", + "\n", + "#### Chunk size recommandation for multi band products\n", + "\n", + "When using multiple band products, dask will automaticaly take chunks per band, which slows done the processing\n", + "\n", + "
\n", + "We recommand in that case defining chunks using \"(-1,sizex,sizey)\" which creates chunks with concatenated bands. The time gain can be up to 20% !\n", + "
\n", + "\n", + "#### Don't hesitate to test different chunk sizes before making a conclusion\n", + "\n", + "In our case we used chunks of 32Mo, it is a best practice to use chunks size multiple of the tile size (multiple of 16 works well) for read/write efficiency in RAM.\n", + "Tests have been done with chunks > 128Mo, bigger chunks tends to slow down the process.\n", + "\n", + "
\n", + "Don't use chunks > 256Mo as it becomes counter-productive\n", + "
\n", + "\n", + "#### Adjust the number of workers for dask\n", + "\n", + "If you have a lot of CPU, you can also gain time by adjusting the number of workers for dask, here for 8 CPU we used 4 workers, which gives 2 threads per CPU which is the perfect scenario for modern CPUs with hyperthreading (8 Core => 16 Threads)" + ] + }, + { + "cell_type": "markdown", + "id": "eace634b-3c4c-4db8-8c4f-92ffea2bf1e6", + "metadata": { + "tags": [] + }, + "source": [ + "### The size of your image should lead you to use the right library\n", + "\n", + "
\n", + "If your product is single band or its size is less than your RAM size divided by the number of CPUs (not threads), it is not recommended to use parallelisation libraries such as dask\n", + "
\n", + "\n", + "Let's say you have an average computer that has 16 or 32Go RAM : with this amount of ram we recommend using dask if your **product size is at least your avaialble RAM / 5**\n", + "\n", + "
\n", + "If your product is multi-band, use RIOXarray and/or Dask, we will see in the next chapter that you can tune the parameters to improve the read/write performances\n", + "
\n", + "\n", + "\n", + "Now Let's see how to optimize dask parameters" + ] + }, + { + "cell_type": "markdown", + "id": "f7746770-c831-4598-96ff-f13e1d372e1d", + "metadata": {}, + "source": [ + "## Improve disk write speed with rio.to_raster \n", + "\n", + "In the previous computing, we didn't use the tiled write capability of rio.to_raster, which speeds up the image writing on disk.\n", + "Let's see how to use it" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bfa94789-8576-4b26-a962-226db7d37f01", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%%timeit\n", + "\n", + "reading_chunks = (-1,2048,2048)\n", + "input_data_array = rxr.open_rasterio(phr_product_cog,chunks=reading_chunks,lock=False)\n", + "ndvi_phr = (input_data_array[3] - input_data_array[0]) / (input_data_array[3] + input_data_array[0])\n", + "ndvi_phr.compute()\n", + "output_file = Path(f\"{output_dir}/ndvi_phr.tif\")\n", + "ndvi_phr.rio.to_raster(output_file)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f4346248-866b-4b31-a54c-2a25b61c431d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "input_data_array" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "909e5746-eee9-4f0c-a840-d3e8850dee83", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%%timeit\n", + "\n", + "reading_chunks = (-1,2048,2048)\n", + "input_data_array = rxr.open_rasterio(phr_product_cog,chunks=reading_chunks,lock=False)\n", + "ndvi_phr = (input_data_array[3] - input_data_array[0]) / (input_data_array[3] + input_data_array[0])\n", + "output_file = Path(f\"{output_dir}/ndvi_phr_rxr.tif\")\n", + "# Don't call dask.compute, use rio.to_raster to launch the dask computing on the background\n", + "# Add the Tiled=true parameter to rxr to speed up the disk write\n", + "ndvi_phr.rio.to_raster(output_file,tiled=True)" + ] + }, + { + "cell_type": "markdown", + "id": "f55307be-456b-4a54-9415-9f46b61837fa", + "metadata": { + "tags": [] + }, + "source": [ + "## Performance graphs dask compute vs rio.to_raster with tiled write\n", + "\n", + "This graph has been generated on TREX, with leads to better performance than in this notebook\n", + "\n", + "**The first computing stops at 55s in these graphs that were generated using a slurm script with the exact same code as above**" + ] + }, + { + "attachments": { + "77035e47-e99e-4a83-a3c2-cee41de28d29.png": { + "image/png": "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\njAylh0FEREQKOHLkCNq0aaP0MIgaxGAdkLfuPnLkCBISEhQeDREREUVCSUkJMjIy5DiASI0YrANy\n6UtCQgKDdSIioijDElhSMxZoERERERGpFIN1IiIiIiKVYrBORERERKRSDNaJiIiIiFSKwToRERER\nkUoxWCciIiIiUikG60REREREKsVgnYiIiIhIpRisExERERGpFIN1IiIiIiKVYrBORERERKRSDNaJ\niIiIiFSKwToRERERkUoxWCciIiIiUikG60REREREKsVgnYiIiIhIpRisExERERGpFIN1IiIiIiKV\nYrBORERERKRSDNaJiIiIiFSKwToRERERkUoxWCciIiIiUikG60REREREKsVgnYiIiIhIpRisExER\nERGpFIN1IiIiIiKVYrBORERERKRSDNaJiIiIiFSKwToRERERkUoxWCciIiIiUikG60QKOVxYgY0H\nCpUeBhEREakYg3UiBfxW6sINf1+PO17biNyT5UoPh4iIiFSKwTqRAh79YAeKKjwQRWB3XonSwyEi\nIiKVUjRYb9++PQRBqHeZMmUKAEAURWRnZyM9PR0xMTEYPHgwdu7cWecxXC4Xpk6dipSUFMTGxuL6\n66/H0aNHlXg5REH55Oc8fLYjX/6ZmXUiIiJqjKLB+ubNm5GXlydfVq9eDQC49dZbAQDz58/HggUL\nsGjRImzevBlOpxPDhg1DaWmp/BjTp0/HypUrkZOTg/Xr16OsrAwjR46E1+tV5DURnUlhmQt//WAH\nAKBlvBUAcKiQwToRERE1TNFgPTU1FU6nU758/PHH6NixIwYNGgRRFPHCCy9gzpw5GDVqFLp37443\n33wTFRUVWL58OQCguLgYS5YswXPPPYehQ4eid+/eWLZsGbZv3441a9Yo+dKIGvTohztxqtyNrs54\nzLqqKwDgYGGFwqMiIiIitVJNzbrb7cayZcswYcIECIKA3Nxc5OfnY/jw4fIxVqsVgwYNwoYNGwAA\nW7ZsgcfjqXNMeno6unfvLh/TEJfLhZKSkjoXIsBfehUun23Pwyc/58FoEPDMLb2Q1TIOADPrRERE\n1DjVBOvvv/8+Tp8+jfHjxwMA8vP9Nb1paWl1jktLS5Nvy8/Ph8ViQWJiYqPHNGTevHlwOBzyJSMj\nI4SvhLTq6c9+wYB5X+GHg6dC/tinyt1y+cu9gzqiRxsH2ifHAgBOlLhQ4a4O+XMSERGR9qkmWF+y\n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\nLHH16tXioEGDxGnTpomiyHMeDg899JB46aWXNno7z3noXXvtteKECRPqXDdq1Chx7NixoijynIcD\nAHHlypXyz8Gc49OnT4tms1nMycmRjzl27JhoMBjEzz//PGJjJ9K6qM2su91ubNmyBcOHD69z/fDh\nw7FhwwaFRqVvxcXFAICkpCQAQG5uLvLz8+v8G1itVgwaNIj/Bs00ZcoUXHvttRg6dGid63nOQ+/D\nDz9E3759ceutt6Jly5bo3bs3XnvtNfl2nvPQu/TSS/Hll19i7969AICffvoJ69evxzXXXAOA5zwS\ngjnHW7ZsgcfjqXNMeno6unfvzn8HoibQxQ6m5+LkyZPwer1IS0urc31aWhry8/MVGpV+iaKIBx98\nEJdeeim6d+8OAPJ5bujf4NChQxEfo17k5OTgxx9/xObNm+vdxnMeegcOHMDixYvx4IMP4pFHHsGm\nTZtw//33w2q14o9//CPPeRg89NBDKC4uRteuXWE0GuH1evHUU0/hjjvuAMD3eSQEc47z8/NhsViQ\nmJhY7xjOs0TBi9pgXSIIQp2fRVGsdx0133333Yeff/4Z69evr3cb/w1C58iRI5g2bRpWrVoFm83W\n6HE856Hj8/nQt29fzJ07FwDQu3dv7Ny5E4sXL8Yf//hH+Tie89BZsWIFli1bhuXLl+P888/Htm3b\nMH36dKSnp2PcuHHycTzn4Xcu55j/DkRNE7VlMCkpKTAajfU+3RcUFNTLFFDzTJ06FR9++CG+/vpr\ntGnTRr7e6XQCAP8NQmjLli0oKChAnz59YDKZYDKZsG7dOrz00kswmUzyeeU5D51WrVrhvPPOq3Nd\nt27d5IXqfJ+H3p///Gc8/PDDuP3229GjRw/84Q9/wAMPPIB58+YB4DmPhGDOsdPphNvtRlFRUaPH\nENHZRW2wbrFY0KdPH6xevbrO9atXr8bAgQMVGpW+iKKI++67D++99x6++uorZGZm1rk9MzMTTqez\nzr+B2+3GunXr+G9wjoYMGYLt27dj27Zt8qVv37648847sW3bNnTo0IHnPMQuueSSei1J9+7di3bt\n2gHg+zwcKioqYDDUnb6MRqPcupHnPPyCOcd9+vSB2Wyuc0xeXh527NjBfweiplBsaasK5OTkiGaz\nWVyyZIm4a9cucfr06WJsbKx48OBBpYemC/fee6/ocDjEtWvXinl5efKloqJCPubpp58WHQ6H+N57\n74nbt28X77jjDrFVq1ZiSUmJgiPXl9rdYESR5zzUNm3aJJpMJvGpp54S9+3bJ77zzjui3W4Xly1b\nJh/Dcx5a48aNE1u3bi1+/PHHYm5urvjee++JKSkp4qxZs+RjeM6br7S0VNy6dau4detWEYC4YMEC\ncevWreKhQ4dEUQzuHN9zzz1imzZtxDVr1og//vijeOWVV4q9evUSq6urlXpZRJoT1cG6KIri3//+\nd7Fdu3aixWIRL7zwQrmtIDUfgAYvb7zxhnyMz+cTH3vsMdHpdIpWq1W8/PLLxe3btys3aB36fbDO\ncx56H330kdi9e3fRarWKXbt2FV999dU6t/Och1ZJSYk4bdo0sW3btqLNZhM7dOggzpkzR3S5XPIx\nPOfN9/XXXzf4O3zcuHGiKAZ3jisrK8X77rtPTEpKEmNiYsSRI0eKhw8fVuDVEGmXIIqiqExOn4iI\niIiIziRqa9aJiIiIiNSOwToRERERkUoxWCciIiIiUikG60REREREKsVgnYiIiIhIpRisExERERGp\nFIN1IiIiIiKVYrBORERERKRSDNaJSDOys7NxwQUXRPx5165dC0EQcPr06Yg/NxERRTfuYEpEqiAI\nwhlvHzduHBYtWgSXy4Xk5OQIjcrP7Xbj1KlTSEtLO+s4iYiIQonBOhGpQn5+vvz3FStW4NFHH8We\nPXvk62JiYuBwOJQYGhERkWJYBkNEquB0OuWLw+GAIAj1rvt9Gcz48eNx4403Yu7cuUhLS0OLFi3w\n+OOPo7q6Gn/+85+RlJSENm3a4PXXX6/zXMeOHcNtt92GxMREJCcn44YbbsDBgwcbHdvvy2CWLl2K\nFi1a4IsvvkC3bt0QFxeHq666Cnl5eY0+RlFREe68806kpqYiJiYGWVlZeOONN5pzyoiIKAowWCci\nTfvqq69w/PhxfPPNN1iwYAGys7MxcuRIJCYm4vvvv8c999yDe+65B0eOHAEAVFRU4IorrkBcXBy+\n+eYbrF+/Xg623W530M9bUVGBZ599Fm+//Ta++eYbHD58GDNnzmz0+L/+9a/YtWsXPvvsM+zevRuL\nFy9GSkpKs18/ERHpm0npARARNUdSUhJeeuklGAwGdOnSBfPnz0dFRQUeeeQRAMDs2bPx9NNP43//\n+x9uv/125OTkwGAw4J///Kdcf/7GG2+gRYsWWLt2LYYPHx7U83o8Hrzyyivo2LEjAOC+++7DE088\n0ejxhw8fRu/evdG3b18AQPv27ZvxqomIKFowWCciTTv//PNhMAS+JExLS0P37t3ln41GI5KTk1FQ\nUAAA2LJlC/bv34/4+Pg6j1NVVYVff/016Oe12+1yoA4ArVq1kp+jIffeey9uvvlm/Pjjjxg+fDhu\nvPFGDBw4MOjnIyKi6MRgnYg0zWw21/lZEIQGr/P5fAAAn8+HPn364J133qn3WKmpqc163jOt17/6\n6qtx6NAhfPLJJ1izZg2GDBmCKVOm4Nlnnw36OYmIKPowWCeiqHLhhRdixYoVaNmyJRISEiL63Kmp\nqRg/fjzGjx+Pyy67DH/+858ZrBMR0RlxgSkRRZU777wTKSkpuOGGG/Dtt98iNzcX69atw7Rp03D0\n6NGwPe+jjz6KDz74APv378fOnTvx8ccfo1u3bmF7PiIi0gcG60QUVex2O7755hu0bdsWo0aNQrdu\n3TBhwgRUVlaGNdNusVgwe/Zs9OzZE5dffjmMRiNycnLC9nxERKQP3BSJiIiIiEilmFknIiIiIlIp\nButERERERCrFYJ2IiIiISKUYrBMRERERqRSDdSIiIiIilWKwTkRERESkUgzWiYiIiIhUisE6ERER\nEZFKMVgnIiIiIlIpButERERERCrFYJ2IiIiISKX+P9TxfO4/i7UCAAAAAElFTkSuQmCC\n" + }, + "8b8360f6-274e-47ae-b601-dfb2fb33e812.png": { + "image/png": "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\n//77mDJlCgD6nPtBf38/AoHc01cwGOTRcbTP/UdmH++zzz4Ih8M599m0aRPeeecdeh+I2qJirYVV\nwIMPPmiGw2HzjjvuMFetWmVefvnlZnNzs7l27dpKb1pd8O1vf9tsa2szFy9ebG7atIn/6+/v5/e5\n/vrrzba2NvPRRx81V65caZ555pnm+PHjze7u7gpueX0hpmGYJu1z3bz++utmKBQyf/azn5mrV682\n77vvPrOpqcm89957+X1on+tlzpw55nbbbWf+9a9/NdesWWM++uij5ujRo82rrrqK34f2uXd6enrM\nt956y3zrrbdMAOZNN91kvvXWW+bHH39smqbcPr7ooovMiRMnms8++6y5fPly86tf/aq5xx57mKlU\nqlIviyCUGdLFsmma5m9/+1tzypQpZiQSMffee28ea0Z4B0DRf3feeSe/TyaTMa+77jqzvb3djEaj\n5iGHHGKuXLmychtdh+QXy7TP9fPEE0+Y06ZNM6PRqLnLLruYt99+e87vaZ/rpbu72/zud79rTp48\n2WxoaDB32GEH8wc/+IEZj8f5fWife+eFF14o+h0+Z84c0zTl9nEsFjMvvfRSc+TIkWZjY6N53HHH\nmevWravAqyEI9ximaZqV0bQJgiAIgiAIoroZsp5lgiAIgiAIgnCCimWCIAiCIAiCsIGKZYIgCIIg\nCIKwgYplgiAIgiAIgrCBimWCIAiCIAiCsIGKZYIgCIIgCIKwgYplgiAIgiAIgrCBimWCIAiCIAiC\nsIGKZYIgaoZ58+Zhzz33LPvzLl68GIZhYNu2bWV/boIgCKKy0AQ/giCqAsMwSv5+zpw5uPXWWxGP\nxzFq1KgybVWWRCKBzz//HOPGjXPcToIgCKK+oGKZIIiqoKOjg///Qw89hB/96Ed47733+G2NjY1o\na2urxKYRBEEQQxiyYRAEURW0t7fzf21tbTAMo+C2fBvGueeei5NOOgk///nPMW7cOAwfPhw//vGP\nkUql8L3vfQ8jR47ExIkTsWDBgpzn+uSTT3D66adjxIgRGDVqFE488USsXbvWdtvybRh33XUXhg8f\njmeeeQa77rorWlpacPTRR2PTpk22f2Pr1q0466yzMGbMGDQ2NmKnnXbCnXfe6WWXEQRBEGWAimWC\nIGqa559/Hhs3bsTSpUtx0003Yd68eTjuuOMwYsQIvPbaa7joootw0UUXYf369QCA/v5+HHbYYWhp\nacHSpUvx0ksv8WI3kUhIP29/fz9+9atf4Z577sHSpUuxbt06XHnllbb3/+EPf4hV/7+9+3eFPw7g\nOP70uS/DFYm7k0XKoIuUH5Nyi7oyEYuyXDZRJsMZDCbJZGFQJnU3KrIY/MjIhuUkMvkDUOr6bvdN\nX59vV+f4yvOxvT99er8+7+3V+/N597m64uDggOvrazY2NojFYhWvX5JUXb+++gEkqRJNTU2sr68T\nBAGdnZ2srq7y9PTE4uIiANlslpWVFc7OzpicnCSXyxEEAVtbW6Xvj7e3t2lsbOTo6Ih0Ol1W7uvr\nK5ubm3R0dAAwNzfH8vJy6P339/f09vYyMDAAQHt7ewWrliR9FsuypG+tq6uLIPjzkqylpYXu7u7S\nOBKJ0NzczOPjIwDn5+cUCgXq6+vfzPPy8sLNzU3ZudFotFSUAVpbW0sZ75mZmWFiYoKLiwvS6TRj\nY2MMDg6WnSdJ+hqWZUnfWm1t7ZtxTU3Nu9eKxSIAxWKR/v5+dnZ2/porHo9XlPuv89IjIyPc3d2x\nv7/P4eEhw8PDzM7Osra2VnamJOnzWZYl/Sh9fX3k83kSiQQNDQ2fmh2Px8lkMmQyGYaGhlhYWLAs\nS9J/zgN+kn6UqakpYrEYo6OjnJ6ecnt7y/HxMfPz8zw8PFQtd2lpid3dXQqFApeXl+zt7ZFMJquW\nJ0n6GJZlST9KNBrl5OSEtrY2xsfHSSaTTE9P8/z8XNWd5rq6OrLZLD09PaRSKSKRCLlcrmp5kqSP\n4U9JJEmSpBDuLEuSJEkhLMuSJElSCMuyJEmSFMKyLEmSJIWwLEuSJEkhLMuSJElSCMuyJEmSFMKy\nLEmSJIWwLEuSJEkhLMuSJElSCMuyJEmSFOI3FwFkCxzjLskAAAAASUVORK5CYII=\n" + }, + "d1a3d796-81df-4a8f-90d5-9324e9d1781d.png": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAtQAAAHTCAYAAAAHwI/VAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90\nbGliIHZlcnNpb24zLjguMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/H5lhTAAAACXBIWXMAAA9h\nAAAPYQGoP6dpAAB/T0lEQVR4nO3dd3xT9foH8M9J2qa7pS1ddAKlQKFQpjJkyBQUBQeKCqJcVFCR\n61URrhTFolxFr6K4LsOfIipDEZUlW1Rm2ZsWyuiC7pE0yff3R5qU0JamTdKMft6vV1/ak5Ocb05C\n8+Q5z/f5SkIIASIiIiIiahCZrQdAREREROTIGFATEREREZmBATURERERkRkYUBMRERERmYEBNRER\nERGRGRhQExERERGZgQE1EREREZEZGFATEREREZmBATURERERkRkYUJNTOXz4MJ588km0atUKHh4e\n8PDwQFxcHCZPnox9+/YZ7ZucnAxJkgw/MpkMYWFhuOuuu/DHH3+YdLyYmBhIkoT+/fvXePtXX31l\nePxt27aZ+ezIVKWlpUhOTrbKOd+2bVutr+fhw4chSRIOHjxo8eOaa8KECYiJibH1MIiInJKLrQdA\nZCmfffYZpk6divj4eLzwwgtISEiAJEk4ceIEvv32W3Tv3h1nz55Fq1atjO63fv16+Pn5QavV4uLF\ni5g/fz769++Pv//+G126dKnzuD4+PtixYwfOnTtX7bEXL14MX19fFBYWWvS50q2VlpZizpw5AFDr\nlx1rWLVqFWJjY5GUlNRoxyQiIttjhpqcwh9//IFnn30Ww4cPx4EDB/D888/jzjvvxMCBAzFlyhTs\n2rUL33//PTw8PKrdt2vXrrjtttvQq1cvjB07FitXroRarcbKlStNOnafPn3QokULLF682Gj7uXPn\nsGPHDjz00EMWeY7WVlZWZushOLyVK1dizJgxth6G3RNC8P1GRE6FATU5hZSUFMjlcnz22Wdwc3Or\ncZ8HHngA4eHhdT6Wn58fAMDV1dWkY8tkMjz++ONYtmwZtFqtYfvixYsRGRmJQYMG1Xi/ffv24Z57\n7kFAQADc3d2RlJSE77//3mifpUuXQpIkbNmyBZMmTUJgYCB8fX3x+OOPo6SkBJmZmXjwwQfh7++P\nsLAwvPTSS6ioqKhzzDExMRg5ciRWr16NpKQkuLu7GzK6mZmZmDx5MiIiIuDm5obY2FjMmTMHarXa\n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\n5owQQog///xT3HfffSI6OlooFAoRGBgo+vXrJ9auXWv0WJs3bxZJSUlCoVAIAGL8+PGG29LS0sTE\niRNFixYthKurq2jevLno1auXmDt3rtFjHD9+XAwePFi4u7uLgIAA8eSTT4qffvrJ6PXs06eP0WPf\n6OrVq+L+++8XAQEBws/PTzz66KNi3759RucoKytLTJgwQbRt21Z4eXkJb29vkZiYKN5//32hVquN\nHu/HH38UAwYMEL6+vkKhUIjo6Ghx//33i82bNxvt9+WXX4q4uDjh5uYm2rRpIxYvXlzj+a6J/r2x\ncuVKkZCQINzc3ERMTEy1jjJCCFFcXCxmzZol4uPjhZubm/Dz8xMdO3YUL774osjMzDTsB0BMmTKl\nzmMLYfrra8p7Re+rr74S3bt3N+yXlJRU7T1KRGQOSQghbBPKE5GzSU9PR2xsLJYsWVKtl7YzyszM\nRIsWLfDjjz/i7rvvtvVwLCImJgYdOnTAunXrbD0UIiKHwZIPIqIGCg0NhUajsfUwiIjIxtg2j4iI\niIjIDCz5ICIiIiIyAzPURERERERmYEBNRERERGQGBtRERERERGZw+i4fWq0WV65cgY+PT72WviUi\nIiLHJYRAUVERwsPDIZMxf0jW5fQB9ZUrVxAZGWnrYRAREZENZGRkICIiwtbDICfn9AG1j48PAN0/\nqJqWnSYiIiLnU1hYiMjISEMcQGRNTh9Q68s8fH19GVATERE1MSz3pMbAoiIiIiIiIjMwoCYiIiIi\nMgMDaiIiIiIiMzCgJiIiIiIyAwNqIiIiIiIzMKAmIiIiIjIDA2oiIiIiIjMwoCYiIiIiMgMDaiIi\nIiIiMzCgJiIiIiIyAwNqIiIiIiIzMKAmIiIiIjIDA2oiIiIiIjMwoCYiIiIiMgMDaiIiIiIiMzCg\nJiIiIiIyAwNqIiIiIiIzMKAmIiIiIjIDA2oiIiIiIjMwoCYiIiIiMgMDaiIiIiIiMzCgJiIiIiIy\nAwNqIiIiIiIzMKAmIiIiIjIDA2oiIiIiIjMwoCYiIiIiMgMDaiIiIiIiMzCgJiIiIiIyAwNqIiIi\nIiIzMKAmIiIiIjKDi60H0GhUJYBKbutREBEROR5XT0CSbD0KIrvVdALq9+IBBf8YEBER1dtrVwA3\nL1uPgshuseSDiIiIiMgMTSdD/c9TgK+vrUdBRETkeFw9bT0CIrvWdAJqNy9eriIiIiIii2PJBxER\nERGRGRhQExERERGZgQE1EREREZEZGFATEREREZmBATURERERkRkYUBMRERERmYEBNRERERGRGWwe\nUF++fBmPPvooAgMD4enpic6dO2P//v2G24UQSE5ORnh4ODw8PNC/f38cO3bMhiMmIiIiIqpi04A6\nLy8PvXv3hqurK3777TccP34c7733Hvz9/Q37zJ8/HwsWLMDChQuxd+9ehIaGYvDgwSgqKrLdwImI\niIiIKklCCGGrg7/66qv4448/sHPnzhpvF0IgPDwc06ZNwyuvvAIAUCqVCAkJwTvvvIPJkyfXeYzC\nwkL4+fmhoKAAvlx6nIiIqEng5z81JptmqNeuXYtu3brhgQceQHBwMJKSkvDFF18Ybk9LS0NmZiaG\nDBli2KZQKNCvXz/s3r27xsdUKpUoLCw0+iEiIiIishabBtTnz5/HokWLEBcXhw0bNuDpp5/G888/\nj6+++goAkJmZCQAICQkxul9ISIjhtpvNmzcPfn5+hp/IyEjrPgkiIiIiatJsGlBrtVp06dIFKSkp\nSEpKwuTJkzFp0iQsWrTIaD9Jkox+F0JU26Y3Y8YMFBQUGH4yMjKsNn4iIiIiIpsG1GFhYWjfvr3R\ntnbt2uHixYsAgNDQUAColo3Ozs6ulrXWUygU8PX1NfohIiIiIrIWmwbUvXv3xqlTp4y2nT59GtHR\n0QCA2NhYhIaGYtOmTYbbVSoVtm/fjl69ejXqWImIiIiIauJiy4O/+OKL6NWrF1JSUvDggw9iz549\n+Pzzz/H5558D0JV6TJs2DSkpKYiLi0NcXBxSUlLg6emJRx55xJZDJyIiIiICYOOAunv37lizZg1m\nzJiBN954A7Gxsfjggw8wbtw4wz4vv/wyysrK8OyzzyIvLw89e/bExo0b4ePjY8ORExERERHp2LQP\ndWNgH0oiIqKmh5//1JhsvvQ4EREREZEjY0BNRERERGQGBtRERERERGZgQE1EREREZAYG1ERERERE\nZmBATURERERkBgbURERERERmYEBNRERERGQGBtRERERERGZgQE1EREREZAYG1EREREREZmBATURE\nRERkBgbURERERERmYEBNRERERGQGBtRERERERGZgQE1EREREZAYG1EREREREZmBATURERERkBgbU\nRERERERmYEBNRERERGQGBtRERERERGZgQE1EREREZAYG1EREREREZmBATURERERkBgbURERERERm\nYEBNRERERGQGBtRERERERGZgQE1EREREZAYG1EREREREZmBATURERERkBgbURERERERmYEBNRERE\nRGQGBtRERERERGZgQE1EREREZAYG1EREREREZmBATURERERkBgbURERERERmYEBNRERERGQGBtRE\nRERERGZgQE1EREREZAYG1EREREREZmBATURERERkBgbURERERERmYEBNRERERGQGBtRERERERGaw\naUCdnJwMSZKMfkJDQw23CyGQnJyM8PBweHh4oH///jh27JgNR0xEREREZMzmGeqEhARcvXrV8HPk\nyBHDbfPnz8eCBQuwcOFC7N27F6GhoRg8eDCKiopsOGIiIiIioiouNh+Ai4tRVlpPCIEPPvgAM2fO\nxOjRowEAy5YtQ0hICJYvX47JkyfX+HhKpRJKpdLwe2FhoXUGTkREREQEO8hQnzlzBuHh4YiNjcXY\nsWNx/vx5AEBaWhoyMzMxZMgQw74KhQL9+vXD7t27a328efPmwc/Pz/ATGRlp9edARERERE2XTQPq\nnj174quvvsKGDRvwxRdfIDMzE7169cK1a9eQmZkJAAgJCTG6T0hIiOG2msyYMQMFBQWGn4yMDKs+\nByIiIiJq2mxa8jF8+HDD/3fs2BG33347WrVqhWXLluG2224DAEiSZHQfIUS1bTdSKBRQKBTWGTAR\nERER0U1sXvJxIy8vL3Ts2BFnzpwx1FXfnI3Ozs6ulrUmIiIiIrIVuwqolUolTpw4gbCwMMTGxiI0\nNBSbNm0y3K5SqbB9+3b06tXLhqMkIiIiIqpi05KPl156CXfffTeioqKQnZ2NuXPnorCwEOPHj4ck\nSZg2bRpSUlIQFxeHuLg4pKSkwNPTE4888ogth01EREREZGDTgPrSpUt4+OGHkZubi+bNm+O2227D\nX3/9hejoaADAyy+/jLKyMjz77LPIy8tDz549sXHjRvj4+Nhy2EREREREBpIQQth6ENZUWFgIPz8/\nFBQUwNfX19bDISIiokbAz39qTHZVQ01ERERE5GgYUBMRERERmYEBNRERERGRGRhQExERERGZgQE1\nEREREZEZGFATEREREZmBATURERERkRkYUBMRERERmYEBNRERERGRGRhQExERERGZgQE1EREREZEZ\nGFATEREREZmBATURERERkRkYUBMRERERmYEBNRERERGRGRhQExERERGZgQE1EREREZEZGFATERER\nEZmBATURERERkRkYUBMRERERmYEBNRERERGRGRhQExERERGZgQE1EREREZEZGFATEREREZmBATUR\nERERkRkYUBMRERERmYEBNRERERGRGRhQExERERGZgQE1EREREZEZGFATEREREZmBATURERERkRkY\nUBMRERERmYEBNRERERGRGRhQExERERGZgQE1EREREZEZGFATEREREZmBATURERERkRkYUBMRERER\nmYEBNRERERGRGRhQExERERGZgQE1EREREZEZGFATEREREZmBATURERERkRkYUBMRERERmcFuAup5\n8+ZBkiRMmzbNsE0IgeTkZISHh8PDwwP9+/fHsWPHbDdIIiIiIqKb2EVAvXfvXnz++edITEw02j5/\n/nwsWLAACxcuxN69exEaGorBgwejqKjIRiMlIiIiIjJm84C6uLgY48aNwxdffIFmzZoZtgsh8MEH\nH2DmzJkYPXo0OnTogGXLlqG0tBTLly+34YiJiIiIiKrYPKCeMmUKRowYgUGDBhltT0tLQ2ZmJoYM\nGWLYplAo0K9fP+zevbvWx1MqlSgsLDT6ISIiIiKyFhdbHnzFihU4cOAA9u7dW+22zMxMAEBISIjR\n9pCQEFy4cKHWx5w3bx7mzJlj2YESEREREdXCZhnqjIwMvPDCC/j666/h7u5e636SJBn9LoSotu1G\nM2bMQEFBgeEnIyPDYmMmIiIiIrqZzTLU+/fvR3Z2Nrp27WrYptFosGPHDixcuBCnTp0CoMtUh4WF\nGfbJzs6ulrW+kUKhgEKhsN7AiYiIiIhuYLMM9Z133okjR44gNTXV8NOtWzeMGzcOqampaNmyJUJD\nQ7Fp0ybDfVQqFbZv345evXrZathEREREREZslqH28fFBhw4djLZ5eXkhMDDQsH3atGlISUlBXFwc\n4uLikJKSAk9PTzzyyCO2GDIRERERUTUNCqj37NmDbdu2ITs7G1qt1ui2BQsWWGRgAPDyyy+jrKwM\nzz77LPLy8tCzZ09s3LgRPj4+FjsGEREREZE5JCGEqM8dUlJSMGvWLMTHxyMkJMRogqAkSdiyZYvF\nB2mOwsJC+Pn5oaCgAL6+vrYeDhERETUCfv5TY6p3hvq///0vFi9ejAkTJlhhOEREREREjqXekxJl\nMhl69+5tjbEQERERETmcegfUL774Ij7++GNrjIWIiIiIyOHUu+TjpZdewogRI9CqVSu0b98erq6u\nRrevXr3aYoMjIiIiIrJ39Q6on3vuOWzduhUDBgxAYGDgLVctJCIiIiJydvUOqL/66iusWrUKI0aM\nsMZ4iIiIiIgcSr1rqAMCAtCqVStrjIWIiIiIyOHUO6BOTk7G7NmzUVpaao3xEBERERE5lHqXfHz4\n4Yc4d+4cQkJCEBMTU21S4oEDByw2OCIiIiIie1fvgPree++1wjCIiIiIiBxTvZcedzRcepSIiKjp\n4ec/NaZ611ADQH5+Pr788kvMmDED169fB6Ar9bh8+bJFB0dEREREZO/qXfJx+PBhDBo0CH5+fkhP\nT8ekSZMQEBCANWvW4MKFC/jqq6+sMU4iIiIiIrtU7wz19OnTMWHCBJw5cwbu7u6G7cOHD8eOHTss\nOjgiIiIiIntX74B67969mDx5crXtLVq0QGZmpkUGRURERETkKOodULu7u6OwsLDa9lOnTqF58+YW\nGRQRERERkaOod0A9atQovPHGG6ioqAAASJKEixcv4tVXX8WYMWMsPkAiIiIiIntW74D63XffRU5O\nDoKDg1FWVoZ+/fqhdevW8PHxwVtvvWWNMRIRERER2a16d/nw9fXFrl27sGXLFhw4cABarRZdunTB\noEGDrDE+IiIiIiK7xoVdiIiIyOnw858ak8kZalP7Sz/++OMNHgwRERERkaMxOUMtk8ng7e0NFxcX\n1HYXSZIMKyfaC35DJSIianr4+U+NyeQMdbt27ZCVlYVHH30UEydORGJiojXHRURERETkEEzu8nHs\n2DH88ssvKCsrwx133IFu3bph0aJFNfakJiIiIiJqKurVNq9nz5747LPPcPXqVTz//PP4/vvvERYW\nhnHjxkGpVFprjEREREREdqvefagBwMPDA48//jjmzJmDHj16YMWKFSgtLbX02IiIiIiI7F69A+rL\nly8jJSUFcXFxGDt2LLp3745jx46hWbNm1hgfEREREZFdM3lS4vfff48lS5Zg+/btGDp0KN577z2M\nGDECcrncmuMjIiIiIrJr9WqbFxUVhXHjxiEkJKTW/Z5//nmLDc4S2DaHiIio6eHnPzUmkwPqmJgY\nSJJ06weTJJw/f94iA7MU/oMiIiJqevj5T43J5JKP9PR0Kw6DiIiIiMgxNajLBxERERER6TCgJiIi\nIiIyAwNqIiIiIiIzMKAmIiIiIjIDA2oiIiIiIjOY3OWjJkIIbN26FWVlZejVqxdXSyQiIiKiJsfk\n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\nQwGAr4EF7d+/H9nZ2ejatStcXFzg4uKC7du348MPP4SLi4vhvPKcW05YWBjat29vtK1du3aGyc18\nn1vHv/71L7z66qsYO3YsOnbsiMceewwvvvgi5s2bB4Dn3dpMOb+hoaFQqVTIy8urdR+ipsQpA2o3\nNzd07doVmzZtMtq+adMm9OrVy0ajci5CCEydOhWrV6/Gli1bEBsba3R7bGwsQkNDjV4DlUqF7du3\n8zVooDvvvBNHjhxBamqq4adbt24YN24cUlNT0bJlS55zC+vdu3e1dpCnT59GdHQ0AL7PraW0tBQy\nmfHHk1wuN7TN43m3LlPOb9euXeHq6mq0z9WrV3H06FG+BtQ02Ww6pJWtWLFCuLq6iv/973/i+PHj\nYtq0acLLy0ukp6fbemhO4ZlnnhF+fn5i27Zt4urVq4af0tJSwz5vv/228PPzE6tXrxZHjhwRDz/8\nsAgLCxOFhYU2HLlzubHLhxA855a2Z88e4eLiIt566y1x5swZ8c033whPT0/x9ddfG/bhObe88ePH\nixYtWoh169aJtLQ0sXr1ahEUFCRefvllwz487+YpKioSBw8eFAcPHhQAxIIFC8TBgwfFhQsXhBCm\nnd+nn35aREREiM2bN4sDBw6IgQMHik6dOgm1Wm2rp0VkM04bUAshxMcffyyio6OFm5ub6NKli6Gl\nG5kPQI0/S5YsMeyj1WrF7NmzRWhoqFAoFOKOO+4QR44csd2gndDNATXPueX9/PPPokOHDkKhUIi2\nbduKzz//3Oh2nnPLKywsFC+88IKIiooS7u7uomXLlmLmzJlCqVQa9uF5N8/WrVtr/Bs+fvx4IYRp\n57esrExMnTpVBAQECA8PDzFy5Ehx8eJFGzwbItuThBDCNrlxIiIiIiLH55Q11EREREREjYUBNRER\nERGRGRhQExERERGZgQE1EREREZEZGFATEREREZmBATURERERkRkYUBMRERERmYEBNRERERGRGRhQ\nE5FdSE5ORufOnRv9uNu2bYMkScjPz2/0YxMRkXPgSolEZHWSJN3y9vHjx2PhwoVQKpUIDAxspFHp\nqFQqXL9+HSEhIXWOk4iIqCYMqInI6jIzMw3//9133+H111/HqVOnDNs8PDzg5+dni6ERERGZjSUf\nRGR1oaGhhh8/Pz9IklRt280lHxMmTMC9996LlJQUhISEwN/fH3PmzIFarca//vUvBAQEICIiAosX\nLzY61uXLl/HQQw+hWbNmCAwMxKhRo5Cenl7r2G4u+Vi6dCn8/f2xYcMGtGvXDt7e3hg2bBiuXr1a\n62Pk5eVh3LhxaN68OTw8PBAXF4clS5aYc8qIiMiBMKAmIru1ZcsWXLlyBTt27MCCBQuQnJyMkSNH\nolmzZvj777/x9NNP4+mnn0ZGRgYAoLS0FAMGDIC3tzd27NiBXbt2GQJilUpl8nFLS0vx7rvv4v/+\n7/+wY8cOXLx4ES+99FKt+//73//G8ePH8dtvv+HEiRNYtGgRgoKCzH7+RETkGFxsPQAiotoEBATg\nww8/hEwmQ3x8PObPn4/S0lK89tprAIAZM2bg7bffxh9//IGxY8dixYoVkMlk+PLLLw310EuWLIG/\nvz+2bduGIUOGmHTciooKfPrpp2jVqhUAYOrUqXjjjTdq3f/ixYtISkpCt27dAAAxMTFmPGsiInI0\nDKiJyG4lJCRAJqu6kBYSEoIOHToYfpfL5QgMDER2djYAYP/+/Th79ix8fHyMHqe8vBznzp0z+bie\nnp6GYBoAwsLCDMeoyTPPPIMxY8bgwIEDGDJkCO6991706tXL5OMREZFjY0BNRHbL1dXV6HdJkmrc\nptVqAQBarRZdu3bFN998U+2xmjdvbtZxbzV/e/jw4bhw4QJ++eUXbN68GXfeeSemTJmCd9991+Rj\nEhGR42JATUROo0uXLvjuu+8QHBwMX1/fRj128+bNMWHCBEyYMAF9+/bFv/71LwbURERNBCclEpHT\nGDduHIKCgjBq1Cjs3LkTaWlp2L59O1544QVcunTJasd9/fXX8dNPP+Hs2bM4duwY1q1bh3bt2lnt\neEREZF8YUBOR0/D09MSOHTsQFRWF0aNHo127dpg4cSLKysqsmrF2c3PDjBkzkJiYiDvuuANyuRwr\nVqyw2vGIiMi+cGEXIiIiIiIzMENNRERERGQGBtRERERERGZgQE1EREREZAYG1EREREREZmBATURE\nRERkBgbURERERERmYEBNRERERGQGBtRERERERGZgQE1EREREZAYG1EREREREZmBATURERERkhv8H\nJp97uSo8quYAAAAASUVORK5CYII=\n" + } + }, + "cell_type": "markdown", + "id": "13fa7a12-eca7-436f-91da-f3feaac19118", + "metadata": {}, + "source": [ + "![CPU_GB_Mem_requested-on-used_per_sec.png](attachment:d1a3d796-81df-4a8f-90d5-9324e9d1781d.png)\n", + "\n", + "In this memory usage graph we can conclude that the memory usage for both methods is the same (due to rioxarray way to handle the memory)\n", + "\n", + "![CPU_Local_IOps_in_MB.png](attachment:8b8360f6-274e-47ae-b601-dfb2fb33e812.png)\n", + "\n", + "The local IO per second graph shows that the tiled write indeed produces a higher level of IOps to make the file write faster, but it is restricted by the speed of your SSD.\n", + "\n", + "![CPU_SUM_-percent-CPU_-on-s.png](attachment:77035e47-e99e-4a83-a3c2-cee41de28d29.png)\n", + "\n", + "The CPU usage shows 2 peaks for the computing with dask, only 1 peak with the tiled write scenario\n", + "\n", + "**Conclusion for the performance graphs**\n", + "\n", + "* Both method consumes the same amount of memory ~ 2x the initial product size\n", + "* Cpu usage is **higher with dask.compute() method**" + ] + }, + { + "cell_type": "markdown", + "id": "ffd1783b-a0e3-43f2-861d-13d043653dc6", + "metadata": {}, + "source": [ + "## Conclusions\n", + "\n", + "The initial compute time for an NDVI on the pleiade tile was around 150s, with all the optimisations (CoG compression, parallelisation dask + rioxarray_to raster with tiled=true) we were able to go down to 35s, which **divided the compute time by 3!**\n", + "\n", + "For an NDVI on the same product, the performance difference between these two parallelisation methods is 55s vs 35s here : **57%!**\n", + "\n", + "### Recommandations\n", + "\n", + "
\n", + " \n", + "* Use **lock=False** and **chunks=(-1,sizex,sizey)** for reading the file to improve READ time\n", + " \n", + "* Use **tiled=True** parameter to rio.to_raster to improve WRITE performance\n", + "\n", + "
\n", + "\n", + "* Use rio.to_raster to compute/write in parallel, instead of dask.compute and then write\n", + "\n", + "* Using parallelisation methods dask / RIOXarray leads to a huge time gain without precision loss with big multiband products\n", + "\n", + "* You have to carefully choose your chunk size using a multiple of the cog size" + ] + }, + { + "cell_type": "markdown", + "id": "1898ca12-fdcc-48b9-b733-642f2627bbe9", + "metadata": { + "tags": [] + }, + "source": [ + "# Choose a data format library adapted to your processing chain\n", + "\n", + "Depending on your project, the data format will vary : it is very important to choose a library that can fully handle your product.\n", + "\n", + "A Tutorial is available [here](https://github.com/CNES/pluto-tuto/tree/main/data_type) for a detailed walkthrough on how to choose the right library" + ] + }, + { + "cell_type": "markdown", + "id": "85b9e4b2-7621-48ac-8fa7-14789d40a34a", + "metadata": { + "tags": [] + }, + "source": [ + "# Profiling your processing chain with TREX monitoring\n", + "\n", + "In order to optimize your chain, you have to check where are the bottlenecks of your program. The TREX cluster provides all the tools you need for that, with the monitoring module.\n", + "\n", + "In this tutorial, we use this script to execute as a slurm job, which creates the graphs for CPU, RAM, DISK in png format. [See the graph section](#Performance-graphs-dask-compute-vs-rio.to_raster-with-tiled-write)\n", + "\n", + "The in depth documentation is available [here](https://hpc.pages.cnes.fr/wiki-hpc-sphinx/module-monitoring-2.html)" + ] + }, + { + "cell_type": "markdown", + "id": "846a9449-a9ba-40be-a372-aa43250eb940", + "metadata": { + "tags": [] + }, + "source": [ + "## Write the monitoring script" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ccc05e8b-cfba-4671-8995-8c6a146ebca7", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "greenit_script_monitored = \"\"\"#!/bin/bash\n", + "#\n", + "# Load monitoring module\n", + "module load monitoring/2.2\n", + "#\n", + "# Use of SLURM $TMPDIR of the interactive job\n", + "WORKDIR=$TMPDIR\n", + "SLURM_SUBMIT_DIR={perfo_result_dir}\n", + "#\n", + "cd \"$WORKDIR\"\n", + "#\n", + "# Give model name\n", + "#\n", + "MODEL_NAME=test_perfo_greenit\n", + "#\n", + "# launch start_monitoring.sh to start monitoring of the job ( --name option mandatory)\n", + "#\n", + "start_monitoring.sh --name $MODEL_NAME --io local\n", + "#\n", + "# lauch program\n", + "#\n", + "source /work/scratch/env/romaint/greenit/env_greenit_py312/bin/activate\n", + "python3 /work/scratch/env/romaint/greenit/test_parallelisation.py\n", + "#\n", + "# Stop monitoring -it will generate output_monitoring directory\n", + "#\n", + "stop_monitoring.sh --name $MODEL_NAME\n", + "\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "524fa4c7-16be-44ab-9cc2-345532bb79aa", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "with open(f\"{input_dir}/greenit_monitored.sh\", 'w') as f:\n", + " f.write(greenit_script_monitored.format(perfo_result_dir=perf_results_dir))\n", + "os.chmod(f\"{input_dir}/greenit_monitored.sh\", 0o755)" + ] + }, + { + "cell_type": "markdown", + "id": "8175da03-8e09-41dc-a1ff-01adac85a07f", + "metadata": { + "tags": [] + }, + "source": [ + "## Write the slurm script and submit the job" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a659871-a0fc-4572-960c-f8bf38d14677", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "greenIT_slurm_script = \"\"\"#!/bin/bash\n", + "#SBATCH --job-name=GreenIT_{cpus}_{mem}\n", + "#SBATCH -N 1\n", + "#SBATCH -n 1\n", + "#SBATCH -c {cpus}\n", + "#SBATCH --mem={mem}G # memory per node\n", + "#SBATCH --time=00:30:00 # Wall Time\n", + "#SBATCH --account=cnes_level2 # MANDATORY : account ( launch myaccounts to list your accounts)\n", + "#SBATCH --export=none # To start the job with a clean environnement and source of ~/.bashrc\n", + "#SBATCH --output={output_greenit}/greenIT-{cpus}-{mem}-%j.out\n", + "#SBATCH --error={output_greenit}/greenIT-{cpus}-{mem}-%j.err\n", + "\n", + "sh {input_dir}/greenit_monitored.sh\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b748533f-f3cd-47b8-b01d-c5e5f55d5afd", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "with open(f\"{input_dir}/GreenIT.slurm\", 'w') as f:\n", + " f.write(greenIT_slurm_script.format(cpus=8,mem=56,input_dir=f\"{input_dir}\",output_greenit=f\"{output_dir}\"))\n", + " f.flush()\n", + "output = subprocess.run(['sbatch', f\"{input_dir}/GreenIT.slurm\"], text=True, shell=False)\n", + "print(f\"Submitted job {output}\")" + ] + }, + { + "cell_type": "markdown", + "id": "fbf6dcd7-2a2c-4116-ae51-6dc381b12d56", + "metadata": { + "tags": [] + }, + "source": [ + "## View the generated graphs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7cf71b8-f3e5-4d39-bb2b-2d44fcddf1b4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from IPython.display import Image\n", + "Image(filename=f\"{perf_results_dir}/output_monitoring/CPU_SUM_-percent-CPU_-on-s.png\")" + ] + }, + { + "cell_type": "markdown", + "id": "97205c02-6fc9-42f3-83ed-c8fd4af704af", + "metadata": {}, + "source": [ + "# Estimate the carbon impact of your code\n", + "Using code carbon you can have an estimate of your code footprint,\n", + "Here we would like to calculate the carbon footprint of an NDVI for a S2 and a PHR image for comparison" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ee231cc6-e45c-4209-9135-8c80e1a4eaf4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from codecarbon import track_emissions, EmissionsTracker\n", + "\n", + "tracker = EmissionsTracker()\n", + "\n", + "#@track_emissions()\n", + "def compute_ndvi_sentinel2():\n", + " input_data_b4 = xarray.open_dataarray(s2_b4)\n", + " input_data_b8 = xarray.open_dataarray(s2_b8)\n", + " ndvi_computed = xarray.apply_ufunc(compute_ndvi_std,input_data_b4,input_data_b8)\n", + " output_file = Path(f\"{output_dir}/ndvi_ufunc_sentinel2.tif\")\n", + " ndvi_computed.rio.to_raster(output_file)\n", + "\n", + "#@track_emissions()\n", + "def compute_ndvi_phr():\n", + " input_data_phr = xarray.open_dataarray(phr_product_cog)\n", + " ndvi_computed = xarray.apply_ufunc(compute_ndvi_std,input_data_phr[0],input_data_phr[3])\n", + " output_file = Path(f\"{output_dir}/ndvi_ufunc_phr.tif\")\n", + " ndvi_computed.rio.to_raster(output_file)\n", + "\n", + "tracker.start()\n", + "start = time.perf_counter()\n", + "compute_ndvi_sentinel2()\n", + "end = time.perf_counter()\n", + "print(\"Time to compute to compute sentinel 2 NDVI = {}s\".format((end - start)))\n", + "\n", + "start = time.perf_counter()\n", + "compute_ndvi_phr()\n", + "end = time.perf_counter()\n", + "print(\"Time to compute to compute PHR Ventoux NDVI = {}s\".format((end - start)))\n", + "tracker.stop()" + ] + } + ], + "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.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}