{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Python Built-in Types" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[![colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/davemlz/spyndex/blob/main/docs/tutorials/python_builtin.ipynb)\n", "![level1](https://raw.githubusercontent.com/davemlz/spyndex/main/docs/_static/level1.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We are going to start using spyndex with the simplest objects: `int`, `float`, and... `list`?.\n", "\n", "Before starting, make sure you have `spyndex` and the latest `dask` version. If not, you can upgrade them here:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!pip install -U spyndex" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, let's start!\n", "\n", "First, import `spyndex`:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import spyndex" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `int`\n", "\n", "Now, let's emulate some values for the Near Infrared (`NIR`) and Red (`RED`) reflectances of vegetation with an `int` data type:\n", "\n", "> Let's say that the data values go from 0 to 10000." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "NIR = 6723\n", "RED = 1243" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we check the data types for each one of our variables, we will see that they are `int`:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "NIR type: , value: 6723\n", "RED type: , value: 1243\n" ] } ], "source": [ "print(f\"NIR type: {type(NIR)}, value: {NIR}\")\n", "print(f\"RED type: {type(RED)}, value: {RED}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, let's go and compute the `NDVI`! Let's check the attributes of the index:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "NDVI: Normalized Difference Vegetation Index (attributes = ['bands', 'contributor', 'date_of_addition', 'formula', 'long_name', 'reference', 'short_name', 'type'])" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spyndex.indices.NDVI" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "From these attributes, we need to know the standard name of the bands so we can compute it:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('N', 'R')" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spyndex.indices.NDVI.bands" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That's it! We need the `N` and `R` parameters! Let's create a `dict` to store them (Psst! This dictionary is useful since we can pass it to the `params` argument in the index computation!):" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "parameters = {\"N\": NIR, \"R\": RED}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we just have to compute the index! It can be easily done with `spyndex.computeIndex()`:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "idx = spyndex.computeIndex(\"NDVI\", parameters)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we check the data type of our result, we'll see that it is a `float`!\n", "\n", "> Usually, spectral indices go from -1 to 1 since most of them are normalized differences!" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "idx type: , value: 0.6879236756213909\n" ] } ], "source": [ "print(f\"idx type: {type(idx)}, value: {idx}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `float`\n", "\n", "What if we, besides the `NDVI`, want to compute another index, mmmm, let's say... the `SAVI`?" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('L', 'N', 'R')" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spyndex.indices.SAVI.bands" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Wow! It seems that now, besides the `N` and `R`, we need another parameter... the `L`!? What is that? Well, let's check it! With the `spyndex.constants` object we can check what are those weird parameters that are not bands and we don't know!" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Canopy background adjustment (default = 1.0)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spyndex.constants.L" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ohh, it is the canopy background adjustment! Now we can give it the desired value!\n", "\n", "> For SAVI, the default L value is 0.5... But don't get confused! For the EVI the default value is 1.0!" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "parameters = {\"N\": NIR / 10000, \"R\": RED / 10000, \"L\": 0.5}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Did you notice that we divided the values by 10000? Well, the idea of that computation is to scale the values to [-1,1]. This is because `SAVI` can't be used with values outside that range! Let's check our data types now:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "NIR type: , value: 0.6723\n", "RED type: , value: 0.1243\n", "L type: , value: 0.5\n" ] } ], "source": [ "print(f\"NIR type: {type(parameters['N'])}, value: {parameters['N']}\")\n", "print(f\"RED type: {type(parameters['R'])}, value: {parameters['R']}\")\n", "print(f\"L type: {type(parameters['L'])}, value: {parameters['L']}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Amazing! Now we can compute our indices! Just pass a list of them to `spyndex.computeIndex()`:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "idx = spyndex.computeIndex([\"NDVI\",\"SAVI\"], parameters)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What do you think we will get as a result?..." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "idx type: , value: [0.687923675621391, 0.6339657565941694]\n" ] } ], "source": [ "print(f\"idx type: {type(idx)}, value: {idx}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That's right! A list! Why? Because we computed more than one spectral index! The length of the resulting list is equal to the number of indices that we computed!\n", "\n", "## `list`?\n", "\n", "Nice, very nice... But what if now we have a list of reflectance values and for each pair/group we want to compute the indices?" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "NIR = [0.634, 0.654, 0.567]\n", "RED = [0.123, 0.156, 0.198]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Remember, these are lists!" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "NIR type: , value: [0.634, 0.654, 0.567]\n", "RED type: , value: [0.123, 0.156, 0.198]\n" ] } ], "source": [ "print(f\"NIR type: {type(NIR)}, value: {NIR}\")\n", "print(f\"RED type: {type(RED)}, value: {RED}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Be careful!" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "parameters = {\"N\": NIR, \"R\": RED, \"L\": 0.5}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Are you ready? Let's compute the indices!" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "unsupported operand type(s) for -: 'list' and 'list'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/tmp/ipykernel_17173/2483861871.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0midx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mspyndex\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcomputeIndex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"NDVI\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\"SAVI\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparameters\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m~/gh/spyndex/spyndex/spyndex.py\u001b[0m in \u001b[0;36mcomputeIndex\u001b[0;34m(index, params, online, returnOrigin, coordinate)\u001b[0m\n\u001b[1;32m 206\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 207\u001b[0m \u001b[0m_check_params\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0midx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparams\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 208\u001b[0;31m \u001b[0mresult\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0meval\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mindices\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0midx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"formula\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparams\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 209\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 210\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n", "\u001b[0;31mTypeError\u001b[0m: unsupported operand type(s) for -: 'list' and 'list'" ] } ], "source": [ "idx = spyndex.computeIndex([\"NDVI\",\"SAVI\"], parameters)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![youdied](https://raw.githubusercontent.com/davemlz/spyndex/main/docs/_static/youdied.png)\n", "\n", "Mein Gott!!! What happened? An error? This is outrageous! Somebody kill me!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Relax, relax... that was an expected error, and I will tell you why:\n", "\n", "- `spyndex` doesn't care what kind of objects you use as long as they support overloaded operators.\n", "- With `int` and `float` types that's not a problem because they by default support overloaded operators.\n", "- The bad thing, is that `list` types DON'T SUPPORT OVERLOADED OPERATORS... (Ehmmmm, they support the `+`, but that's a concatenation operation, not an addition)\n", "\n", "Well, now what do we do?...\n", "\n", "Don't worry, people, because `numpy` is here to save us!" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's transform those lists to `numpy.ndarray` objects!" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "parameters = {\"N\": np.array(NIR), \"R\": np.array(RED), \"L\": 0.5}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's check the data types to be sure!" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "NIR type: , value: [0.634 0.654 0.567]\n", "RED type: , value: [0.123 0.156 0.198]\n", "L type: , value: 0.5\n" ] } ], "source": [ "print(f\"NIR type: {type(parameters['N'])}, value: {parameters['N']}\")\n", "print(f\"RED type: {type(parameters['R'])}, value: {parameters['R']}\")\n", "print(f\"L type: {type(parameters['L'])}, value: {parameters['L']}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since `L` is a constant, you don't need to create a repeated list of it ;) Now, let's compute the indices!" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "idx = spyndex.computeIndex([\"NDVI\",\"SAVI\"], parameters)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "No error! :))) Let's check our result!" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "idx type: , value: [[0.67503303 0.61481481 0.48235294]\n", " [0.6097852 0.57022901 0.43754941]]\n" ] } ], "source": [ "print(f\"idx type: {type(idx)}, value: {idx}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Wow! The result is a `numpy.ndarray`? YES! As long as `returnOrigin=True`, `spyndex` will return the result in the same data type as the input!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nice, right?" ] } ], "metadata": { "interpreter": { "hash": "ec6a25acaecf7f06cb08206f3f56e96ccaf6fbab432a979bcf67c9e0ca577c87" }, "kernelspec": { "display_name": "Python 3.9.7 64-bit ('spyndex': conda)", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.7" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }