{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Try GRASS GIS in Jupyter Notebook with Python\n",
    "\n",
    "[<img src=\"../../gui/images/splash_screen.png\" alt=\"GRASS GIS\" style=\"height: 20ex;\"/>](https://grass.osgeo.org/)\n",
    "\n",
    "This is a quick introduction to *GRASS GIS* in a *Jupyter Notebook* using the *Python* scripting language.\n",
    "The interactive notebook is available online thanks to the [*Binder*](https://mybinder.org/) service.\n",
    "\n",
    "Examples here are using a sample GRASS GIS dataset for North Carolina, USA. The dataset is included in this environment.\n",
    "\n",
    "## Usage\n",
    "\n",
    "To run the selected part which is called a cell, hit `Shift + Enter`.\n",
    "\n",
    "## Start\n",
    "\n",
    "There are several ways to use GRASS GIS. When using Python in a notebook, we usually find GRASS GIS Python packages first, import them, initialize GRASS GIS session, and set several variables useful for using GRASS GIS in a notebook."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import Python standard library and IPython packages we need.\n",
    "import os\n",
    "import sys\n",
    "import subprocess\n",
    "from IPython.display import Image\n",
    "\n",
    "# Ask GRASS GIS where its Python packages are.\n",
    "sys.path.append(\n",
    "    subprocess.check_output([\"grass\", \"--config\", \"python_path\"], text=True).strip()\n",
    ")\n",
    "\n",
    "# Import the GRASS GIS packages we need.\n",
    "import grass.script as gs\n",
    "import grass.script.setup as gsetup\n",
    "\n",
    "# Create a GRASS GIS session.\n",
    "gsetup.init(\"~/data/grassdata/nc_basic_spm_grass7/user1\")\n",
    "\n",
    "# We want functions to raise exceptions and see standard output of the modules in the notebook.\n",
    "gs.set_raise_on_error(True)\n",
    "gs.set_capture_stderr(True)\n",
    "# Simply overwrite existing maps like we overwrite Python variable values.\n",
    "os.environ[\"GRASS_OVERWRITE\"] = \"1\"\n",
    "# Enable map rendering in a notebook.\n",
    "os.environ[\"GRASS_FONT\"] = \"sans\"\n",
    "# Set display modules to render into a file (named map.png by default)\n",
    "os.environ[\"GRASS_RENDER_IMMEDIATE\"] = \"cairo\"\n",
    "os.environ[\"GRASS_RENDER_FILE_READ\"] = \"TRUE\"\n",
    "os.environ[\"GRASS_LEGEND_FILE\"] = \"legend.txt\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Raster buffer\n",
    "\n",
    "Set computational region and create multiple buffers in given distances\n",
    "around lakes represented as raster:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gs.parse_command(\"g.region\", raster=\"lakes\", flags=\"pg\")\n",
    "gs.run_command(\"r.buffer\", input=\"lakes\", output=\"lakes_buff\", distances=[60, 120, 240, 500])\n",
    "gs.run_command(\"d.erase\")\n",
    "gs.run_command(\"d.rast\", map=\"lakes_buff\")\n",
    "gs.run_command(\"d.legend\", raster=\"lakes_buff\", range=(2, 5), at=(80, 100, 2, 10))\n",
    "Image(filename=\"map.png\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Vector buffer\n",
    "\n",
    "Create a negative buffer around state boundary represented as a vector.\n",
    "Vector modules typically don't follow computational region,\n",
    "but we set it to inform display modules about our area of interest."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "gs.run_command(\"v.buffer\", input=\"boundary_state\", output=\"buffer\", distance=-10000)\n",
    "gs.parse_command(\"g.region\", vector=\"boundary_state\", flags=\"pg\")\n",
    "gs.run_command(\"d.erase\")  # erase the display before drawing again\n",
    "!rm -f $GRASS_LEGEND_FILE  # and remove the legend file\n",
    "gs.run_command(\"d.vect\", map=\"boundary_state\", fill_color=\"#5A91ED\", legend_label=\"State boundary\")\n",
    "gs.run_command(\"d.vect\", map=\"buffer\", fill_color=\"#F8766D\", legend_label=\"Inner portion\")\n",
    "gs.run_command(\"d.legend.vect\", at=(10, 35))\n",
    "Image(filename=\"map.png\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Additional GRASS Information and Tutorials\n",
    "\n",
    "To find more information on what one can do with GRASS GIS APIs, check out:\n",
    "    \n",
    " - [GRASS GIS Manual](https://grass.osgeo.org/grass-stable/manuals)\n",
    "    \n",
    " - [GRASS Python API Manual](https://grass.osgeo.org/grass-stable/manuals/libpython)\n",
    "\n",
    "For more Jupyter Notebook GRASS GIS tutorials, visit:\n",
    " - [Try GRASS GIS online](https://grass.osgeo.org/learn/tryonline/)\n",
    "\n",
    "## What else is in the sample North Carolina dataset?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(gs.read_command(\"g.list\", type=\"all\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## What other GRASS modules can I try in this notebooks?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(gs.read_command(\"g.search.modules\", flags=\"g\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## When the work finished\n",
    "\n",
    "When we are finished working the mapset, we should end the GRASS session using `finish()` which will remove the temporary files created in the background. After the call, GRASS modules can no longer be executed, so the call is commented out in this notebook to allow running all cells and, at the same time, going back and experimenting with the code."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Uncomment and run when done.\n",
    "# gsetup.finish()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
