├── .gitignore ├── 00_Introduction.ipynb ├── 01_Modules_scripting.ipynb ├── 02_Modules_pygrass.ipynb ├── 03_GIS_objects_pygrass.ipynb ├── 04_Vector_scripting.ipynb ├── 05_Vector_geometries_pygrass.ipynb ├── 06_Vector_pygrass.ipynb ├── 07_Raster_scripting.ipynb ├── 08_Raster_pygrass.ipynb ├── 09_Modules_pygrass_advance.ipynb ├── 10_Modules_pygrass_parallel.ipynb ├── README.md ├── images ├── command_help.png ├── command_structure.png ├── command_window.png ├── grass_database.png ├── grass_start.png └── help_loc_struct.png ├── notebooks.md ├── show.py └── solutions ├── 00_modules.py ├── 02_vector.py └── 03_raster.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | 21 | # Installer logs 22 | pip-log.txt 23 | 24 | # Unit test / coverage reports 25 | .coverage 26 | .tox 27 | nosetests.xml 28 | 29 | # Translations 30 | *.mo 31 | 32 | # Mr Developer 33 | .mr.developer.cfg 34 | .project 35 | .pydevproject 36 | 37 | # backups 38 | *~ 39 | *.png 40 | *.svg 41 | *.csv 42 | -------------------------------------------------------------------------------- /00_Introduction.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# GRASS GIS introduction" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "**GRASS GIS**, commonly referred to as GRASS (Geographic Resources Analysis Support System), is the *oldest free and open source Geographic Information System (GIS) software* suite with around *500 modules* used for geospatial data management and analysis, image processing, graphics and maps production, spatial modeling, and visualization." 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "After launching GRASS GIS, the startup screen will open:" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "![GRASS GIS 7 startup](images/grass_start.png)" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "GRASS data are stored in a directory referred to as DATABASE (also called \"GISDBASE\"). Within this DATABASE, the projects are organized by project areas stored in subdirectories called **LOCATIONs**. " 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "A **LOCATION** *is defined by its coordinate system, map projection and geographical boundaries*. The subdirectories and files defining a LOCATION are created automatically when GRASS is started the first time with a new LOCATION. It is important to understand that each projection stays in its own LOCATION.\n", 43 | "\n", 44 | "See the *Location Wizard* to easily create a new LOCATION from scratch from a geocoded file, by defining the parameters or by selecting the corresponding EPSG projection code. " 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "Each LOCATION can have many **MAPSETs**. Each MAPSET is a LOCATION's subdirectory. New MAPSET can be added at GRASS startup (see related button). " 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "When GRASS GIS is started you can choose your *preferred interface*: **graphical** or **command line**" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "![GRASS GIS 7 graphical interface](images/command_window.png)" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "metadata": {}, 71 | "source": [ 72 | "![GRASS GIS 7 command line](images/command_help.png)" 73 | ] 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "metadata": {}, 78 | "source": [ 79 | "## GRASS GIS data structure" 80 | ] 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "metadata": {}, 85 | "source": [ 86 | "![GRASS GIS 7 location structure](images/grass_database.png)" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "One motivation to maintain *different MAPSETs is to store maps related to project issues or subregions*. Another motivation is to *support simultaneous access of several users* to the map layers stored within the same LOCATION, i.e. teams working on the same project. For teams, a centralized GRASS DATABASE would be defined in a shared network file system (e.g. NFS, Samba). Besides access to his/her own MAPSET, each user can also read map layers in other users' MAPSETs, but s/he *can modify or remove only the map layers in his/her own MAPSET*. " 94 | ] 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "metadata": {}, 99 | "source": [ 100 | "When creating a new LOCATION, GRASS automatically creates a special MAPSET called PERMANENT where the core data for the project can be stored. Data in the PERMANENT MAPSET can only be added, modified or removed by the owner of the PERMANENT MAPSET; however, they can be accessed, analyzed, and copied into their own MAPSET by the other users. The PERMANENT MAPSET is useful for providing general spatial data (e.g. an elevation model), accessible but write-protected to all users who are working in the same LOCATION as the database owner" 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "metadata": {}, 106 | "source": [ 107 | "## GRASS GIS modules structure" 108 | ] 109 | }, 110 | { 111 | "cell_type": "markdown", 112 | "metadata": {}, 113 | "source": [ 114 | "GRASS GIS has a *modular structure* for it's tools, they are divided in several classes depending on the main topic of the tool" 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": {}, 120 | "source": [ 121 | "![GRASS GIS 7 module structure](images/command_structure.png)" 122 | ] 123 | }, 124 | { 125 | "cell_type": "markdown", 126 | "metadata": {}, 127 | "source": [ 128 | "## GRASS GIS raster region and resolution" 129 | ] 130 | }, 131 | { 132 | "cell_type": "markdown", 133 | "metadata": {}, 134 | "source": [ 135 | "In GRASS GIS there are three different region working with raster:\n", 136 | "* [computational region](http://grasswiki.osgeo.org/wiki/Computational_region): extension and resolution for analysis, we have to take care about this when we run our analysis\n", 137 | "* raster region: extension and resolution of the raster\n", 138 | "* visualization region: extension of display to show the maps; this exist only in the GUI" 139 | ] 140 | }, 141 | { 142 | "cell_type": "markdown", 143 | "metadata": {}, 144 | "source": [ 145 | "# Python introduction" 146 | ] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "metadata": {}, 151 | "source": [ 152 | "[http://python.org](Python) is very popular programing language, which has it's supporters and haters. It's syntax is (if compared to other languages) specific among others because of the fact, no brackets are used - code blocks are separated by indentation. " 153 | ] 154 | }, 155 | { 156 | "cell_type": "markdown", 157 | "metadata": {}, 158 | "source": [ 159 | "In the world of geomatics is Python very popular (and we can say, that it's popularity is growing). It's standing between simple scripting using SHELL commands nad more advanced coding on the sytem level in e.g. C. It can also be compared in some ways to Java platform. Most of the existing libraries and programs do have their API suitable for Python, like GRASS GIS Python API." 160 | ] 161 | }, 162 | { 163 | "cell_type": "markdown", 164 | "metadata": {}, 165 | "source": [ 166 | "## Hello world" 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "metadata": {}, 172 | "source": [ 173 | "This is really simple example to print something in Python" 174 | ] 175 | }, 176 | { 177 | "cell_type": "code", 178 | "execution_count": null, 179 | "metadata": {}, 180 | "outputs": [], 181 | "source": [ 182 | "# we define a variable\n", 183 | "myvar = 'Hello world'\n", 184 | "# we print it, print is a Python function\n", 185 | "print (myvar)" 186 | ] 187 | }, 188 | { 189 | "cell_type": "markdown", 190 | "metadata": {}, 191 | "source": [ 192 | "Now we can create a simple function to do the same of before" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": null, 198 | "metadata": {}, 199 | "outputs": [], 200 | "source": [ 201 | "# we define a new funtion\n", 202 | "def myprint(name):\n", 203 | " \"\"\"Function doc string\n", 204 | " \n", 205 | " This function will print given name\n", 206 | " \n", 207 | " :param str name: the name to print\n", 208 | " \"\"\"\n", 209 | " # we use Python print and format function\n", 210 | " print (\"Hello, {na}!\".format(na=name))\n", 211 | " \n", 212 | "myprint('world')" 213 | ] 214 | } 215 | ], 216 | "metadata": { 217 | "kernelspec": { 218 | "display_name": "Python 2", 219 | "language": "python", 220 | "name": "python2" 221 | }, 222 | "language_info": { 223 | "codemirror_mode": { 224 | "name": "ipython", 225 | "version": 2 226 | }, 227 | "file_extension": ".py", 228 | "mimetype": "text/x-python", 229 | "name": "python", 230 | "nbconvert_exporter": "python", 231 | "pygments_lexer": "ipython2", 232 | "version": "2.7.16" 233 | } 234 | }, 235 | "nbformat": 4, 236 | "nbformat_minor": 1 237 | } 238 | -------------------------------------------------------------------------------- /01_Modules_scripting.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from subprocess import PIPE\n", 10 | "import numpy as np\n", 11 | "from IPython.display import Image" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "# Ipython notebook tips" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "Some small tips of the new interface in python/ipython:\n", 26 | "\n", 27 | "* Tab inside brackets gives the help of the command;\n", 28 | "* or using:" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": null, 34 | "metadata": {}, 35 | "outputs": [], 36 | "source": [ 37 | "from grass import script" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "Test the IPython API completition to access GRASS script API, uncomment the line below and press **```tab```** key " 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": null, 50 | "metadata": {}, 51 | "outputs": [], 52 | "source": [ 53 | "#script." 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "metadata": {}, 59 | "source": [ 60 | "Access IPython helper function using the **```?```** suffix" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": null, 66 | "metadata": {}, 67 | "outputs": [], 68 | "source": [ 69 | "script?" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "# Replace BASH" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "GRASS6 and GRASS7, the traditional way for scripting." 84 | ] 85 | }, 86 | { 87 | "cell_type": "markdown", 88 | "metadata": {}, 89 | "source": [ 90 | "Import grass script module, which has some useful functions:" 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": null, 96 | "metadata": {}, 97 | "outputs": [], 98 | "source": [ 99 | "from grass import script" 100 | ] 101 | }, 102 | { 103 | "cell_type": "markdown", 104 | "metadata": {}, 105 | "source": [ 106 | "Let's have a look which function containing the word command are available, with:" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": null, 112 | "metadata": {}, 113 | "outputs": [], 114 | "source": [ 115 | "from grass.pygrass.utils import looking\n", 116 | "\n", 117 | "looking(script, '*command*')" 118 | ] 119 | }, 120 | { 121 | "cell_type": "code", 122 | "execution_count": null, 123 | "metadata": {}, 124 | "outputs": [], 125 | "source": [ 126 | "script.list_pairs(type='rast')" 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "### Start and wait until the end of the process" 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "execution_count": null, 139 | "metadata": {}, 140 | "outputs": [], 141 | "source": [ 142 | "script.run_command('r.info', map='elevation')" 143 | ] 144 | }, 145 | { 146 | "cell_type": "markdown", 147 | "metadata": {}, 148 | "source": [ 149 | "### Parse the kwargs and return a list of parameters" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": null, 155 | "metadata": {}, 156 | "outputs": [], 157 | "source": [ 158 | "script.make_command('r.info', map='elevation', flags='r')" 159 | ] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "metadata": {}, 164 | "source": [ 165 | "### Start and return a `Popen` object" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": null, 171 | "metadata": {}, 172 | "outputs": [], 173 | "source": [ 174 | "script.start_command('r.info', map='elevation')" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": null, 180 | "metadata": {}, 181 | "outputs": [], 182 | "source": [ 183 | "process = script.start_command('r.info', map='elevation', flags='r', stdout=PIPE)" 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": null, 189 | "metadata": {}, 190 | "outputs": [], 191 | "source": [ 192 | "stdout = process.stdout" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": null, 198 | "metadata": {}, 199 | "outputs": [], 200 | "source": [ 201 | "print([line.strip().split('=') for line in stdout])" 202 | ] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": {}, 207 | "source": [ 208 | "### Parse the output of a command" 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": null, 214 | "metadata": {}, 215 | "outputs": [], 216 | "source": [ 217 | "script.parse_command('r.info', map='elevation', flags='g', delimiter='=')" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "execution_count": null, 223 | "metadata": {}, 224 | "outputs": [], 225 | "source": [ 226 | "script.parse_command('g.region', flags='p', delimiter=':')" 227 | ] 228 | }, 229 | { 230 | "cell_type": "markdown", 231 | "metadata": {}, 232 | "source": [ 233 | "### Catch the command output" 234 | ] 235 | }, 236 | { 237 | "cell_type": "code", 238 | "execution_count": null, 239 | "metadata": {}, 240 | "outputs": [], 241 | "source": [ 242 | "region = script.pipe_command('r.info', map='elevation', flags='r')\n", 243 | "region" 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "execution_count": null, 249 | "metadata": {}, 250 | "outputs": [], 251 | "source": [ 252 | "stdout = ''.join(line for line in region.stdout)\n", 253 | "print(stdout)" 254 | ] 255 | }, 256 | { 257 | "cell_type": "markdown", 258 | "metadata": {}, 259 | "source": [ 260 | "### Catch and return the stdout" 261 | ] 262 | }, 263 | { 264 | "cell_type": "code", 265 | "execution_count": null, 266 | "metadata": {}, 267 | "outputs": [], 268 | "source": [ 269 | "stdout = script.read_command('r.info', map='elevation', flags='r')\n", 270 | "print(stdout)" 271 | ] 272 | }, 273 | { 274 | "cell_type": "code", 275 | "execution_count": null, 276 | "metadata": {}, 277 | "outputs": [], 278 | "source": [ 279 | "mrange = dict([line.split('=') for line in stdout.split('\\n') if line != ''])\n", 280 | "for k in mrange:\n", 281 | " mrange[k] = float(mrange[k])\n", 282 | "mrange" 283 | ] 284 | }, 285 | { 286 | "cell_type": "markdown", 287 | "metadata": {}, 288 | "source": [ 289 | "### Use the pipe as input for another command" 290 | ] 291 | }, 292 | { 293 | "cell_type": "markdown", 294 | "metadata": {}, 295 | "source": [ 296 | "Write the rules that we want to use for the reclassification:" 297 | ] 298 | }, 299 | { 300 | "cell_type": "code", 301 | "execution_count": null, 302 | "metadata": {}, 303 | "outputs": [], 304 | "source": [ 305 | "keys = ['low', 'medium low', 'medium', 'medium high', 'high']\n", 306 | "vals = np.linspace(mrange['min']-1, mrange['max']+1, num=len(keys)+1, endpoint=True)\n", 307 | "\n", 308 | "rvals = [(int(vals[i-1])+1, int(vals[i]), i, keys[i-1]) for i in range(1, len(vals))]\n", 309 | "rules = '\\n'.join(['%3d thru %3d = %2d %s' % v for v in rvals])\n", 310 | "print(rules)" 311 | ] 312 | }, 313 | { 314 | "cell_type": "markdown", 315 | "metadata": {}, 316 | "source": [ 317 | "Now we can pass as input for the r.reclass the rules using the function `write_command`:" 318 | ] 319 | }, 320 | { 321 | "cell_type": "code", 322 | "execution_count": null, 323 | "metadata": {}, 324 | "outputs": [], 325 | "source": [ 326 | "script.write_command('r.reclass', input='elevation', output='elev_reclass', rules='-', overwrite=True, stdin=rules)" 327 | ] 328 | }, 329 | { 330 | "cell_type": "markdown", 331 | "metadata": {}, 332 | "source": [ 333 | "### Display the map inside the ipython notebook" 334 | ] 335 | }, 336 | { 337 | "cell_type": "markdown", 338 | "metadata": {}, 339 | "source": [ 340 | "Start a new virtual monitor that generate a file: `view.png` that we can display inside the ipython notebook." 341 | ] 342 | }, 343 | { 344 | "cell_type": "code", 345 | "execution_count": null, 346 | "metadata": {}, 347 | "outputs": [], 348 | "source": [ 349 | "script.run_command('d.mon', start='png', output='view.png', overwrite=True)" 350 | ] 351 | }, 352 | { 353 | "cell_type": "code", 354 | "execution_count": null, 355 | "metadata": {}, 356 | "outputs": [], 357 | "source": [ 358 | "script.run_command('d.rast', map='elevation')\n", 359 | "Image('view.png')" 360 | ] 361 | }, 362 | { 363 | "cell_type": "code", 364 | "execution_count": null, 365 | "metadata": {}, 366 | "outputs": [], 367 | "source": [ 368 | "script.run_command('d.rast', map='elev_reclass')\n", 369 | "Image('view.png')" 370 | ] 371 | }, 372 | { 373 | "cell_type": "code", 374 | "execution_count": null, 375 | "metadata": {}, 376 | "outputs": [], 377 | "source": [ 378 | "script.run_command('d.mon', stop='png')" 379 | ] 380 | }, 381 | { 382 | "cell_type": "markdown", 383 | "metadata": {}, 384 | "source": [ 385 | "# Summary" 386 | ] 387 | }, 388 | { 389 | "cell_type": "markdown", 390 | "metadata": {}, 391 | "source": [ 392 | "We have seen:\n", 393 | "\n", 394 | "* how we can replace Bash script with Python;\n", 395 | "* how to use some IPython Notebook features with GRASS Python;" 396 | ] 397 | }, 398 | { 399 | "cell_type": "markdown", 400 | "metadata": {}, 401 | "source": [ 402 | "# Exercise" 403 | ] 404 | }, 405 | { 406 | "cell_type": "markdown", 407 | "metadata": {}, 408 | "source": [ 409 | "## Time for coding!" 410 | ] 411 | }, 412 | { 413 | "cell_type": "markdown", 414 | "metadata": {}, 415 | "source": [ 416 | "Transform the following Bash script:" 417 | ] 418 | }, 419 | { 420 | "cell_type": "raw", 421 | "metadata": {}, 422 | "source": [ 423 | "#!/bin/bash\n", 424 | "#\n", 425 | "# Compute the distance from a road\n", 426 | "#\n", 427 | "\n", 428 | "# set the region to elevation map:\n", 429 | "g.region rast=elevation\n", 430 | "\n", 431 | "# convert street vector to raster\n", 432 | "v.to.rast input=streets type=line output=streets use=cat --overwrite\n", 433 | "\n", 434 | "# create a unitary map of the cost\n", 435 | "r.mapcalc expression=\"dist_cost=10./cos(slope)\" --overwrite\n", 436 | "\n", 437 | "# compute the distance\n", 438 | "r.cost input=dist_cost output=distance_from_streets outdir=direction start_rast=streets -k --overwrite \n" 439 | ] 440 | }, 441 | { 442 | "cell_type": "markdown", 443 | "metadata": {}, 444 | "source": [ 445 | "into a Python one:" 446 | ] 447 | }, 448 | { 449 | "cell_type": "code", 450 | "execution_count": null, 451 | "metadata": {}, 452 | "outputs": [], 453 | "source": [] 454 | }, 455 | { 456 | "cell_type": "markdown", 457 | "metadata": {}, 458 | "source": [ 459 | "## Create a GRASS module using scripting library" 460 | ] 461 | }, 462 | { 463 | "cell_type": "code", 464 | "execution_count": null, 465 | "metadata": {}, 466 | "outputs": [], 467 | "source": [ 468 | "%%file mygrassmodule.py\n", 469 | "#!/usr/bin/env python\n", 470 | "# -- coding: utf-8 --\n", 471 | "#\n", 472 | "############################################################################\n", 473 | "#\n", 474 | "# MODULE:\t \n", 475 | "#\n", 476 | "# AUTHOR(S): \n", 477 | "#\n", 478 | "# COPYRIGHT:\t(C) 2013 by the GRASS Development Team\n", 479 | "#\n", 480 | "#\t\tThis program is free software under the GNU General Public\n", 481 | "#\t\tLicense (>=v2). Read the file COPYING that comes with GRASS\n", 482 | "#\t\tfor details.\n", 483 | "#\n", 484 | "#############################################################################\n", 485 | "\n", 486 | "##-----------------------\n", 487 | "## DESCRIPTION\n", 488 | "##-----------------------\n", 489 | "#%Module\n", 490 | "#% description: \n", 491 | "#% keywords: \n", 492 | "#% keywords: \n", 493 | "#% keywords: \n", 494 | "#% overwrite: yes\n", 495 | "#%End\n", 496 | "\n", 497 | "##-----------------------\n", 498 | "## VECTOR INPUT\n", 499 | "##-----------------------\n", 500 | "#%option G_OPT_V_MAP\n", 501 | "#% key: key0\n", 502 | "#% description: \n", 503 | "#% required: yes\n", 504 | "#%end\n", 505 | "\n", 506 | "##-----------------------\n", 507 | "## MULTI RASTER INPUT\n", 508 | "##-----------------------\n", 509 | "#%option G_OPT_R_INPUTS\n", 510 | "#% key: key1\n", 511 | "#% description: \n", 512 | "#% multiple: yes\n", 513 | "#% required: no\n", 514 | "#%end\n", 515 | "\n", 516 | "##-----------------------\n", 517 | "## STRING INPUT\n", 518 | "##-----------------------\n", 519 | "#%option\n", 520 | "#% key: key2\n", 521 | "#% description: \n", 522 | "#% type: string\n", 523 | "#% multiple: yes\n", 524 | "#% required: no\n", 525 | "#%end\n", 526 | "from pprint import pprint\n", 527 | "from grass.script import parser\n", 528 | "\n", 529 | "def main(opts, flgs):\n", 530 | " print('OPTIONS:')\n", 531 | " pprint(opts)\n", 532 | " print('FLAGS:')\n", 533 | " pprint(flgs)\n", 534 | " #do something with scripting library\n", 535 | "\n", 536 | "if __name__ == \"__main__\":\n", 537 | " opts, flgs = parser()\n", 538 | " main(opts, flgs)\n", 539 | "\n" 540 | ] 541 | }, 542 | { 543 | "cell_type": "code", 544 | "execution_count": null, 545 | "metadata": {}, 546 | "outputs": [], 547 | "source": [ 548 | "!python2 mygrassmodule.py --h" 549 | ] 550 | }, 551 | { 552 | "cell_type": "code", 553 | "execution_count": null, 554 | "metadata": {}, 555 | "outputs": [], 556 | "source": [ 557 | "!python2 mygrassmodule.py key0=pippo key1=pluto,topolino key2=minni,clarabella" 558 | ] 559 | } 560 | ], 561 | "metadata": { 562 | "kernelspec": { 563 | "display_name": "Python 2", 564 | "language": "python", 565 | "name": "python2" 566 | }, 567 | "language_info": { 568 | "codemirror_mode": { 569 | "name": "ipython", 570 | "version": 2 571 | }, 572 | "file_extension": ".py", 573 | "mimetype": "text/x-python", 574 | "name": "python", 575 | "nbconvert_exporter": "python", 576 | "pygments_lexer": "ipython2", 577 | "version": "2.7.16" 578 | } 579 | }, 580 | "nbformat": 4, 581 | "nbformat_minor": 1 582 | } 583 | -------------------------------------------------------------------------------- /02_Modules_pygrass.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Modules" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "The Modules module permits to work directly with the GRASS GIS module.\n", 15 | "\n", 16 | "More info about Module class" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": null, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "from IPython.display import Image\n", 26 | "from pprint import pprint\n", 27 | "from subprocess import PIPE\n", 28 | "\n", 29 | "import numpy as np\n", 30 | "\n", 31 | "from show import show\n" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "## Using the pygrass module interface" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "User who just wants to replace BASH with python has to import modules in the following manner:" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": null, 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [ 54 | "from grass.pygrass.modules.shortcuts import raster as r, vector as v, general as g, display as d\n", 55 | "from grass.pygrass.modules import Module" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "And then call the grass modules" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": null, 68 | "metadata": {}, 69 | "outputs": [], 70 | "source": [ 71 | "g.region(raster='elevation', flags='p')" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": null, 77 | "metadata": {}, 78 | "outputs": [], 79 | "source": [ 80 | "print(g.region(flags='p', stdout_=PIPE).outputs.stdout)" 81 | ] 82 | }, 83 | { 84 | "cell_type": "markdown", 85 | "metadata": {}, 86 | "source": [ 87 | "If the name of the grass module contains \".\" you should replace it with \"_\". See the example bellow:" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": null, 93 | "metadata": {}, 94 | "outputs": [], 95 | "source": [ 96 | "r.slope_aspect(elevation='elevation', slope='slope', aspect='aspect', overwrite=True)\n", 97 | "r.mapcalc(\"slope_gt_10 = if(slope > 10, slope, null())\", overwrite=True)\n", 98 | "print(r.info(map='slope_gt_10', flags='r', stdout_=PIPE).outputs.stdout)" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": null, 104 | "metadata": {}, 105 | "outputs": [], 106 | "source": [ 107 | "show('slope_gt_10', flags='n')" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": null, 113 | "metadata": {}, 114 | "outputs": [], 115 | "source": [ 116 | "show('slope')" 117 | ] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": {}, 122 | "source": [ 123 | "Do something with the vectors:" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": null, 129 | "metadata": {}, 130 | "outputs": [], 131 | "source": [ 132 | "print(g.list(type='raster', flags='m', stdout_=PIPE).outputs.stdout)" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": null, 138 | "metadata": {}, 139 | "outputs": [], 140 | "source": [ 141 | "v.to_rast(input='hospitals', output='hospitals', type=\"point\", use='cat', overwrite=True, quiet=True)" 142 | ] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "execution_count": null, 147 | "metadata": {}, 148 | "outputs": [], 149 | "source": [ 150 | "print(g.list(type='raster', flags='m', stdout_=PIPE).outputs.stdout)" 151 | ] 152 | }, 153 | { 154 | "cell_type": "markdown", 155 | "metadata": {}, 156 | "source": [ 157 | "## Backwards compatibility" 158 | ] 159 | }, 160 | { 161 | "cell_type": "markdown", 162 | "metadata": {}, 163 | "source": [ 164 | "If you have a python script and want to convert it to use the new python interface, you just need to transform:" 165 | ] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "execution_count": null, 170 | "metadata": {}, 171 | "outputs": [], 172 | "source": [ 173 | "#from grass.script.core import run_command\n", 174 | "from grass.pygrass.modules import Module as run_command\n", 175 | "\n", 176 | "run_command(\"r.info\", map='elevation')\n", 177 | "#etc..." 178 | ] 179 | }, 180 | { 181 | "cell_type": "markdown", 182 | "metadata": {}, 183 | "source": [ 184 | "## Module as object" 185 | ] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "metadata": {}, 190 | "source": [ 191 | "Import the Module class, and instantiate the command, the name of the GRASS module is required." 192 | ] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "execution_count": null, 197 | "metadata": {}, 198 | "outputs": [], 199 | "source": [ 200 | "from grass.pygrass.modules import Module\n", 201 | "\n", 202 | "slp = Module(\"r.slope.aspect\")" 203 | ] 204 | }, 205 | { 206 | "cell_type": "markdown", 207 | "metadata": {}, 208 | "source": [ 209 | "### Attributes" 210 | ] 211 | }, 212 | { 213 | "cell_type": "code", 214 | "execution_count": null, 215 | "metadata": {}, 216 | "outputs": [], 217 | "source": [ 218 | "slp.name" 219 | ] 220 | }, 221 | { 222 | "cell_type": "code", 223 | "execution_count": null, 224 | "metadata": {}, 225 | "outputs": [], 226 | "source": [ 227 | "slp.description" 228 | ] 229 | }, 230 | { 231 | "cell_type": "code", 232 | "execution_count": null, 233 | "metadata": {}, 234 | "outputs": [], 235 | "source": [ 236 | "slp.keywords" 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": null, 242 | "metadata": {}, 243 | "outputs": [], 244 | "source": [ 245 | "slp.label" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": null, 251 | "metadata": {}, 252 | "outputs": [], 253 | "source": [ 254 | "# get the documentation of the module\n", 255 | "slp?" 256 | ] 257 | }, 258 | { 259 | "cell_type": "markdown", 260 | "metadata": {}, 261 | "source": [ 262 | "The instantiated module splits the parameters in:\n", 263 | "\n", 264 | "* inputs\n", 265 | "* outputs\n", 266 | "\n", 267 | "both parameters are an [OrderedDict](http://docs.python.org/2/library/collections.html#collections.OrderedDict) python object. Additionally, the 'required' attribute returns a list of the parameters that are required.\n", 268 | "\n" 269 | ] 270 | }, 271 | { 272 | "cell_type": "code", 273 | "execution_count": null, 274 | "metadata": {}, 275 | "outputs": [], 276 | "source": [ 277 | "pprint(dict(slp.inputs))" 278 | ] 279 | }, 280 | { 281 | "cell_type": "code", 282 | "execution_count": null, 283 | "metadata": {}, 284 | "outputs": [], 285 | "source": [ 286 | "pprint(dict(slp.outputs))" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": null, 292 | "metadata": {}, 293 | "outputs": [], 294 | "source": [ 295 | "slp.required" 296 | ] 297 | }, 298 | { 299 | "cell_type": "code", 300 | "execution_count": null, 301 | "metadata": {}, 302 | "outputs": [], 303 | "source": [ 304 | "slp.inputs['elevation']" 305 | ] 306 | }, 307 | { 308 | "cell_type": "code", 309 | "execution_count": null, 310 | "metadata": {}, 311 | "outputs": [], 312 | "source": [ 313 | "slp.inputs.elevation = \"elevation\"" 314 | ] 315 | }, 316 | { 317 | "cell_type": "code", 318 | "execution_count": null, 319 | "metadata": {}, 320 | "outputs": [], 321 | "source": [ 322 | "slp.inputs.elevation" 323 | ] 324 | }, 325 | { 326 | "cell_type": "code", 327 | "execution_count": null, 328 | "metadata": {}, 329 | "outputs": [], 330 | "source": [ 331 | "slp.inputs[\"format\"]" 332 | ] 333 | }, 334 | { 335 | "cell_type": "code", 336 | "execution_count": null, 337 | "metadata": {}, 338 | "outputs": [], 339 | "source": [ 340 | "slp.inputs.format = 'percents'" 341 | ] 342 | }, 343 | { 344 | "cell_type": "code", 345 | "execution_count": null, 346 | "metadata": {}, 347 | "outputs": [], 348 | "source": [ 349 | "slp.inputs.format = 'percent'" 350 | ] 351 | }, 352 | { 353 | "cell_type": "code", 354 | "execution_count": null, 355 | "metadata": {}, 356 | "outputs": [], 357 | "source": [ 358 | "slp.outputs.slope = 'slope'" 359 | ] 360 | }, 361 | { 362 | "cell_type": "code", 363 | "execution_count": null, 364 | "metadata": {}, 365 | "outputs": [], 366 | "source": [ 367 | "slp.flags.g = True" 368 | ] 369 | }, 370 | { 371 | "cell_type": "code", 372 | "execution_count": null, 373 | "metadata": {}, 374 | "outputs": [], 375 | "source": [ 376 | "slp.flags.a = True" 377 | ] 378 | }, 379 | { 380 | "cell_type": "code", 381 | "execution_count": null, 382 | "metadata": {}, 383 | "outputs": [], 384 | "source": [ 385 | "print slp.flags.overwrite # --overwrite, --verbose, --quite" 386 | ] 387 | }, 388 | { 389 | "cell_type": "code", 390 | "execution_count": null, 391 | "metadata": {}, 392 | "outputs": [], 393 | "source": [ 394 | "slp.flags.overwrite = True\n", 395 | "\n", 396 | "# run the module\n", 397 | "slp.run()" 398 | ] 399 | }, 400 | { 401 | "cell_type": "markdown", 402 | "metadata": {}, 403 | "source": [ 404 | "### Methods" 405 | ] 406 | }, 407 | { 408 | "cell_type": "code", 409 | "execution_count": null, 410 | "metadata": {}, 411 | "outputs": [], 412 | "source": [ 413 | "print slp # __str__" 414 | ] 415 | }, 416 | { 417 | "cell_type": "code", 418 | "execution_count": null, 419 | "metadata": {}, 420 | "outputs": [], 421 | "source": [ 422 | "repr(slp) # __repr__" 423 | ] 424 | }, 425 | { 426 | "cell_type": "code", 427 | "execution_count": null, 428 | "metadata": {}, 429 | "outputs": [], 430 | "source": [ 431 | "from grass.pygrass.modules import Module\n", 432 | "\n", 433 | "slp = Module(\"r.slope.aspect\")\n", 434 | "\n", 435 | "slp(elevation='elevation', \n", 436 | " slope='slp', aspect='asp', \n", 437 | " format='percent', overwrite=True, \n", 438 | " verbose=False, flags='a', run_=False)\n", 439 | "\n", 440 | "print slp.get_bash()\n", 441 | "print slp.get_python()" 442 | ] 443 | }, 444 | { 445 | "cell_type": "markdown", 446 | "metadata": {}, 447 | "source": [ 448 | "## Run as a function" 449 | ] 450 | }, 451 | { 452 | "cell_type": "code", 453 | "execution_count": null, 454 | "metadata": {}, 455 | "outputs": [], 456 | "source": [ 457 | "slp(elevation='elevation', slope='slp', aspect='asp', format='percent', overwrite=True)" 458 | ] 459 | }, 460 | { 461 | "cell_type": "markdown", 462 | "metadata": {}, 463 | "source": [ 464 | "## Special parameters" 465 | ] 466 | }, 467 | { 468 | "cell_type": "markdown", 469 | "metadata": {}, 470 | "source": [ 471 | "### \"run_\" to run later" 472 | ] 473 | }, 474 | { 475 | "cell_type": "code", 476 | "execution_count": null, 477 | "metadata": {}, 478 | "outputs": [], 479 | "source": [ 480 | "slp(elevation='elevation', slope='slp', aspect='asp', format='percent', overwrite=True, run_=False)" 481 | ] 482 | }, 483 | { 484 | "cell_type": "markdown", 485 | "metadata": {}, 486 | "source": [ 487 | "### \"finish_\" to manage the process" 488 | ] 489 | }, 490 | { 491 | "cell_type": "code", 492 | "execution_count": null, 493 | "metadata": {}, 494 | "outputs": [], 495 | "source": [ 496 | "slp(elevation='elevation', slope='slp', aspect='asp', format='percent', overwrite=True, run_=True, finish_=False)" 497 | ] 498 | }, 499 | { 500 | "cell_type": "code", 501 | "execution_count": null, 502 | "metadata": {}, 503 | "outputs": [], 504 | "source": [ 505 | "slp.popen.wait() # .kill()" 506 | ] 507 | }, 508 | { 509 | "cell_type": "markdown", 510 | "metadata": {}, 511 | "source": [ 512 | "### `stdin_`, `stdout_`, `stderr_`" 513 | ] 514 | }, 515 | { 516 | "cell_type": "code", 517 | "execution_count": null, 518 | "metadata": {}, 519 | "outputs": [], 520 | "source": [ 521 | "slp(elevation='elevation', slope='slp', aspect='asp', \n", 522 | " format='percent', overwrite=True, stderr_=PIPE, run_=True)" 523 | ] 524 | }, 525 | { 526 | "cell_type": "code", 527 | "execution_count": null, 528 | "metadata": {}, 529 | "outputs": [], 530 | "source": [ 531 | "print(slp.outputs.stderr)" 532 | ] 533 | }, 534 | { 535 | "cell_type": "code", 536 | "execution_count": null, 537 | "metadata": {}, 538 | "outputs": [], 539 | "source": [ 540 | "gmapset = g.mapset(mapset='_', flags='p', stdout_=PIPE)\n", 541 | "gmapset.outputs.stdout.strip()" 542 | ] 543 | }, 544 | { 545 | "cell_type": "markdown", 546 | "metadata": {}, 547 | "source": [ 548 | "# Summary" 549 | ] 550 | }, 551 | { 552 | "cell_type": "markdown", 553 | "metadata": {}, 554 | "source": [ 555 | "We have seen:\n", 556 | "\n", 557 | "* how we can update existing Python script to use pygrass;\n", 558 | "* play with the grass modules as objects, changing only few parameters;\n", 559 | "* give more power to the user with the special parameters \"*_\".\n", 560 | "\n", 561 | "For more info about Module you can see the class documentation" 562 | ] 563 | }, 564 | { 565 | "cell_type": "markdown", 566 | "metadata": {}, 567 | "source": [ 568 | "# Exercise" 569 | ] 570 | }, 571 | { 572 | "cell_type": "markdown", 573 | "metadata": {}, 574 | "source": [ 575 | "## Time for coding!" 576 | ] 577 | }, 578 | { 579 | "cell_type": "code", 580 | "execution_count": null, 581 | "metadata": {}, 582 | "outputs": [], 583 | "source": [ 584 | "!g.region -p" 585 | ] 586 | }, 587 | { 588 | "cell_type": "markdown", 589 | "metadata": {}, 590 | "source": [ 591 | "Read the output of g.region and return a dictionary." 592 | ] 593 | }, 594 | { 595 | "cell_type": "code", 596 | "execution_count": null, 597 | "metadata": {}, 598 | "outputs": [], 599 | "source": [] 600 | }, 601 | { 602 | "cell_type": "markdown", 603 | "metadata": {}, 604 | "source": [ 605 | "## Create a GRASS module using pygrass" 606 | ] 607 | }, 608 | { 609 | "cell_type": "code", 610 | "execution_count": null, 611 | "metadata": {}, 612 | "outputs": [], 613 | "source": [ 614 | "%%file mygrassmodule.py\n", 615 | "#!/usr/bin/env python\n", 616 | "# -- coding: utf-8 --\n", 617 | "#\n", 618 | "############################################################################\n", 619 | "#\n", 620 | "# MODULE:\t \n", 621 | "#\n", 622 | "# AUTHOR(S): \n", 623 | "#\n", 624 | "# COPYRIGHT:\t(C) 2013 by the GRASS Development Team\n", 625 | "#\n", 626 | "#\t\tThis program is free software under the GNU General Public\n", 627 | "#\t\tLicense (>=v2). Read the file COPYING that comes with GRASS\n", 628 | "#\t\tfor details.\n", 629 | "#\n", 630 | "#############################################################################\n", 631 | "\n", 632 | "##-----------------------\n", 633 | "## DESCRIPTION\n", 634 | "##-----------------------\n", 635 | "#%Module\n", 636 | "#% description: \n", 637 | "#% keywords: \n", 638 | "#% keywords: \n", 639 | "#% keywords: \n", 640 | "#% overwrite: yes\n", 641 | "#%End\n", 642 | "\n", 643 | "##-----------------------\n", 644 | "## VECTOR INPUT\n", 645 | "##-----------------------\n", 646 | "#%option G_OPT_V_MAP\n", 647 | "#% key: key0\n", 648 | "#% description: \n", 649 | "#% required: yes\n", 650 | "#%end\n", 651 | "\n", 652 | "##-----------------------\n", 653 | "## MULTI RASTER INPUT\n", 654 | "##-----------------------\n", 655 | "#%option G_OPT_R_INPUTS\n", 656 | "#% key: key1\n", 657 | "#% description: \n", 658 | "#% multiple: yes\n", 659 | "#% required: no\n", 660 | "#%end\n", 661 | "\n", 662 | "##-----------------------\n", 663 | "## STRING INPUT\n", 664 | "##-----------------------\n", 665 | "#%option\n", 666 | "#% key: key2\n", 667 | "#% description: \n", 668 | "#% type: string\n", 669 | "#% multiple: yes\n", 670 | "#% required: no\n", 671 | "#%end\n", 672 | "from pprint import pprint\n", 673 | "from grass.script import parser\n", 674 | "\n", 675 | "def main(opts, flgs):\n", 676 | " print('OPTIONS:')\n", 677 | " pprint(opts)\n", 678 | " print('FLAGS:')\n", 679 | " pprint(flgs)\n", 680 | " # do something with GRASS script\n", 681 | "\n", 682 | "if __name__ == \"__main__\":\n", 683 | " opts, flgs = parser()\n", 684 | " main(opts, flgs)\n", 685 | "\n" 686 | ] 687 | }, 688 | { 689 | "cell_type": "code", 690 | "execution_count": null, 691 | "metadata": {}, 692 | "outputs": [], 693 | "source": [ 694 | "!python2 mygrassmodule.py --h" 695 | ] 696 | }, 697 | { 698 | "cell_type": "code", 699 | "execution_count": null, 700 | "metadata": {}, 701 | "outputs": [], 702 | "source": [ 703 | "!python2 mygrassmodule.py key0=pippo key1=pluto,topolino key2=minni,clarabella" 704 | ] 705 | } 706 | ], 707 | "metadata": { 708 | "kernelspec": { 709 | "display_name": "Python 2", 710 | "language": "python", 711 | "name": "python2" 712 | }, 713 | "language_info": { 714 | "codemirror_mode": { 715 | "name": "ipython", 716 | "version": 2 717 | }, 718 | "file_extension": ".py", 719 | "mimetype": "text/x-python", 720 | "name": "python", 721 | "nbconvert_exporter": "python", 722 | "pygments_lexer": "ipython2", 723 | "version": "2.7.16" 724 | } 725 | }, 726 | "nbformat": 4, 727 | "nbformat_minor": 1 728 | } 729 | -------------------------------------------------------------------------------- /03_GIS_objects_pygrass.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "In this notebook we will see and use some of the GRASS GIS structure object. You can read more about GRASSDATA, LOCATION and MAPSET in the GRASS GIS introduction." 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "# GISDBASE" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "The GISDBASE, also called *GRASSDATA* is a directory with the structure used by GRASS GIS to store the data, it contain at least a LOCATION.\n", 22 | "\n", 23 | "More info about Gisdbase class" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "from grass.pygrass.gis import Gisdbase\n", 33 | "loc_name = 'nc_basic_spm_grass7'\n", 34 | "#loc_name = 'loc_ncarolina_spm_base0.3.1'\n", 35 | "mapset_name = 'user1'" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": null, 41 | "metadata": {}, 42 | "outputs": [], 43 | "source": [ 44 | "gisdb = Gisdbase()" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": null, 50 | "metadata": {}, 51 | "outputs": [], 52 | "source": [ 53 | "gisdb.name" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": null, 59 | "metadata": {}, 60 | "outputs": [], 61 | "source": [ 62 | "gisdb.locations()" 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": {}, 68 | "source": [ 69 | "# LOCATION" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "The LOCATION is some geographic extent of interest that contains data sets that [should] all be in the **same coordinate system**.\n", 77 | "\n", 78 | "More info about Location class" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [ 87 | "from grass.pygrass.gis import Location\n", 88 | "\n", 89 | "Location()" 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": null, 95 | "metadata": {}, 96 | "outputs": [], 97 | "source": [ 98 | "gisdb[loc_name]" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": null, 104 | "metadata": {}, 105 | "outputs": [], 106 | "source": [ 107 | "northc = gisdb[loc_name]" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": null, 113 | "metadata": {}, 114 | "outputs": [], 115 | "source": [ 116 | "northc.gisdbase" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": null, 122 | "metadata": {}, 123 | "outputs": [], 124 | "source": [ 125 | "northc.name" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": null, 131 | "metadata": {}, 132 | "outputs": [], 133 | "source": [ 134 | "northc.mapsets()" 135 | ] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "metadata": {}, 140 | "source": [ 141 | "# MAPSET" 142 | ] 143 | }, 144 | { 145 | "cell_type": "markdown", 146 | "metadata": {}, 147 | "source": [ 148 | "In a MAPSET you can **organize GIS maps thematically or geographically or by project or whatever**. Every GRASS session runs under the name of a MAPSET. A MAPSET may be a geographical subset or as large as the parent LOCATION.\n", 149 | "\n", 150 | "More info about Mapset class" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": null, 156 | "metadata": {}, 157 | "outputs": [], 158 | "source": [ 159 | "from grass.pygrass.gis import Mapset\n", 160 | "\n", 161 | "Mapset()" 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": null, 167 | "metadata": {}, 168 | "outputs": [], 169 | "source": [ 170 | "northc[mapset_name]" 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": null, 176 | "metadata": {}, 177 | "outputs": [], 178 | "source": [ 179 | "user1 = northc['user1']" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": null, 185 | "metadata": {}, 186 | "outputs": [], 187 | "source": [ 188 | "user1.gisdbase" 189 | ] 190 | }, 191 | { 192 | "cell_type": "code", 193 | "execution_count": null, 194 | "metadata": {}, 195 | "outputs": [], 196 | "source": [ 197 | "user1.location" 198 | ] 199 | }, 200 | { 201 | "cell_type": "code", 202 | "execution_count": null, 203 | "metadata": {}, 204 | "outputs": [], 205 | "source": [ 206 | "user1.name" 207 | ] 208 | }, 209 | { 210 | "cell_type": "code", 211 | "execution_count": null, 212 | "metadata": {}, 213 | "outputs": [], 214 | "source": [ 215 | "user1.glist('raster')" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": null, 221 | "metadata": {}, 222 | "outputs": [], 223 | "source": [ 224 | "%timeit Mapset('user1').glist('raster')" 225 | ] 226 | }, 227 | { 228 | "cell_type": "code", 229 | "execution_count": null, 230 | "metadata": {}, 231 | "outputs": [], 232 | "source": [ 233 | "from grass.script import core as gcore" 234 | ] 235 | }, 236 | { 237 | "cell_type": "code", 238 | "execution_count": null, 239 | "metadata": {}, 240 | "outputs": [], 241 | "source": [ 242 | "gcore.list_grouped('raster')['PERMANENT']" 243 | ] 244 | }, 245 | { 246 | "cell_type": "code", 247 | "execution_count": null, 248 | "metadata": {}, 249 | "outputs": [], 250 | "source": [ 251 | "%timeit gcore.list_grouped('raster')['PERMANENT']" 252 | ] 253 | }, 254 | { 255 | "cell_type": "code", 256 | "execution_count": null, 257 | "metadata": {}, 258 | "outputs": [], 259 | "source": [ 260 | "Mapset('PERMANENT').glist('raster', pattern='el*')" 261 | ] 262 | }, 263 | { 264 | "cell_type": "markdown", 265 | "metadata": {}, 266 | "source": [ 267 | "# Region" 268 | ] 269 | }, 270 | { 271 | "cell_type": "markdown", 272 | "metadata": {}, 273 | "source": [ 274 | "The REGION may be the entire area or subset of the chosen LOCATION. **It is defined by northern, southern, eastern, and western bounds, as well as the raster grid resolution**. It is controlled by the g.region module and is of **primary importance for raster operations**\n", 275 | "\n", 276 | "More info about Region class" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": null, 282 | "metadata": {}, 283 | "outputs": [], 284 | "source": [ 285 | "from grass.pygrass.gis.region import Region" 286 | ] 287 | }, 288 | { 289 | "cell_type": "code", 290 | "execution_count": null, 291 | "metadata": {}, 292 | "outputs": [], 293 | "source": [ 294 | "reg = Region()\n", 295 | "reg" 296 | ] 297 | }, 298 | { 299 | "cell_type": "code", 300 | "execution_count": null, 301 | "metadata": {}, 302 | "outputs": [], 303 | "source": [ 304 | "reg.items()" 305 | ] 306 | }, 307 | { 308 | "cell_type": "code", 309 | "execution_count": null, 310 | "metadata": {}, 311 | "outputs": [], 312 | "source": [ 313 | "reg.north" 314 | ] 315 | }, 316 | { 317 | "cell_type": "code", 318 | "execution_count": null, 319 | "metadata": {}, 320 | "outputs": [], 321 | "source": [ 322 | "reg.ewres" 323 | ] 324 | }, 325 | { 326 | "cell_type": "code", 327 | "execution_count": null, 328 | "metadata": {}, 329 | "outputs": [], 330 | "source": [ 331 | "reg.get_bbox()" 332 | ] 333 | }, 334 | { 335 | "cell_type": "markdown", 336 | "metadata": {}, 337 | "source": [ 338 | "# Bbox" 339 | ] 340 | }, 341 | { 342 | "cell_type": "markdown", 343 | "metadata": {}, 344 | "source": [ 345 | "Is a element of pygrass to create a Bounding Box, it use the bound_box GRASS GIS C structure.\n", 346 | "\n", 347 | "More info about Bbox class" 348 | ] 349 | }, 350 | { 351 | "cell_type": "code", 352 | "execution_count": null, 353 | "metadata": {}, 354 | "outputs": [], 355 | "source": [ 356 | "from grass.pygrass.vector.basic import Bbox\n", 357 | "from grass.pygrass.vector.geometry import Point" 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": null, 363 | "metadata": {}, 364 | "outputs": [], 365 | "source": [ 366 | "bbox = Bbox()" 367 | ] 368 | }, 369 | { 370 | "cell_type": "code", 371 | "execution_count": null, 372 | "metadata": {}, 373 | "outputs": [], 374 | "source": [ 375 | "bbox" 376 | ] 377 | }, 378 | { 379 | "cell_type": "code", 380 | "execution_count": null, 381 | "metadata": {}, 382 | "outputs": [], 383 | "source": [ 384 | "bbox.north = 10\n", 385 | "bbox.east = 10" 386 | ] 387 | }, 388 | { 389 | "cell_type": "code", 390 | "execution_count": null, 391 | "metadata": {}, 392 | "outputs": [], 393 | "source": [ 394 | "point = Point(5, 5)" 395 | ] 396 | }, 397 | { 398 | "cell_type": "code", 399 | "execution_count": null, 400 | "metadata": {}, 401 | "outputs": [], 402 | "source": [ 403 | "bbox.contains(point)" 404 | ] 405 | }, 406 | { 407 | "cell_type": "markdown", 408 | "metadata": {}, 409 | "source": [ 410 | "# Summary" 411 | ] 412 | }, 413 | { 414 | "cell_type": "markdown", 415 | "metadata": {}, 416 | "source": [ 417 | "We have seen:\n", 418 | "\n", 419 | "* GISDBASE, LOCATION and MAPSET classes to work with the GRASS GIS file structure\n", 420 | "* REGION element to obtain informations about GRASS GIS Region and work with it\n", 421 | "* BBOX class to work with bounding box" 422 | ] 423 | } 424 | ], 425 | "metadata": { 426 | "kernelspec": { 427 | "display_name": "Python 2", 428 | "language": "python", 429 | "name": "python2" 430 | }, 431 | "language_info": { 432 | "codemirror_mode": { 433 | "name": "ipython", 434 | "version": 2 435 | }, 436 | "file_extension": ".py", 437 | "mimetype": "text/x-python", 438 | "name": "python", 439 | "nbconvert_exporter": "python", 440 | "pygments_lexer": "ipython2", 441 | "version": "2.7.16" 442 | } 443 | }, 444 | "nbformat": 4, 445 | "nbformat_minor": 1 446 | } 447 | -------------------------------------------------------------------------------- /04_Vector_scripting.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "In this quick notebook we will use some functions of the scripting library to work with vector maps" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "from grass import script\n", 17 | "import collections" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": null, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "MAP = 'geology'\n", 27 | "POINT = [[640000, 228000]]" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": {}, 33 | "source": [ 34 | "# Information" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "Obtain metadata of the map" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "script.vector_info(MAP)" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "Obtain information about the map's topology" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": null, 63 | "metadata": {}, 64 | "outputs": [], 65 | "source": [ 66 | "script.vector_info_topo(MAP)" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": {}, 72 | "source": [ 73 | "Or query the map on a point" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": null, 79 | "metadata": {}, 80 | "outputs": [], 81 | "source": [ 82 | "out = script.vector_what(MAP, POINT)" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": null, 88 | "metadata": {}, 89 | "outputs": [], 90 | "source": [ 91 | "print(out)" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": {}, 98 | "outputs": [], 99 | "source": [ 100 | "for o in out:\n", 101 | " for k,v in o.items():\n", 102 | " if type(v) == collections.OrderedDict:\n", 103 | " print \"{key} = \".format(key=k),\n", 104 | " for ka, va in v.items():\n", 105 | " print(\"{key}: {val}\".format(key=ka, val=va)),\n", 106 | " print()\n", 107 | " else:\n", 108 | " print(\"{key} = {val}\".format(key=k, val=v))" 109 | ] 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "metadata": {}, 114 | "source": [ 115 | "# Attributes" 116 | ] 117 | }, 118 | { 119 | "cell_type": "markdown", 120 | "metadata": {}, 121 | "source": [ 122 | "In this section we will work with the attributes of a vector map.\n", 123 | "\n", 124 | "First we will check if the vector has a connected table" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": null, 130 | "metadata": {}, 131 | "outputs": [], 132 | "source": [ 133 | "script.vector_db(MAP)" 134 | ] 135 | }, 136 | { 137 | "cell_type": "markdown", 138 | "metadata": {}, 139 | "source": [ 140 | "We are also able to see the columns' name" 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": null, 146 | "metadata": {}, 147 | "outputs": [], 148 | "source": [ 149 | "script.vector_columns(MAP)" 150 | ] 151 | }, 152 | { 153 | "cell_type": "markdown", 154 | "metadata": {}, 155 | "source": [ 156 | "It is also possible to query the attributes" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": null, 162 | "metadata": {}, 163 | "outputs": [], 164 | "source": [ 165 | "all_values = script.vector_db_select(MAP)" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": null, 171 | "metadata": {}, 172 | "outputs": [], 173 | "source": [ 174 | "print all_values['columns']" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": null, 180 | "metadata": {}, 181 | "outputs": [], 182 | "source": [ 183 | "print all_values['values'][1]" 184 | ] 185 | } 186 | ], 187 | "metadata": { 188 | "kernelspec": { 189 | "display_name": "Python 2", 190 | "language": "python", 191 | "name": "python2" 192 | }, 193 | "language_info": { 194 | "codemirror_mode": { 195 | "name": "ipython", 196 | "version": 2 197 | }, 198 | "file_extension": ".py", 199 | "mimetype": "text/x-python", 200 | "name": "python", 201 | "nbconvert_exporter": "python", 202 | "pygments_lexer": "ipython2", 203 | "version": "2.7.16" 204 | } 205 | }, 206 | "nbformat": 4, 207 | "nbformat_minor": 1 208 | } 209 | -------------------------------------------------------------------------------- /05_Vector_geometries_pygrass.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "", 4 | "signature": "sha256:4a4840a81d72085cbf62d7d8b72467928c1c7582f09dac66f01f36186ad03c2d" 5 | }, 6 | "nbformat": 3, 7 | "nbformat_minor": 0, 8 | "worksheets": [ 9 | { 10 | "cells": [ 11 | { 12 | "cell_type": "heading", 13 | "level": 1, 14 | "metadata": {}, 15 | "source": [ 16 | "Geometry features" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "Vector maps have different geometry features, like:\n", 24 | "\n", 25 | "* point;\n", 26 | "* line;\n", 27 | "* boundary;\n", 28 | "* area;\n", 29 | "* face (not supported yet);\n", 30 | "* kernel (not supported yet);\n", 31 | "\n", 32 | "All these geometry features are define in:" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "collapsed": false, 38 | "input": [ 39 | "from grass.pygrass.vector import geometry as geo" 40 | ], 41 | "language": "python", 42 | "metadata": {}, 43 | "outputs": [] 44 | }, 45 | { 46 | "cell_type": "heading", 47 | "level": 2, 48 | "metadata": {}, 49 | "source": [ 50 | "Point" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "The point is the simpler type of geometry, it is composed by at least 2 coordinates.\n", 58 | "\n", 59 | "" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "collapsed": false, 65 | "input": [ 66 | "pnt00 = geo.Point(0, 0)" 67 | ], 68 | "language": "python", 69 | "metadata": {}, 70 | "outputs": [] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "We can calculate the distance between two points" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "collapsed": false, 82 | "input": [ 83 | "pnt00.distance(geo.Point(1, 1))" 84 | ], 85 | "language": "python", 86 | "metadata": {}, 87 | "outputs": [] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "Check if it is 2D or 3D" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "collapsed": false, 99 | "input": [ 100 | "pnt00.is2D" 101 | ], 102 | "language": "python", 103 | "metadata": {}, 104 | "outputs": [] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "collapsed": false, 109 | "input": [ 110 | "pnt00.z = 0\n", 111 | "pnt00.is2D" 112 | ], 113 | "language": "python", 114 | "metadata": {}, 115 | "outputs": [] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": {}, 120 | "source": [ 121 | "It is also possible to create a buffer around the point, and obtain an area object" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "collapsed": false, 127 | "input": [ 128 | "buff = pnt00.buffer(2)" 129 | ], 130 | "language": "python", 131 | "metadata": {}, 132 | "outputs": [] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "collapsed": false, 137 | "input": [ 138 | "buff" 139 | ], 140 | "language": "python", 141 | "metadata": {}, 142 | "outputs": [] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "collapsed": false, 147 | "input": [ 148 | "buff.boundary" 149 | ], 150 | "language": "python", 151 | "metadata": {}, 152 | "outputs": [] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "collapsed": false, 157 | "input": [ 158 | "buff.centroid" 159 | ], 160 | "language": "python", 161 | "metadata": {}, 162 | "outputs": [] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "collapsed": false, 167 | "input": [ 168 | "buff.isles" 169 | ], 170 | "language": "python", 171 | "metadata": {}, 172 | "outputs": [] 173 | }, 174 | { 175 | "cell_type": "heading", 176 | "level": 2, 177 | "metadata": {}, 178 | "source": [ 179 | "Line" 180 | ] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": {}, 185 | "source": [ 186 | "A line is created from several [points](#Point).\n", 187 | "\n", 188 | "" 189 | ] 190 | }, 191 | { 192 | "cell_type": "code", 193 | "collapsed": false, 194 | "input": [ 195 | "line = geo.Line([(0, 0), (0, 3)])" 196 | ], 197 | "language": "python", 198 | "metadata": {}, 199 | "outputs": [] 200 | }, 201 | { 202 | "cell_type": "markdown", 203 | "metadata": {}, 204 | "source": [ 205 | "We can perform some simple analysis like:" 206 | ] 207 | }, 208 | { 209 | "cell_type": "markdown", 210 | "metadata": {}, 211 | "source": [ 212 | "* bounding box" 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "collapsed": false, 218 | "input": [ 219 | "line.bbox()" 220 | ], 221 | "language": "python", 222 | "metadata": {}, 223 | "outputs": [] 224 | }, 225 | { 226 | "cell_type": "markdown", 227 | "metadata": {}, 228 | "source": [ 229 | "* length" 230 | ] 231 | }, 232 | { 233 | "cell_type": "code", 234 | "collapsed": false, 235 | "input": [ 236 | "line.length()" 237 | ], 238 | "language": "python", 239 | "metadata": {}, 240 | "outputs": [] 241 | }, 242 | { 243 | "cell_type": "markdown", 244 | "metadata": {}, 245 | "source": [ 246 | "* distance" 247 | ] 248 | }, 249 | { 250 | "cell_type": "code", 251 | "collapsed": false, 252 | "input": [ 253 | "line.distance(geo.Point(4, 1))" 254 | ], 255 | "language": "python", 256 | "metadata": {}, 257 | "outputs": [] 258 | }, 259 | { 260 | "cell_type": "code", 261 | "collapsed": false, 262 | "input": [ 263 | "line.distance?" 264 | ], 265 | "language": "python", 266 | "metadata": {}, 267 | "outputs": [] 268 | }, 269 | { 270 | "cell_type": "markdown", 271 | "metadata": {}, 272 | "source": [ 273 | "* buffer" 274 | ] 275 | }, 276 | { 277 | "cell_type": "code", 278 | "collapsed": false, 279 | "input": [ 280 | "line.is_with_topology()" 281 | ], 282 | "language": "python", 283 | "metadata": {}, 284 | "outputs": [] 285 | }, 286 | { 287 | "cell_type": "code", 288 | "collapsed": false, 289 | "input": [ 290 | "buff = line.buffer(2)" 291 | ], 292 | "language": "python", 293 | "metadata": {}, 294 | "outputs": [] 295 | }, 296 | { 297 | "cell_type": "code", 298 | "collapsed": false, 299 | "input": [ 300 | "buff" 301 | ], 302 | "language": "python", 303 | "metadata": {}, 304 | "outputs": [] 305 | }, 306 | { 307 | "cell_type": "code", 308 | "collapsed": false, 309 | "input": [ 310 | "buff.boundary" 311 | ], 312 | "language": "python", 313 | "metadata": {}, 314 | "outputs": [] 315 | }, 316 | { 317 | "cell_type": "code", 318 | "collapsed": false, 319 | "input": [ 320 | "buff.centroid" 321 | ], 322 | "language": "python", 323 | "metadata": {}, 324 | "outputs": [] 325 | }, 326 | { 327 | "cell_type": "code", 328 | "collapsed": false, 329 | "input": [ 330 | "buff.isles" 331 | ], 332 | "language": "python", 333 | "metadata": {}, 334 | "outputs": [] 335 | }, 336 | { 337 | "cell_type": "heading", 338 | "level": 2, 339 | "metadata": {}, 340 | "source": [ 341 | "Area" 342 | ] 343 | }, 344 | { 345 | "cell_type": "markdown", 346 | "metadata": {}, 347 | "source": [ 348 | "An area is composed by a boundary (a closed, first e last point should be the same, [Line](#Line) object) and a centroid (a [point](#Point) object)" 349 | ] 350 | }, 351 | { 352 | "cell_type": "code", 353 | "collapsed": false, 354 | "input": [ 355 | "area = geo.Area(boundary=geo.Line([(0, 0), (0, 2), (2, 2), (2, 0), (0, 0)]), centroid=geo.Point(1, 1))" 356 | ], 357 | "language": "python", 358 | "metadata": {}, 359 | "outputs": [] 360 | }, 361 | { 362 | "cell_type": "code", 363 | "collapsed": false, 364 | "input": [ 365 | "area.is_with_topology()" 366 | ], 367 | "language": "python", 368 | "metadata": {}, 369 | "outputs": [] 370 | }, 371 | { 372 | "cell_type": "heading", 373 | "level": 1, 374 | "metadata": {}, 375 | "source": [ 376 | "Summary" 377 | ] 378 | }, 379 | { 380 | "cell_type": "markdown", 381 | "metadata": {}, 382 | "source": [ 383 | "We saw how to:\n", 384 | "\n", 385 | "* instantiate a geometry objects (Point, Line, Area);\n", 386 | "* and saw some of their methods (distance, buffer, lenght, etc);" 387 | ] 388 | }, 389 | { 390 | "cell_type": "heading", 391 | "level": 1, 392 | "metadata": {}, 393 | "source": [ 394 | "Exercise" 395 | ] 396 | }, 397 | { 398 | "cell_type": "markdown", 399 | "metadata": {}, 400 | "source": [ 401 | "Below, we define a function to create random point" 402 | ] 403 | }, 404 | { 405 | "cell_type": "code", 406 | "collapsed": false, 407 | "input": [ 408 | "# import the random function\n", 409 | "import random\n", 410 | "\n", 411 | "# import the Point and Region functions?\n", 412 | "from grass.pygrass.vector.geometry import Point\n", 413 | "from grass.pygrass.gis.region import Region\n", 414 | "\n", 415 | "# define a function to produce random points\n", 416 | "def get_random_points(num):\n", 417 | " # inside current GRASS' region of course\n", 418 | " reg = Region()\n", 419 | " # loop over a series of numbers from 0 up to...\n", 420 | " for _ in xrange(0, num):\n", 421 | " # use the function randrange() to get both x and y random numbers\n", 422 | " x = random.randrange(reg.south, reg.north)\n", 423 | " y = random.randrange(reg.west, reg.east)\n", 424 | " # at the end of each loop we need to explicitly catch the pairs of x and y numbers\n", 425 | " # in order to produce a point\n", 426 | " yield Point(x, y)\n" 427 | ], 428 | "language": "python", 429 | "metadata": {}, 430 | "outputs": [] 431 | }, 432 | { 433 | "cell_type": "markdown", 434 | "metadata": {}, 435 | "source": [ 436 | "Using the **get_random_points** function write two functions:\n", 437 | "* one that return the distances between the different points\n", 438 | "* one that return the distances between the points a a line " 439 | ] 440 | }, 441 | { 442 | "cell_type": "code", 443 | "collapsed": false, 444 | "input": [], 445 | "language": "python", 446 | "metadata": {}, 447 | "outputs": [] 448 | }, 449 | { 450 | "cell_type": "code", 451 | "collapsed": false, 452 | "input": [ 453 | "rand_pnts = rand_vect_points('random_points', npoints=10)" 454 | ], 455 | "language": "python", 456 | "metadata": {}, 457 | "outputs": [] 458 | }, 459 | { 460 | "cell_type": "code", 461 | "collapsed": false, 462 | "input": [], 463 | "language": "python", 464 | "metadata": {}, 465 | "outputs": [] 466 | } 467 | ], 468 | "metadata": {} 469 | } 470 | ] 471 | } -------------------------------------------------------------------------------- /06_Vector_pygrass.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Vector Map" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "The pygrass interface for raster maps is divided in 2 classes that represent different ways to interact with vector.\n", 15 | "\n", 16 | "The [**Vector**](http://grass.osgeo.org/grass71/manuals/libpython/pygrass.vector.html#pygrass.vector.Vector) class it is used to work with vector data *without topology*\n", 17 | "\n", 18 | "The [**VectorTopo**](http://grass.osgeo.org/grass71/manuals/libpython/pygrass.vector.html#pygrass.vector.VectorTopo) class instead it is used to work with vector data *with topology*; **this is the class that you should use in most of the case**\n", 19 | "\n", 20 | "We can create a vector map with two approaches:\n", 21 | "\n", 22 | "1) write the vector in two steps:\n", 23 | "\n", 24 | " a. write the geometry features of the vector map\n", 25 | " b. write the values in the attribute table\n", 26 | "\n", 27 | "2) write the vector map, geometry features and tabel attrinute in one step" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": {}, 33 | "source": [ 34 | "## Write a vector map in two steps" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "### Write the geometry features" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "from grass.pygrass.vector import VectorTopo\n", 51 | "from grass.pygrass.vector.geometry import Point" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "new = VectorTopo('newvect')" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": null, 66 | "metadata": {}, 67 | "outputs": [], 68 | "source": [ 69 | "new.open('w')" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "Define some geometry features that will be add to the vector map" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": null, 82 | "metadata": {}, 83 | "outputs": [], 84 | "source": [ 85 | "point0 = Point(636981.336043, 216517.602235)\n", 86 | "point1 = Point(637209.083058, 217970.129540)" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "Write the geometry to the vector map" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": null, 99 | "metadata": {}, 100 | "outputs": [], 101 | "source": [ 102 | "new.write(point0)\n", 103 | "new.write(point1)" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": null, 109 | "metadata": {}, 110 | "outputs": [], 111 | "source": [ 112 | "new.close()" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "### Read the geometry features of the vector map" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": null, 125 | "metadata": {}, 126 | "outputs": [], 127 | "source": [ 128 | "new.open('r')" 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "execution_count": null, 134 | "metadata": {}, 135 | "outputs": [], 136 | "source": [ 137 | "new[1]" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": null, 143 | "metadata": {}, 144 | "outputs": [], 145 | "source": [ 146 | "new[2]" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": null, 152 | "metadata": {}, 153 | "outputs": [], 154 | "source": [ 155 | "new[1].attrs # No table attribute has been created yet" 156 | ] 157 | }, 158 | { 159 | "cell_type": "code", 160 | "execution_count": null, 161 | "metadata": {}, 162 | "outputs": [], 163 | "source": [ 164 | "new.build()" 165 | ] 166 | }, 167 | { 168 | "cell_type": "markdown", 169 | "metadata": {}, 170 | "source": [ 171 | "### Write the attribute values" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "Create a connection with the database" 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": null, 184 | "metadata": {}, 185 | "outputs": [], 186 | "source": [ 187 | "from grass.pygrass.vector.table import Link\n", 188 | "\n", 189 | "# set the layer name\n", 190 | "new.layer = 1\n", 191 | "# create a Link object\n", 192 | "link = Link(layer=new.layer, name=new.name, table=new.name, key='cat',\n", 193 | " database='$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite/sqlite.db',\n", 194 | " driver='sqlite')" 195 | ] 196 | }, 197 | { 198 | "cell_type": "markdown", 199 | "metadata": {}, 200 | "source": [ 201 | "Open the vector map in read and write mode to not loose the geometry features of the vector map" 202 | ] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "execution_count": null, 207 | "metadata": {}, 208 | "outputs": [], 209 | "source": [ 210 | "new.open('rw')" 211 | ] 212 | }, 213 | { 214 | "cell_type": "markdown", 215 | "metadata": {}, 216 | "source": [ 217 | "Add the link to dblinks" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "execution_count": null, 223 | "metadata": {}, 224 | "outputs": [], 225 | "source": [ 226 | "new.dblinks.add(link)" 227 | ] 228 | }, 229 | { 230 | "cell_type": "markdown", 231 | "metadata": {}, 232 | "source": [ 233 | "Define the columns of the attribute table" 234 | ] 235 | }, 236 | { 237 | "cell_type": "code", 238 | "execution_count": null, 239 | "metadata": {}, 240 | "outputs": [], 241 | "source": [ 242 | "cols = [(u'cat', 'INTEGER PRIMARY KEY'),\n", 243 | " (u'name', 'VARCHAR')]" 244 | ] 245 | }, 246 | { 247 | "cell_type": "markdown", 248 | "metadata": {}, 249 | "source": [ 250 | "Retrive the Table object and create the table in the database" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": null, 256 | "metadata": {}, 257 | "outputs": [], 258 | "source": [ 259 | "new.table = new.dblinks[0].table()\n", 260 | "\n", 261 | "# create the table in the DB\n", 262 | "# new.table.columns.create(cols)\n", 263 | "new.table.create(cols)" 264 | ] 265 | }, 266 | { 267 | "cell_type": "markdown", 268 | "metadata": {}, 269 | "source": [ 270 | "insert the values in the table" 271 | ] 272 | }, 273 | { 274 | "cell_type": "code", 275 | "execution_count": null, 276 | "metadata": {}, 277 | "outputs": [], 278 | "source": [ 279 | "new.table.insert([(1, 'pub'), (2, 'resturant')], many=True)" 280 | ] 281 | }, 282 | { 283 | "cell_type": "markdown", 284 | "metadata": {}, 285 | "source": [ 286 | "Save the changes" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": null, 292 | "metadata": {}, 293 | "outputs": [], 294 | "source": [ 295 | "new.table.conn.commit()\n", 296 | "new.close()" 297 | ] 298 | }, 299 | { 300 | "cell_type": "markdown", 301 | "metadata": {}, 302 | "source": [ 303 | "## Write a new vector map in one step" 304 | ] 305 | }, 306 | { 307 | "cell_type": "markdown", 308 | "metadata": {}, 309 | "source": [ 310 | "Remove the previous map" 311 | ] 312 | }, 313 | { 314 | "cell_type": "code", 315 | "execution_count": null, 316 | "metadata": {}, 317 | "outputs": [], 318 | "source": [ 319 | "new.remove()" 320 | ] 321 | }, 322 | { 323 | "cell_type": "markdown", 324 | "metadata": {}, 325 | "source": [ 326 | "Open the map and create the database link and table, with:" 327 | ] 328 | }, 329 | { 330 | "cell_type": "code", 331 | "execution_count": null, 332 | "metadata": {}, 333 | "outputs": [], 334 | "source": [ 335 | "new = VectorTopo('newvect')\n", 336 | "new.open('w', tab_cols=cols)" 337 | ] 338 | }, 339 | { 340 | "cell_type": "markdown", 341 | "metadata": {}, 342 | "source": [ 343 | "Write the geometry feature and the attribute" 344 | ] 345 | }, 346 | { 347 | "cell_type": "code", 348 | "execution_count": null, 349 | "metadata": {}, 350 | "outputs": [], 351 | "source": [ 352 | "new.write(point0, ('pub', ))\n", 353 | "new.write(point1, ('restaurant', ))" 354 | ] 355 | }, 356 | { 357 | "cell_type": "markdown", 358 | "metadata": {}, 359 | "source": [ 360 | "save the changes and close the map" 361 | ] 362 | }, 363 | { 364 | "cell_type": "code", 365 | "execution_count": null, 366 | "metadata": {}, 367 | "outputs": [], 368 | "source": [ 369 | "new.table.conn.commit()\n", 370 | "new.close()" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": null, 376 | "metadata": {}, 377 | "outputs": [], 378 | "source": [ 379 | "new.open('r')\n", 380 | "new[1].attrs['name']" 381 | ] 382 | }, 383 | { 384 | "cell_type": "code", 385 | "execution_count": null, 386 | "metadata": {}, 387 | "outputs": [], 388 | "source": [ 389 | "new.close()" 390 | ] 391 | }, 392 | { 393 | "cell_type": "markdown", 394 | "metadata": {}, 395 | "source": [ 396 | "### Read the new vector map" 397 | ] 398 | }, 399 | { 400 | "cell_type": "code", 401 | "execution_count": null, 402 | "metadata": {}, 403 | "outputs": [], 404 | "source": [ 405 | "new = VectorTopo('newvect')\n", 406 | "new.open('r')" 407 | ] 408 | }, 409 | { 410 | "cell_type": "markdown", 411 | "metadata": {}, 412 | "source": [ 413 | "Read the keys of attribute table for the first feature" 414 | ] 415 | }, 416 | { 417 | "cell_type": "code", 418 | "execution_count": null, 419 | "metadata": {}, 420 | "outputs": [], 421 | "source": [ 422 | "first=new[1]\n", 423 | "first.read()" 424 | ] 425 | }, 426 | { 427 | "cell_type": "markdown", 428 | "metadata": {}, 429 | "source": [ 430 | "Read the values of attribute table for the first feature" 431 | ] 432 | }, 433 | { 434 | "cell_type": "code", 435 | "execution_count": null, 436 | "metadata": {}, 437 | "outputs": [], 438 | "source": [ 439 | "first.attrs" 440 | ] 441 | }, 442 | { 443 | "cell_type": "code", 444 | "execution_count": null, 445 | "metadata": {}, 446 | "outputs": [], 447 | "source": [ 448 | "first.attrs['name']" 449 | ] 450 | }, 451 | { 452 | "cell_type": "markdown", 453 | "metadata": {}, 454 | "source": [ 455 | "Replace value of *name* columns for the first feature" 456 | ] 457 | }, 458 | { 459 | "cell_type": "code", 460 | "execution_count": null, 461 | "metadata": {}, 462 | "outputs": [], 463 | "source": [ 464 | "new[1].attrs['name'] = 'pizza'" 465 | ] 466 | }, 467 | { 468 | "cell_type": "code", 469 | "execution_count": null, 470 | "metadata": {}, 471 | "outputs": [], 472 | "source": [ 473 | "new[1].attrs['name']" 474 | ] 475 | }, 476 | { 477 | "cell_type": "code", 478 | "execution_count": null, 479 | "metadata": {}, 480 | "outputs": [], 481 | "source": [ 482 | "new[1].attrs['cat']" 483 | ] 484 | }, 485 | { 486 | "cell_type": "code", 487 | "execution_count": null, 488 | "metadata": {}, 489 | "outputs": [], 490 | "source": [ 491 | "new.cat(1, 'points')" 492 | ] 493 | }, 494 | { 495 | "cell_type": "code", 496 | "execution_count": null, 497 | "metadata": {}, 498 | "outputs": [], 499 | "source": [ 500 | "pnt = new.cat(1, 'points')[0]" 501 | ] 502 | }, 503 | { 504 | "cell_type": "code", 505 | "execution_count": null, 506 | "metadata": {}, 507 | "outputs": [], 508 | "source": [ 509 | "pnt.cat" 510 | ] 511 | }, 512 | { 513 | "cell_type": "code", 514 | "execution_count": null, 515 | "metadata": {}, 516 | "outputs": [], 517 | "source": [ 518 | "pnt.attrs['name']" 519 | ] 520 | }, 521 | { 522 | "cell_type": "code", 523 | "execution_count": null, 524 | "metadata": {}, 525 | "outputs": [], 526 | "source": [ 527 | "new.close()" 528 | ] 529 | }, 530 | { 531 | "cell_type": "markdown", 532 | "metadata": {}, 533 | "source": [ 534 | "## Rewrite" 535 | ] 536 | }, 537 | { 538 | "cell_type": "markdown", 539 | "metadata": {}, 540 | "source": [ 541 | "Open the map in read-write mode" 542 | ] 543 | }, 544 | { 545 | "cell_type": "code", 546 | "execution_count": null, 547 | "metadata": {}, 548 | "outputs": [], 549 | "source": [ 550 | "new.open('rw')" 551 | ] 552 | }, 553 | { 554 | "cell_type": "markdown", 555 | "metadata": {}, 556 | "source": [ 557 | "Create a new geometry feature:" 558 | ] 559 | }, 560 | { 561 | "cell_type": "code", 562 | "execution_count": null, 563 | "metadata": {}, 564 | "outputs": [], 565 | "source": [ 566 | "point010 = Point(point0.x + 10, point0.y + 10)" 567 | ] 568 | }, 569 | { 570 | "cell_type": "markdown", 571 | "metadata": {}, 572 | "source": [ 573 | "Check the existing values:" 574 | ] 575 | }, 576 | { 577 | "cell_type": "code", 578 | "execution_count": null, 579 | "metadata": {}, 580 | "outputs": [], 581 | "source": [ 582 | "print(new[1] == point010)\n", 583 | "print(new[1].attrs.values())" 584 | ] 585 | }, 586 | { 587 | "cell_type": "markdown", 588 | "metadata": {}, 589 | "source": [ 590 | "Rewrite the values:" 591 | ] 592 | }, 593 | { 594 | "cell_type": "code", 595 | "execution_count": null, 596 | "metadata": {}, 597 | "outputs": [], 598 | "source": [ 599 | "new.rewrite(point010, cat=1, attrs=('Irish Pub',))" 600 | ] 601 | }, 602 | { 603 | "cell_type": "markdown", 604 | "metadata": {}, 605 | "source": [ 606 | "And commit the changes in the database and close the vector map" 607 | ] 608 | }, 609 | { 610 | "cell_type": "code", 611 | "execution_count": null, 612 | "metadata": {}, 613 | "outputs": [], 614 | "source": [ 615 | "new.table.conn.commit()\n", 616 | "new.close()" 617 | ] 618 | }, 619 | { 620 | "cell_type": "markdown", 621 | "metadata": {}, 622 | "source": [ 623 | "Check the values in the vector map" 624 | ] 625 | }, 626 | { 627 | "cell_type": "code", 628 | "execution_count": null, 629 | "metadata": {}, 630 | "outputs": [], 631 | "source": [ 632 | "new.open('r')\n", 633 | "print(new[1] == point010)\n", 634 | "print(new[1].attrs.values())\n", 635 | "new.close()" 636 | ] 637 | }, 638 | { 639 | "cell_type": "markdown", 640 | "metadata": {}, 641 | "source": [ 642 | "## Vector class methods" 643 | ] 644 | }, 645 | { 646 | "cell_type": "markdown", 647 | "metadata": {}, 648 | "source": [ 649 | "Check if a map exists with **exist** method." 650 | ] 651 | }, 652 | { 653 | "cell_type": "code", 654 | "execution_count": null, 655 | "metadata": {}, 656 | "outputs": [], 657 | "source": [ 658 | "new.exist()" 659 | ] 660 | }, 661 | { 662 | "cell_type": "markdown", 663 | "metadata": {}, 664 | "source": [ 665 | "Check if a map is open or not, with **is_open** method." 666 | ] 667 | }, 668 | { 669 | "cell_type": "code", 670 | "execution_count": null, 671 | "metadata": {}, 672 | "outputs": [], 673 | "source": [ 674 | "new.is_open()" 675 | ] 676 | }, 677 | { 678 | "cell_type": "markdown", 679 | "metadata": {}, 680 | "source": [ 681 | "Let's open and ask for **bbox()**" 682 | ] 683 | }, 684 | { 685 | "cell_type": "code", 686 | "execution_count": null, 687 | "metadata": {}, 688 | "outputs": [], 689 | "source": [ 690 | "new.open('r')" 691 | ] 692 | }, 693 | { 694 | "cell_type": "code", 695 | "execution_count": null, 696 | "metadata": {}, 697 | "outputs": [], 698 | "source": [ 699 | "new.bbox()" 700 | ] 701 | }, 702 | { 703 | "cell_type": "markdown", 704 | "metadata": {}, 705 | "source": [ 706 | "Iterate between each line of the vector map" 707 | ] 708 | }, 709 | { 710 | "cell_type": "code", 711 | "execution_count": null, 712 | "metadata": {}, 713 | "outputs": [], 714 | "source": [ 715 | "for pnt in new:\n", 716 | " print(pnt, pnt.attrs.values())" 717 | ] 718 | }, 719 | { 720 | "cell_type": "markdown", 721 | "metadata": {}, 722 | "source": [ 723 | "Get a dictionary with the number of primitive that are present in the vector map" 724 | ] 725 | }, 726 | { 727 | "cell_type": "code", 728 | "execution_count": null, 729 | "metadata": {}, 730 | "outputs": [], 731 | "source": [ 732 | "new.num_primitives()" 733 | ] 734 | }, 735 | { 736 | "cell_type": "markdown", 737 | "metadata": {}, 738 | "source": [ 739 | "Get a number of primitive of the vector map for a selected geometry feature. " 740 | ] 741 | }, 742 | { 743 | "cell_type": "code", 744 | "execution_count": null, 745 | "metadata": {}, 746 | "outputs": [], 747 | "source": [ 748 | "new.num_primitive_of('point')" 749 | ] 750 | }, 751 | { 752 | "cell_type": "code", 753 | "execution_count": null, 754 | "metadata": {}, 755 | "outputs": [], 756 | "source": [ 757 | "new.person" 758 | ] 759 | }, 760 | { 761 | "cell_type": "markdown", 762 | "metadata": {}, 763 | "source": [ 764 | "**viter()** is an iteration method that can be use to perform tasks on each geometry primitive." 765 | ] 766 | }, 767 | { 768 | "cell_type": "code", 769 | "execution_count": null, 770 | "metadata": {}, 771 | "outputs": [], 772 | "source": [ 773 | "count = 0\n", 774 | "for pnt in new.viter(\"lines\"):\n", 775 | " count += 1\n", 776 | "print(\"Lines {}\".format(count))\n", 777 | "count = 0\n", 778 | "for pnt in new.viter(\"points\"):\n", 779 | " count += 1\n", 780 | "print(\"Points {}\".format(count))" 781 | ] 782 | }, 783 | { 784 | "cell_type": "markdown", 785 | "metadata": {}, 786 | "source": [ 787 | "# Object contained in a Vector map" 788 | ] 789 | }, 790 | { 791 | "cell_type": "markdown", 792 | "metadata": {}, 793 | "source": [ 794 | "## DBLinks" 795 | ] 796 | }, 797 | { 798 | "cell_type": "markdown", 799 | "metadata": {}, 800 | "source": [ 801 | "A vector map may have differents attributes tables connected using different database link. The **dblinks** attribute containes all this information.\n", 802 | "\n", 803 | "More info about DBLinks class" 804 | ] 805 | }, 806 | { 807 | "cell_type": "code", 808 | "execution_count": null, 809 | "metadata": {}, 810 | "outputs": [], 811 | "source": [ 812 | "new.dblinks" 813 | ] 814 | }, 815 | { 816 | "cell_type": "markdown", 817 | "metadata": {}, 818 | "source": [ 819 | "The **num_dblinks** method return the number of link object that are available for the vector map" 820 | ] 821 | }, 822 | { 823 | "cell_type": "code", 824 | "execution_count": null, 825 | "metadata": {}, 826 | "outputs": [], 827 | "source": [ 828 | "new.dblinks.num_dblinks()" 829 | ] 830 | }, 831 | { 832 | "cell_type": "markdown", 833 | "metadata": {}, 834 | "source": [ 835 | "Then we can choose the database connection using the **index**, the **layer** or the connection **name**:" 836 | ] 837 | }, 838 | { 839 | "cell_type": "code", 840 | "execution_count": null, 841 | "metadata": {}, 842 | "outputs": [], 843 | "source": [ 844 | "new.dblinks.by_index(0)" 845 | ] 846 | }, 847 | { 848 | "cell_type": "code", 849 | "execution_count": null, 850 | "metadata": {}, 851 | "outputs": [], 852 | "source": [ 853 | "new.dblinks.by_layer(1)" 854 | ] 855 | }, 856 | { 857 | "cell_type": "code", 858 | "execution_count": null, 859 | "metadata": {}, 860 | "outputs": [], 861 | "source": [ 862 | "new.dblinks.by_name('newvect')" 863 | ] 864 | }, 865 | { 866 | "cell_type": "markdown", 867 | "metadata": {}, 868 | "source": [ 869 | "We can add new connection to the vector map with the **add** method:" 870 | ] 871 | }, 872 | { 873 | "cell_type": "code", 874 | "execution_count": null, 875 | "metadata": {}, 876 | "outputs": [], 877 | "source": [ 878 | "new.dblinks.add" 879 | ] 880 | }, 881 | { 882 | "cell_type": "markdown", 883 | "metadata": {}, 884 | "source": [ 885 | "and remove the connection with the **remove** method" 886 | ] 887 | }, 888 | { 889 | "cell_type": "code", 890 | "execution_count": null, 891 | "metadata": {}, 892 | "outputs": [], 893 | "source": [ 894 | "new.dblinks.remove" 895 | ] 896 | }, 897 | { 898 | "cell_type": "markdown", 899 | "metadata": {}, 900 | "source": [ 901 | "## Link" 902 | ] 903 | }, 904 | { 905 | "cell_type": "markdown", 906 | "metadata": {}, 907 | "source": [ 908 | "The *Link* class it is used for the link between vector map and attribute table.\n", 909 | "\n", 910 | "More info about Link class" 911 | ] 912 | }, 913 | { 914 | "cell_type": "code", 915 | "execution_count": null, 916 | "metadata": {}, 917 | "outputs": [], 918 | "source": [ 919 | "link = new.dblinks[0]" 920 | ] 921 | }, 922 | { 923 | "cell_type": "markdown", 924 | "metadata": {}, 925 | "source": [ 926 | "You can obtain more information about the connection link" 927 | ] 928 | }, 929 | { 930 | "cell_type": "code", 931 | "execution_count": null, 932 | "metadata": {}, 933 | "outputs": [], 934 | "source": [ 935 | "link.database" 936 | ] 937 | }, 938 | { 939 | "cell_type": "code", 940 | "execution_count": null, 941 | "metadata": {}, 942 | "outputs": [], 943 | "source": [ 944 | "link.name" 945 | ] 946 | }, 947 | { 948 | "cell_type": "code", 949 | "execution_count": null, 950 | "metadata": {}, 951 | "outputs": [], 952 | "source": [ 953 | "link.table_name" 954 | ] 955 | }, 956 | { 957 | "cell_type": "code", 958 | "execution_count": null, 959 | "metadata": {}, 960 | "outputs": [], 961 | "source": [ 962 | "link.driver" 963 | ] 964 | }, 965 | { 966 | "cell_type": "code", 967 | "execution_count": null, 968 | "metadata": {}, 969 | "outputs": [], 970 | "source": [ 971 | "link.key" 972 | ] 973 | }, 974 | { 975 | "cell_type": "code", 976 | "execution_count": null, 977 | "metadata": {}, 978 | "outputs": [], 979 | "source": [ 980 | "link.layer" 981 | ] 982 | }, 983 | { 984 | "cell_type": "markdown", 985 | "metadata": {}, 986 | "source": [ 987 | "The **connection** method return a Connection object that follow the [PEP-249](http://www.python.org/dev/peps/pep-0249/)" 988 | ] 989 | }, 990 | { 991 | "cell_type": "code", 992 | "execution_count": null, 993 | "metadata": {}, 994 | "outputs": [], 995 | "source": [ 996 | "link.connection()" 997 | ] 998 | }, 999 | { 1000 | "cell_type": "markdown", 1001 | "metadata": {}, 1002 | "source": [ 1003 | "therefore we can use directly the connection with the db, with:" 1004 | ] 1005 | }, 1006 | { 1007 | "cell_type": "code", 1008 | "execution_count": null, 1009 | "metadata": {}, 1010 | "outputs": [], 1011 | "source": [ 1012 | "conn = link.connection()\n", 1013 | "cur = conn.cursor()\n", 1014 | "cur.execute(\"SELECT * FROM {nv}\".format(nv=new.name))\n", 1015 | "cur.fetchall()" 1016 | ] 1017 | }, 1018 | { 1019 | "cell_type": "markdown", 1020 | "metadata": {}, 1021 | "source": [ 1022 | "The **table** method return a **Table** object that will be show in the following part." 1023 | ] 1024 | }, 1025 | { 1026 | "cell_type": "code", 1027 | "execution_count": null, 1028 | "metadata": {}, 1029 | "outputs": [], 1030 | "source": [ 1031 | "link.table()" 1032 | ] 1033 | }, 1034 | { 1035 | "cell_type": "markdown", 1036 | "metadata": {}, 1037 | "source": [ 1038 | "## Table" 1039 | ] 1040 | }, 1041 | { 1042 | "cell_type": "markdown", 1043 | "metadata": {}, 1044 | "source": [ 1045 | "The **Table** object describe the attribute table, and it is possible to *do query on attributes*.\n", 1046 | "\n", 1047 | "More info about Table class" 1048 | ] 1049 | }, 1050 | { 1051 | "cell_type": "code", 1052 | "execution_count": null, 1053 | "metadata": {}, 1054 | "outputs": [], 1055 | "source": [ 1056 | "new.table.columns" 1057 | ] 1058 | }, 1059 | { 1060 | "cell_type": "markdown", 1061 | "metadata": {}, 1062 | "source": [ 1063 | "Obtain all the data from the table" 1064 | ] 1065 | }, 1066 | { 1067 | "cell_type": "code", 1068 | "execution_count": null, 1069 | "metadata": {}, 1070 | "outputs": [], 1071 | "source": [ 1072 | "cur = new.table.execute()\n", 1073 | "cur.fetchall()" 1074 | ] 1075 | }, 1076 | { 1077 | "cell_type": "markdown", 1078 | "metadata": {}, 1079 | "source": [ 1080 | "or filter the select" 1081 | ] 1082 | }, 1083 | { 1084 | "cell_type": "code", 1085 | "execution_count": null, 1086 | "metadata": {}, 1087 | "outputs": [], 1088 | "source": [ 1089 | "new.table.filters.select('name').where('cat=1')" 1090 | ] 1091 | }, 1092 | { 1093 | "cell_type": "code", 1094 | "execution_count": null, 1095 | "metadata": {}, 1096 | "outputs": [], 1097 | "source": [ 1098 | "new.table.filters.get_sql()" 1099 | ] 1100 | }, 1101 | { 1102 | "cell_type": "code", 1103 | "execution_count": null, 1104 | "metadata": {}, 1105 | "outputs": [], 1106 | "source": [ 1107 | "cur = new.table.execute()\n", 1108 | "cur.fetchone()[0]" 1109 | ] 1110 | }, 1111 | { 1112 | "cell_type": "code", 1113 | "execution_count": null, 1114 | "metadata": {}, 1115 | "outputs": [], 1116 | "source": [ 1117 | "new.close()" 1118 | ] 1119 | }, 1120 | { 1121 | "cell_type": "markdown", 1122 | "metadata": {}, 1123 | "source": [ 1124 | "# Summary" 1125 | ] 1126 | }, 1127 | { 1128 | "cell_type": "markdown", 1129 | "metadata": {}, 1130 | "source": [ 1131 | "We saw how to:\n", 1132 | "\n", 1133 | "* write a vector map with only the geometry features;\n", 1134 | "* add a new database connection, create and fill the attributes table;\n", 1135 | "* read, iterate and modify an existing vector map;\n", 1136 | "* select some values from an attribute table, change, add, cast and remove columns;" 1137 | ] 1138 | }, 1139 | { 1140 | "cell_type": "markdown", 1141 | "metadata": {}, 1142 | "source": [ 1143 | "# Exercise" 1144 | ] 1145 | }, 1146 | { 1147 | "cell_type": "markdown", 1148 | "metadata": {}, 1149 | "source": [ 1150 | "Below, we define a function to create random point" 1151 | ] 1152 | }, 1153 | { 1154 | "cell_type": "code", 1155 | "execution_count": null, 1156 | "metadata": {}, 1157 | "outputs": [], 1158 | "source": [ 1159 | "# import the random function\n", 1160 | "import random\n", 1161 | "\n", 1162 | "# import the Point and Region functions?\n", 1163 | "from grass.pygrass.vector.geometry import Point\n", 1164 | "from grass.pygrass.gis.region import Region\n", 1165 | "\n", 1166 | "# define a function to produce random points\n", 1167 | "def get_random_points(num):\n", 1168 | " # inside current GRASS' region of course\n", 1169 | " reg = Region()\n", 1170 | " # loop over a series of numbers from 0 up to...\n", 1171 | " for _ in xrange(0, num):\n", 1172 | " # use the function randrange() to get both x and y random numbers\n", 1173 | " x = random.randrange(reg.south, reg.north)\n", 1174 | " y = random.randrange(reg.west, reg.east)\n", 1175 | " # at the end of each loop we need to explicitly catch the pairs of x and y numbers\n", 1176 | " # in order to produce a point\n", 1177 | " yield Point(x, y)\n" 1178 | ] 1179 | }, 1180 | { 1181 | "cell_type": "markdown", 1182 | "metadata": {}, 1183 | "source": [ 1184 | "Using the **get_random_points** function write a function that return a new vector points map" 1185 | ] 1186 | }, 1187 | { 1188 | "cell_type": "code", 1189 | "execution_count": null, 1190 | "metadata": {}, 1191 | "outputs": [], 1192 | "source": [ 1193 | "# Here write the function" 1194 | ] 1195 | }, 1196 | { 1197 | "cell_type": "code", 1198 | "execution_count": null, 1199 | "metadata": {}, 1200 | "outputs": [], 1201 | "source": [ 1202 | "rand_pnts = rand_vect_points('random_points', npoints=10)" 1203 | ] 1204 | }, 1205 | { 1206 | "cell_type": "code", 1207 | "execution_count": null, 1208 | "metadata": {}, 1209 | "outputs": [], 1210 | "source": [ 1211 | "# Here create the new vector" 1212 | ] 1213 | }, 1214 | { 1215 | "cell_type": "markdown", 1216 | "metadata": {}, 1217 | "source": [ 1218 | "use the **viter()** function, just to prove the iteration concept " 1219 | ] 1220 | }, 1221 | { 1222 | "cell_type": "code", 1223 | "execution_count": null, 1224 | "metadata": {}, 1225 | "outputs": [], 1226 | "source": [] 1227 | } 1228 | ], 1229 | "metadata": { 1230 | "kernelspec": { 1231 | "display_name": "Python 2", 1232 | "language": "python", 1233 | "name": "python2" 1234 | }, 1235 | "language_info": { 1236 | "codemirror_mode": { 1237 | "name": "ipython", 1238 | "version": 2 1239 | }, 1240 | "file_extension": ".py", 1241 | "mimetype": "text/x-python", 1242 | "name": "python", 1243 | "nbconvert_exporter": "python", 1244 | "pygments_lexer": "ipython2", 1245 | "version": "2.7.16" 1246 | } 1247 | }, 1248 | "nbformat": 4, 1249 | "nbformat_minor": 1 1250 | } 1251 | -------------------------------------------------------------------------------- /07_Raster_scripting.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "In this quick notebook we will use some functions of the scripting library to work with raster maps" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": {}, 14 | "outputs": [], 15 | "source": [ 16 | "from grass import script" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": null, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "MAP = 'elevation'\n", 26 | "POINT = [[640000, 228000]]" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "# Information" 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "Obtain information about the map" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": null, 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "eleinfo = script.raster_info(MAP)\n", 50 | "print(eleinfo)" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "Or query the map on a point" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": null, 63 | "metadata": {}, 64 | "outputs": [], 65 | "source": [ 66 | "script.raster_what(MAP, POINT)" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": {}, 72 | "source": [ 73 | "# Map algebra" 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "metadata": {}, 79 | "source": [ 80 | "We can execute any kind of *map algebra analysis* using an interface to r.mapcalc module" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": null, 86 | "metadata": {}, 87 | "outputs": [], 88 | "source": [ 89 | "script.mapcalc(\"elevation100 = if(elevation > 100, elevation, null())\", overwrite=True)" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": {}, 95 | "source": [ 96 | "Now check the result: the maximum should be the same of original map and the minimum should be 100" 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": null, 102 | "metadata": {}, 103 | "outputs": [], 104 | "source": [ 105 | "newinfo = script.raster_info(\"elevation100\")\n", 106 | "if eleinfo['max'] == newinfo['max'] and newinfo['min'] == 100:\n", 107 | " print(\"Succeded\")\n", 108 | "else:\n", 109 | " print(\"Failed\")" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "# Other modules" 117 | ] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": {}, 122 | "source": [ 123 | "Is it possible to run all the modules with the following functions" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": null, 129 | "metadata": {}, 130 | "outputs": [], 131 | "source": [ 132 | "from grass.pygrass.utils import looking\n", 133 | "\n", 134 | "looking(script, '*command*')" 135 | ] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "metadata": {}, 140 | "source": [ 141 | "**You can see some examples of these functions in the Modules notebook**.\n", 142 | "\n", 143 | "Read more about about these functions on the classes documentations or in the wiki page" 144 | ] 145 | } 146 | ], 147 | "metadata": { 148 | "kernelspec": { 149 | "display_name": "Python 2", 150 | "language": "python", 151 | "name": "python2" 152 | }, 153 | "language_info": { 154 | "codemirror_mode": { 155 | "name": "ipython", 156 | "version": 2 157 | }, 158 | "file_extension": ".py", 159 | "mimetype": "text/x-python", 160 | "name": "python", 161 | "nbconvert_exporter": "python", 162 | "pygments_lexer": "ipython2", 163 | "version": "2.7.16" 164 | } 165 | }, 166 | "nbformat": 4, 167 | "nbformat_minor": 1 168 | } 169 | -------------------------------------------------------------------------------- /08_Raster_pygrass.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Raster" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "The pygrass interface for raster maps is divided in 3 classes that represent different ways to interact with rasters. In order to give greater freedom of implementation to users and developers, each class\n", 15 | "uses a different C API, providing the tools to fit different needs. \n", 16 | "\n", 17 | "The **RasterRow** class reads the content of the raster row by row and writes it in a sequential mode: row after row.\n", 18 | "To read and write the same map at the same time is not supported by the RasterRow class.\n", 19 | "\n", 20 | "The **RasterRowIO** class implements a row cache that allows users to read and re-read raster rows randomly.\n", 21 | "\n", 22 | "The **RasterSegment** class divides the map into several tiles, each tile is saved into a file. With this class it is possible to read and write the pixel value randomly at the same time in the same map.\n", 23 | "\n", 24 | "All the Raster classes shared common methods to open, read and get raster information and write meta-data like: categories and history. Similarly to Vector class, the same syntax has been used to instantiate a raster object.\n" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": null, 30 | "metadata": {}, 31 | "outputs": [], 32 | "source": [ 33 | "from __future__ import (nested_scopes, generators, division, absolute_import,\n", 34 | " with_statement, print_function, unicode_literals)" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "## Read raster map" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "from grass.pygrass.raster import RasterRow" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": null, 56 | "metadata": {}, 57 | "outputs": [], 58 | "source": [ 59 | "elev = RasterRow('elevation')" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": null, 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [ 68 | "elev.exist()" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": null, 74 | "metadata": {}, 75 | "outputs": [], 76 | "source": [ 77 | "elev.mapset" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "### Open a raster map" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": null, 90 | "metadata": {}, 91 | "outputs": [], 92 | "source": [ 93 | "elev.open('r')" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": null, 99 | "metadata": {}, 100 | "outputs": [], 101 | "source": [ 102 | "elev[0]" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": null, 108 | "metadata": {}, 109 | "outputs": [], 110 | "source": [ 111 | "elev[0]/100." 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": null, 117 | "metadata": {}, 118 | "outputs": [], 119 | "source": [ 120 | "import numpy as np\n", 121 | "np.sin(elev[0])" 122 | ] 123 | }, 124 | { 125 | "cell_type": "markdown", 126 | "metadata": {}, 127 | "source": [ 128 | "### Query a raster using a Point object" 129 | ] 130 | }, 131 | { 132 | "cell_type": "markdown", 133 | "metadata": {}, 134 | "source": [ 135 | "Return Region object in Bbox format" 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": null, 141 | "metadata": {}, 142 | "outputs": [], 143 | "source": [ 144 | "from grass.pygrass.gis.region import Region\n", 145 | "reg = Region()\n", 146 | "reg_bbox = reg.get_bbox()\n", 147 | "print( reg_bbox)" 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": {}, 153 | "source": [ 154 | "Create two point object" 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "execution_count": null, 160 | "metadata": {}, 161 | "outputs": [], 162 | "source": [ 163 | "from grass.pygrass.vector import geometry\n", 164 | "poi1 = geometry.Point(643521.76, 223101.31)\n", 165 | "poi2 = geometry.Point(223101.31, 640000.76)" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": null, 171 | "metadata": {}, 172 | "outputs": [], 173 | "source": [ 174 | "print(elev.get_value(poi1))\n", 175 | "print(elev.get_value(poi2))" 176 | ] 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": {}, 181 | "source": [ 182 | "Check if contained in the region" 183 | ] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "execution_count": null, 188 | "metadata": {}, 189 | "outputs": [], 190 | "source": [ 191 | "print(reg_bbox.contains(poi1))\n", 192 | "print(reg_bbox.contains(poi2))" 193 | ] 194 | }, 195 | { 196 | "cell_type": "markdown", 197 | "metadata": {}, 198 | "source": [ 199 | "## Write a raster map" 200 | ] 201 | }, 202 | { 203 | "cell_type": "markdown", 204 | "metadata": {}, 205 | "source": [ 206 | "### Write a new raster map from existing one" 207 | ] 208 | }, 209 | { 210 | "cell_type": "markdown", 211 | "metadata": {}, 212 | "source": [ 213 | "Read the *elevation* map and write new map with value divided by 10" 214 | ] 215 | }, 216 | { 217 | "cell_type": "code", 218 | "execution_count": null, 219 | "metadata": {}, 220 | "outputs": [], 221 | "source": [ 222 | "new = RasterRow('newele')\n", 223 | "new.open('w', overwrite=True)\n", 224 | "for row in elev:\n", 225 | " # the row is a Buffer class to load it\n", 226 | " # grass.pygrass.raster.buffer.Buffer\n", 227 | " new.put_row(row/10)\n", 228 | "new.close()" 229 | ] 230 | }, 231 | { 232 | "cell_type": "markdown", 233 | "metadata": {}, 234 | "source": [ 235 | "Check if the new raster map exists" 236 | ] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "execution_count": null, 241 | "metadata": {}, 242 | "outputs": [], 243 | "source": [ 244 | "new.exist()" 245 | ] 246 | }, 247 | { 248 | "cell_type": "markdown", 249 | "metadata": {}, 250 | "source": [ 251 | "### Write a new raster map starting from scratch" 252 | ] 253 | }, 254 | { 255 | "cell_type": "markdown", 256 | "metadata": {}, 257 | "source": [ 258 | "To create a raster from scratch you have to create row using a **Buffer** istance, so you open new raster map in write mode" 259 | ] 260 | }, 261 | { 262 | "cell_type": "code", 263 | "execution_count": null, 264 | "metadata": {}, 265 | "outputs": [], 266 | "source": [ 267 | "from grass.pygrass.raster.buffer import Buffer\n", 268 | "\n", 269 | "# create the new raster and open it in write mode\n", 270 | "newscratch = RasterRow('newscratch')\n", 271 | "newscratch.open('w', overwrite=True)" 272 | ] 273 | }, 274 | { 275 | "cell_type": "markdown", 276 | "metadata": {}, 277 | "source": [ 278 | "now you are going to write cell by cell for each row" 279 | ] 280 | }, 281 | { 282 | "cell_type": "code", 283 | "execution_count": null, 284 | "metadata": {}, 285 | "outputs": [], 286 | "source": [ 287 | "# create an empty row\n", 288 | "newrow = Buffer((reg.cols,), mtype='CELL')\n", 289 | " \n", 290 | "# we create a raster to fill all the GRASS GIS region\n", 291 | "for r in range(reg.rows):\n", 292 | " newrow[:] = np.random.random_integers(0, 1000, size=newrow.size)\n", 293 | " # Add row to the raster\n", 294 | " newscratch.put_row(newrow)" 295 | ] 296 | }, 297 | { 298 | "cell_type": "markdown", 299 | "metadata": {}, 300 | "source": [ 301 | "Finally you have to close the map" 302 | ] 303 | }, 304 | { 305 | "cell_type": "code", 306 | "execution_count": null, 307 | "metadata": {}, 308 | "outputs": [], 309 | "source": [ 310 | "newscratch.close()" 311 | ] 312 | }, 313 | { 314 | "cell_type": "code", 315 | "execution_count": null, 316 | "metadata": {}, 317 | "outputs": [], 318 | "source": [ 319 | "from show import show" 320 | ] 321 | }, 322 | { 323 | "cell_type": "code", 324 | "execution_count": null, 325 | "metadata": {}, 326 | "outputs": [], 327 | "source": [ 328 | "show(newscratch.name.encode())" 329 | ] 330 | }, 331 | { 332 | "cell_type": "markdown", 333 | "metadata": {}, 334 | "source": [ 335 | "Check if the new map exist and the range of data" 336 | ] 337 | }, 338 | { 339 | "cell_type": "code", 340 | "execution_count": null, 341 | "metadata": {}, 342 | "outputs": [], 343 | "source": [ 344 | "newscratch = RasterRow('newscratch')\n", 345 | "newscratch.open('r')\n", 346 | "print(newscratch.exist())\n", 347 | "print(newscratch.info)\n", 348 | "newscratch.close()" 349 | ] 350 | }, 351 | { 352 | "cell_type": "markdown", 353 | "metadata": {}, 354 | "source": [ 355 | "# Object contained in a Raster map" 356 | ] 357 | }, 358 | { 359 | "cell_type": "markdown", 360 | "metadata": {}, 361 | "source": [ 362 | "## Info" 363 | ] 364 | }, 365 | { 366 | "cell_type": "markdown", 367 | "metadata": {}, 368 | "source": [ 369 | "The **Info** class contain all the information about a raster map" 370 | ] 371 | }, 372 | { 373 | "cell_type": "code", 374 | "execution_count": null, 375 | "metadata": {}, 376 | "outputs": [], 377 | "source": [ 378 | "elev.open('r')\n", 379 | "elev.info.mapset" 380 | ] 381 | }, 382 | { 383 | "cell_type": "code", 384 | "execution_count": null, 385 | "metadata": {}, 386 | "outputs": [], 387 | "source": [ 388 | "eleinfo = elev.info" 389 | ] 390 | }, 391 | { 392 | "cell_type": "markdown", 393 | "metadata": {}, 394 | "source": [ 395 | "Now you can obtain several informations" 396 | ] 397 | }, 398 | { 399 | "cell_type": "code", 400 | "execution_count": null, 401 | "metadata": {}, 402 | "outputs": [], 403 | "source": [ 404 | "print(eleinfo.range)\n", 405 | "print(eleinfo.mapset)\n", 406 | "print(eleinfo.south)" 407 | ] 408 | }, 409 | { 410 | "cell_type": "code", 411 | "execution_count": null, 412 | "metadata": {}, 413 | "outputs": [], 414 | "source": [ 415 | "eleinfo." 416 | ] 417 | }, 418 | { 419 | "cell_type": "markdown", 420 | "metadata": {}, 421 | "source": [ 422 | "## History" 423 | ] 424 | }, 425 | { 426 | "cell_type": "markdown", 427 | "metadata": {}, 428 | "source": [ 429 | "The **History** class contain the information about history of a map" 430 | ] 431 | }, 432 | { 433 | "cell_type": "code", 434 | "execution_count": null, 435 | "metadata": {}, 436 | "outputs": [], 437 | "source": [ 438 | "elev.open()\n", 439 | "elehisto = elev.hist" 440 | ] 441 | }, 442 | { 443 | "cell_type": "markdown", 444 | "metadata": {}, 445 | "source": [ 446 | "Now you can obtain several informations like creator, date of creation, keywords etc." 447 | ] 448 | }, 449 | { 450 | "cell_type": "code", 451 | "execution_count": null, 452 | "metadata": {}, 453 | "outputs": [], 454 | "source": [ 455 | "print(elehisto.creator)\n", 456 | "#print(elehisto.date)\n", 457 | "print(elehisto.keyword)" 458 | ] 459 | }, 460 | { 461 | "cell_type": "markdown", 462 | "metadata": {}, 463 | "source": [ 464 | "# Categories" 465 | ] 466 | }, 467 | { 468 | "cell_type": "markdown", 469 | "metadata": {}, 470 | "source": [ 471 | "The **Category** class contain the information about categories of raster, if they are present" 472 | ] 473 | }, 474 | { 475 | "cell_type": "code", 476 | "execution_count": null, 477 | "metadata": {}, 478 | "outputs": [], 479 | "source": [ 480 | "land = RasterRow('landuse')\n", 481 | "land.open()\n", 482 | "land.cats" 483 | ] 484 | }, 485 | { 486 | "cell_type": "markdown", 487 | "metadata": {}, 488 | "source": [ 489 | "Now you can obtain more information about categories" 490 | ] 491 | }, 492 | { 493 | "cell_type": "code", 494 | "execution_count": null, 495 | "metadata": {}, 496 | "outputs": [], 497 | "source": [ 498 | "landcats = land.cats\n", 499 | "print(landcats.labels())\n", 500 | "print(landcats.ncats())" 501 | ] 502 | }, 503 | { 504 | "cell_type": "markdown", 505 | "metadata": {}, 506 | "source": [ 507 | "You could also rewrite the cats using a rules files (for example newrules.txt) containg:" 508 | ] 509 | }, 510 | { 511 | "cell_type": "raw", 512 | "metadata": {}, 513 | "source": [ 514 | "0:undefined\n", 515 | "1:developed\n", 516 | "2:agri\n", 517 | "3:herba\n", 518 | "4:shru\n", 519 | "5:fore\n", 520 | "6:water\n", 521 | "7:sedi" 522 | ] 523 | }, 524 | { 525 | "cell_type": "code", 526 | "execution_count": null, 527 | "metadata": {}, 528 | "outputs": [], 529 | "source": [ 530 | "landcats.write_rules('newrules.txt')" 531 | ] 532 | }, 533 | { 534 | "cell_type": "markdown", 535 | "metadata": {}, 536 | "source": [ 537 | "# Summary" 538 | ] 539 | }, 540 | { 541 | "cell_type": "markdown", 542 | "metadata": {}, 543 | "source": [ 544 | "We saw how:\n", 545 | "\n", 546 | "* **read** and query a Raster\n", 547 | "* **write** a raster: reading from existing one and from the scratch\n", 548 | "* the **Info** element for information of a raster\n", 549 | "* the **History** element for history of a raster\n", 550 | "* the **Category** element for categories if they exist" 551 | ] 552 | }, 553 | { 554 | "cell_type": "markdown", 555 | "metadata": {}, 556 | "source": [ 557 | "# Exercise" 558 | ] 559 | }, 560 | { 561 | "cell_type": "markdown", 562 | "metadata": {}, 563 | "source": [ 564 | "## Exercise 1" 565 | ] 566 | }, 567 | { 568 | "cell_type": "markdown", 569 | "metadata": {}, 570 | "source": [ 571 | "Write a function that do the same operation of:\n", 572 | " \n", 573 | " r.mapcalc expression=\"new = if(elevation>100, elevation, 0)\"\n", 574 | "\n", 575 | "not using Modules class" 576 | ] 577 | }, 578 | { 579 | "cell_type": "code", 580 | "execution_count": null, 581 | "metadata": {}, 582 | "outputs": [], 583 | "source": [] 584 | }, 585 | { 586 | "cell_type": "markdown", 587 | "metadata": {}, 588 | "source": [ 589 | "## Exercise 2" 590 | ] 591 | }, 592 | { 593 | "cell_type": "markdown", 594 | "metadata": {}, 595 | "source": [ 596 | "Write a function that generate a random vector points map and query a raster map and add the value of the raster map to the attributes table of the vector map" 597 | ] 598 | }, 599 | { 600 | "cell_type": "code", 601 | "execution_count": null, 602 | "metadata": {}, 603 | "outputs": [], 604 | "source": [] 605 | } 606 | ], 607 | "metadata": { 608 | "kernelspec": { 609 | "display_name": "Python 2", 610 | "language": "python", 611 | "name": "python2" 612 | }, 613 | "language_info": { 614 | "codemirror_mode": { 615 | "name": "ipython", 616 | "version": 2 617 | }, 618 | "file_extension": ".py", 619 | "mimetype": "text/x-python", 620 | "name": "python", 621 | "nbconvert_exporter": "python", 622 | "pygments_lexer": "ipython2", 623 | "version": "2.7.16" 624 | } 625 | }, 626 | "nbformat": 4, 627 | "nbformat_minor": 1 628 | } 629 | -------------------------------------------------------------------------------- /09_Modules_pygrass_advance.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# pygrass Modules, advance usage" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "We already pygrass `Modules` module in the unit 02. Now we will see other modules to run `Modules` in different ways. " 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": null, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "from IPython.display import Image\n", 24 | "# pretty-print\n", 25 | "from pprint import pprint\n", 26 | "from subprocess import PIPE\n", 27 | "from multiprocessing import Process" 28 | ] 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "metadata": {}, 33 | "source": [ 34 | "## MultiModules, run several modules in serial" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "`MultiModules` is designed to run a list of modules in serial in the provided order within a temporary region environment. `Modules` can be run in serial synchronously or asynchronously." 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "from grass.pygrass.modules import Module\n", 51 | "from grass.pygrass.modules import MultiModule" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "Let's create to Modules objects and try to run them with `MultiModules`" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": null, 64 | "metadata": {}, 65 | "outputs": [], 66 | "source": [ 67 | "# we need to remember to use run_=False\n", 68 | "listvect = Module('g.list', type='vector', mapset='.', stdout_=PIPE, run_=False)\n", 69 | "listraster = Module('g.list', type='raster', mapset='.', stdout_=PIPE, run_=False)" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": null, 75 | "metadata": {}, 76 | "outputs": [], 77 | "source": [ 78 | "# we can i\n", 79 | "mm = MultiModule(module_list=[listvect, listraster])\n", 80 | "mm.run()" 81 | ] 82 | }, 83 | { 84 | "cell_type": "markdown", 85 | "metadata": {}, 86 | "source": [ 87 | "At this point you can see the output of the modules" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": null, 93 | "metadata": {}, 94 | "outputs": [], 95 | "source": [ 96 | "print(mm.module_list[0].outputs.stdout)" 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": null, 102 | "metadata": {}, 103 | "outputs": [], 104 | "source": [ 105 | "print(mm.module_list[1].outputs.stdout)" 106 | ] 107 | }, 108 | { 109 | "cell_type": "markdown", 110 | "metadata": {}, 111 | "source": [ 112 | "It is possible to get the help for `MultiModules`" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": null, 118 | "metadata": {}, 119 | "outputs": [], 120 | "source": [ 121 | "mm?" 122 | ] 123 | }, 124 | { 125 | "cell_type": "markdown", 126 | "metadata": {}, 127 | "source": [ 128 | "It is possible to test the asynchronous mode.\n", 129 | "You can test it running several map algebra with `r.mapcalc` module. First set the right Region and get info about the raster" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": null, 135 | "metadata": {}, 136 | "outputs": [], 137 | "source": [ 138 | "print(Module('g.region', raster='elevation@PERMANENT', flags='p', stdout_=PIPE).outputs.stdout)\n", 139 | "print(Module('r.info', map='elevation@PERMANENT', flags='r', stdout_=PIPE).outputs.stdout)" 140 | ] 141 | }, 142 | { 143 | "cell_type": "markdown", 144 | "metadata": {}, 145 | "source": [ 146 | "Now it is possible to create a list of `r.mapcalc` `Modules` objects. " 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": null, 152 | "metadata": {}, 153 | "outputs": [], 154 | "source": [ 155 | "listmapcalc = []\n", 156 | "val = 0\n", 157 | "while val < 200:\n", 158 | " listmapcalc.append(Module(\"r.mapcalc\",\n", 159 | " expression=\"elevation_{va}=if(elevation@PERMANENT>{va} && elevation@PERMANENT<={va2}, elevation@PERMANENT, null())\".format(va=val, va2=val+50),\n", 160 | " overwrite=True, run_=False, finish_=False)\n", 161 | " )\n", 162 | " val += 50\n" 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": null, 168 | "metadata": {}, 169 | "outputs": [], 170 | "source": [ 171 | "listmapcalc[-1].get_bash()" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "At this point create the `MultiModules` object in asynchronous mode and run it." 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": null, 184 | "metadata": {}, 185 | "outputs": [], 186 | "source": [ 187 | "mm = MultiModule(module_list=listmapcalc, sync=False)\n", 188 | "pro = mm.run()\n", 189 | "isinstance(pro, Process)" 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "execution_count": null, 195 | "metadata": {}, 196 | "outputs": [], 197 | "source": [ 198 | "mapcalc_list = mm.wait()\n", 199 | "for mapcalc in mapcalc_list:\n", 200 | " print(mapcalc.popen.returncode)\n", 201 | "print(Module('g.list', type='raster', pattern='elevation*', stdout_=PIPE).outputs.stdout)" 202 | ] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": {}, 207 | "source": [ 208 | "## GridModules, run a single process in multiprocessing" 209 | ] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "metadata": {}, 214 | "source": [ 215 | "`GridModules` provide a simple Module to run a GRASS process and split analysis between several processes. " 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": null, 221 | "metadata": {}, 222 | "outputs": [], 223 | "source": [ 224 | "from grass.pygrass.modules.grid.grid import GridModule" 225 | ] 226 | }, 227 | { 228 | "cell_type": "code", 229 | "execution_count": null, 230 | "metadata": {}, 231 | "outputs": [], 232 | "source": [ 233 | "# create GridModule object and get the different works\n", 234 | "grd = GridModule('r.slope.aspect',\n", 235 | " width=1000, height=1000, overlap=2,\n", 236 | " processes=None, split=False,\n", 237 | " elevation='elevation@PERMANENT',\n", 238 | " slope='slope_grid', aspect='aspect_grid', overwrite=True)\n", 239 | "grd.get_works()" 240 | ] 241 | }, 242 | { 243 | "cell_type": "markdown", 244 | "metadata": {}, 245 | "source": [ 246 | "At this point run it and check if the maps are created..." 247 | ] 248 | }, 249 | { 250 | "cell_type": "code", 251 | "execution_count": null, 252 | "metadata": {}, 253 | "outputs": [], 254 | "source": [ 255 | "grd.run()" 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": null, 261 | "metadata": {}, 262 | "outputs": [], 263 | "source": [ 264 | "print(Module('g.list', type='raster', mapset='.', stdout_=PIPE, pattern=\"*_grid\").outputs.stdout)" 265 | ] 266 | }, 267 | { 268 | "cell_type": "markdown", 269 | "metadata": {}, 270 | "source": [ 271 | "# Summary" 272 | ] 273 | }, 274 | { 275 | "cell_type": "markdown", 276 | "metadata": {}, 277 | "source": [ 278 | "We have seen\n", 279 | "\n", 280 | "* how to run several command in serial mode\n", 281 | "* how to run a command splitting its calculation in several process. \n", 282 | " **Pay attention because for several analysis this is no possible**" 283 | ] 284 | }, 285 | { 286 | "cell_type": "markdown", 287 | "metadata": {}, 288 | "source": [ 289 | "# Exercise" 290 | ] 291 | }, 292 | { 293 | "cell_type": "markdown", 294 | "metadata": {}, 295 | "source": [ 296 | "## Exercise 1" 297 | ] 298 | }, 299 | { 300 | "cell_type": "markdown", 301 | "metadata": { 302 | "collapsed": true 303 | }, 304 | "source": [ 305 | "Computes the viewshed for ten point on the `elevation` raster map inside the computational region" 306 | ] 307 | }, 308 | { 309 | "cell_type": "code", 310 | "execution_count": null, 311 | "metadata": {}, 312 | "outputs": [], 313 | "source": [] 314 | }, 315 | { 316 | "cell_type": "markdown", 317 | "metadata": { 318 | "collapsed": true 319 | }, 320 | "source": [ 321 | "## Exercise 2" 322 | ] 323 | }, 324 | { 325 | "cell_type": "markdown", 326 | "metadata": {}, 327 | "source": [ 328 | "Run `r.geomorphon` as single process with `Module` and using `GridModule` and check if the results are the same" 329 | ] 330 | }, 331 | { 332 | "cell_type": "code", 333 | "execution_count": null, 334 | "metadata": {}, 335 | "outputs": [], 336 | "source": [] 337 | } 338 | ], 339 | "metadata": { 340 | "kernelspec": { 341 | "display_name": "Python 2", 342 | "language": "python", 343 | "name": "python2" 344 | }, 345 | "language_info": { 346 | "codemirror_mode": { 347 | "name": "ipython", 348 | "version": 2 349 | }, 350 | "file_extension": ".py", 351 | "mimetype": "text/x-python", 352 | "name": "python", 353 | "nbconvert_exporter": "python", 354 | "pygments_lexer": "ipython2", 355 | "version": "2.7.16" 356 | } 357 | }, 358 | "nbformat": 4, 359 | "nbformat_minor": 2 360 | } 361 | -------------------------------------------------------------------------------- /10_Modules_pygrass_parallel.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# How to run pygrass `Modules` in parallel" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "It is possible to run `Modules` object in parallel. There are more ways, in this documents there are two of them.\n", 15 | "\n", 16 | "* using `subprocess` module\n", 17 | "* using `ParallelModuleQueue` pygrass modules" 18 | ] 19 | }, 20 | { 21 | "cell_type": "markdown", 22 | "metadata": {}, 23 | "source": [ 24 | "## subprocess" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "`subprocess` is the Python module to spawn new processes, connect to their input/output/error pipes, and obtain their return codes." 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": null, 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "from multiprocessing import Queue, Process\n", 41 | "import grass.script as grass" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "First it is required to create a function with the analysis needed, in this case create a buffer around the input vector map." 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": null, 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [ 57 | "def calculate(inp, dist):\n", 58 | " # function to create a buffer\n", 59 | " out = \"{ip}_buffer_{di}\".format(ip=inp, di=dist)\n", 60 | " grass.run_command(\"v.buffer\", input=inp, output=out, distance=dist, overwrite=True, quiet=True)\n", 61 | " return out" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": null, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [ 70 | "def spawn(func):\n", 71 | " def funct(q_in, q_out):\n", 72 | " while True:\n", 73 | " vec, dis = q_in.get()\n", 74 | " if vec is None:\n", 75 | " break\n", 76 | " q_out.put(func(vec, dis))\n", 77 | " return funct" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "Now create the needed input" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": null, 90 | "metadata": {}, 91 | "outputs": [], 92 | "source": [ 93 | "# two queue object, one for input and output\n", 94 | "q_in = Queue(1)\n", 95 | "q_out = Queue()\n", 96 | "# number of process to create\n", 97 | "nproc = 3\n", 98 | "# input vector and distances\n", 99 | "invect = \"schools\"\n", 100 | "inbuffer = range(0,220,20)" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": null, 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [ 109 | "Queue?" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "Create a list of process according to `nproc` variable, the target is the `spawn` function with `calculate` as variable for `spawn`" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": null, 122 | "metadata": {}, 123 | "outputs": [], 124 | "source": [ 125 | "procs = [Process(target=spawn(calculate), args=(q_in, q_out)) for _ in range(nproc)]" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": null, 131 | "metadata": {}, 132 | "outputs": [], 133 | "source": [ 134 | "Process?" 135 | ] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "metadata": {}, 140 | "source": [ 141 | "For each process set it as daemon and start the process" 142 | ] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "execution_count": null, 147 | "metadata": {}, 148 | "outputs": [], 149 | "source": [ 150 | "for proc in procs:\n", 151 | " proc.daemon = True\n", 152 | " proc.start()" 153 | ] 154 | }, 155 | { 156 | "cell_type": "markdown", 157 | "metadata": {}, 158 | "source": [ 159 | "Set the inputs (vector map and distance)" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": null, 165 | "metadata": {}, 166 | "outputs": [], 167 | "source": [ 168 | "ans = [q_in.put((invect, i)) for i in inbuffer if i > 0]" 169 | ] 170 | }, 171 | { 172 | "cell_type": "markdown", 173 | "metadata": {}, 174 | "source": [ 175 | "Set `None` to each processes to terminate them" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": null, 181 | "metadata": { 182 | "scrolled": true 183 | }, 184 | "outputs": [], 185 | "source": [ 186 | "[q_in.put((None, None)) for proc in procs]" 187 | ] 188 | }, 189 | { 190 | "cell_type": "markdown", 191 | "metadata": {}, 192 | "source": [ 193 | "At this point check if the processes run correctly and if the maps are created" 194 | ] 195 | }, 196 | { 197 | "cell_type": "code", 198 | "execution_count": null, 199 | "metadata": { 200 | "scrolled": true 201 | }, 202 | "outputs": [], 203 | "source": [ 204 | "[proc.join() for proc in procs]\n", 205 | "processed = [q_out.get() for _ in ans]\n", 206 | "if len(processed) != len(inbuffer) - 1:\n", 207 | " print(\"An error occurs\")\n", 208 | "print(grass.read_command('g.list', type=\"vector\", pattern=\"schools_buffer*\", mapset='.'))" 209 | ] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "metadata": {}, 214 | "source": [ 215 | "## ParallelModuleQueue" 216 | ] 217 | }, 218 | { 219 | "cell_type": "markdown", 220 | "metadata": {}, 221 | "source": [ 222 | "The `ParallelModuleQueue` is designed to run an arbitrary number of pygrass Module or MultiModule processes in parallel. " 223 | ] 224 | }, 225 | { 226 | "cell_type": "code", 227 | "execution_count": null, 228 | "metadata": {}, 229 | "outputs": [], 230 | "source": [ 231 | "from grass.pygrass.modules import Module, ParallelModuleQueue" 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": null, 237 | "metadata": {}, 238 | "outputs": [], 239 | "source": [ 240 | "ParallelModuleQueue?" 241 | ] 242 | }, 243 | { 244 | "cell_type": "markdown", 245 | "metadata": {}, 246 | "source": [ 247 | "Initialize the `ParallelModuleQueue` object" 248 | ] 249 | }, 250 | { 251 | "cell_type": "code", 252 | "execution_count": null, 253 | "metadata": {}, 254 | "outputs": [], 255 | "source": [ 256 | "queue = ParallelModuleQueue(nprocs=nproc)" 257 | ] 258 | }, 259 | { 260 | "cell_type": "markdown", 261 | "metadata": {}, 262 | "source": [ 263 | "Put the `Modules` objects inside the `queue` and wait until the finish" 264 | ] 265 | }, 266 | { 267 | "cell_type": "code", 268 | "execution_count": null, 269 | "metadata": {}, 270 | "outputs": [], 271 | "source": [ 272 | "val = 0\n", 273 | "while val < 200:\n", 274 | " queue.put(Module(\"r.mapcalc\",\n", 275 | " expression=\"elevation_{va}=if(elevation@PERMANENT>{va} && elevation@PERMANENT<={va2}, elevation@PERMANENT, null())\".format(va=val, va2=val+50),\n", 276 | " overwrite=True, run_=False, finish_=False)\n", 277 | " )\n", 278 | " val += 50\n", 279 | "queue.wait()" 280 | ] 281 | }, 282 | { 283 | "cell_type": "markdown", 284 | "metadata": {}, 285 | "source": [ 286 | "Check how the processes terminate" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": null, 292 | "metadata": {}, 293 | "outputs": [], 294 | "source": [ 295 | "print(\"Number of running process \".format(queue.get_num_run_procs()))\n", 296 | "print(\"Number of max number of process \".format(queue.get_max_num_procs()))" 297 | ] 298 | }, 299 | { 300 | "cell_type": "code", 301 | "execution_count": null, 302 | "metadata": {}, 303 | "outputs": [], 304 | "source": [ 305 | "for mapcalc in queue.get_finished_modules():\n", 306 | " print(mapcalc.popen.returncode)" 307 | ] 308 | }, 309 | { 310 | "cell_type": "markdown", 311 | "metadata": {}, 312 | "source": [ 313 | "# Summary" 314 | ] 315 | }, 316 | { 317 | "cell_type": "markdown", 318 | "metadata": { 319 | "collapsed": true 320 | }, 321 | "source": [ 322 | "We have seen\n", 323 | "\n", 324 | "* how to run GRASS modules using the standard library `subprocess` module\n", 325 | "* how to use `ParallelModuleQueue` pygrass module" 326 | ] 327 | }, 328 | { 329 | "cell_type": "markdown", 330 | "metadata": {}, 331 | "source": [ 332 | "# Exercise" 333 | ] 334 | }, 335 | { 336 | "cell_type": "code", 337 | "execution_count": null, 338 | "metadata": {}, 339 | "outputs": [], 340 | "source": [] 341 | } 342 | ], 343 | "metadata": { 344 | "kernelspec": { 345 | "display_name": "Python 2", 346 | "language": "python", 347 | "name": "python2" 348 | }, 349 | "language_info": { 350 | "codemirror_mode": { 351 | "name": "ipython", 352 | "version": 2 353 | }, 354 | "file_extension": ".py", 355 | "mimetype": "text/x-python", 356 | "name": "python", 357 | "nbconvert_exporter": "python", 358 | "pygments_lexer": "ipython2", 359 | "version": "2.7.16" 360 | } 361 | }, 362 | "nbformat": 4, 363 | "nbformat_minor": 2 364 | } 365 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | workshop-pygrass 2 | ================ 3 | 4 | Workshop on pygrass for GRASS GIS 7 using IPython notebook. 5 | 6 | You need to install iPython and iPython notebook. 7 | 8 | How to start 9 | ============= 10 | 11 | Launch GRASS GIS 7 using the demolocation *nc_basic_spm_grass7* downloadable from here http://grass.osgeo.org/sampledata/north_carolina/nc_basic_spm_grass7.tar.gz 12 | 13 | Now move inside the direcotry of pygrass workshop and launch *ipython notebook --pylab inline*. 14 | 15 | Enjoy the tutorial!! 16 | 17 | Authors 18 | ========= 19 | 20 | * Pietro Zambelli (original author) 21 | * Luca Delucchi 22 | 23 | License 24 | ========= 25 | 26 | This material is released under Creative Commons Attribution-ShareAlike 4.0 https://creativecommons.org/licenses/by-sa/4.0/ 27 | -------------------------------------------------------------------------------- /images/command_help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zarch/workshop-pygrass/d183b7fb593623f23678bb597547a7b4378e2be5/images/command_help.png -------------------------------------------------------------------------------- /images/command_structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zarch/workshop-pygrass/d183b7fb593623f23678bb597547a7b4378e2be5/images/command_structure.png -------------------------------------------------------------------------------- /images/command_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zarch/workshop-pygrass/d183b7fb593623f23678bb597547a7b4378e2be5/images/command_window.png -------------------------------------------------------------------------------- /images/grass_database.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zarch/workshop-pygrass/d183b7fb593623f23678bb597547a7b4378e2be5/images/grass_database.png -------------------------------------------------------------------------------- /images/grass_start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zarch/workshop-pygrass/d183b7fb593623f23678bb597547a7b4378e2be5/images/grass_start.png -------------------------------------------------------------------------------- /images/help_loc_struct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zarch/workshop-pygrass/d183b7fb593623f23678bb597547a7b4378e2be5/images/help_loc_struct.png -------------------------------------------------------------------------------- /notebooks.md: -------------------------------------------------------------------------------- 1 | ## Notebooks 2 | 3 | * [00_Modules](http://nbviewer.ipython.org/github/epifanio/workshop-pygrass/blob/master/00_Modules.ipynb) 4 | 5 | * [01_GIS_objects](http://nbviewer.ipython.org/github/epifanio/workshop-pygrass/blob/master/01_GIS_objects.ipynb) 6 | 7 | * [02_Vector](http://nbviewer.ipython.org/github/epifanio/workshop-pygrass/blob/master/02_Vector.ipynb) 8 | 9 | * [03_Raster](http://nbviewer.ipython.org/github/epifanio/workshop-pygrass/blob/master/03_Raster.ipynb) 10 | 11 | 12 | -------------------------------------------------------------------------------- /show.py: -------------------------------------------------------------------------------- 1 | # define a funcion to show raster map 2 | from IPython.core.display import Image 3 | from grass.pygrass.modules.shortcuts import display 4 | 5 | 6 | def show(mapname, type='rast', start='png', output='view.png', 7 | select=None, width=None, height=None, resolution=None, bgcolor=None, 8 | overwrite=True, *args, **kwargs): 9 | """Return an instance of IPython Image. 10 | 11 | Parameters 12 | ----------- 13 | 14 | mapname : Nname of the map. 15 | type: map type ('rast', 'vect') 16 | 17 | start, output, select, width, height, resolution, bgcolor, overwrite 18 | are parameters of d.mon module. 19 | *args and **kwargs are parameters of d.rast or d.vect depend from the type. 20 | """ 21 | display.mon(start=start, output=output, select=select, 22 | width=width, height=height, resolution=resolution, 23 | bgcolor=bgcolor, overwrite=overwrite) 24 | getattr(display, type)(map=mapname, *args, **kwargs) 25 | display.mon(stop=start) 26 | return Image(filename=output) 27 | 28 | -------------------------------------------------------------------------------- /solutions/00_modules.py: -------------------------------------------------------------------------------- 1 | # 2 | # Exercise 1 3 | # 4 | g.region(rast='elevation') 5 | v.to_rast(input='streets', type='line', output='streets', use='cat', overwrite=True) 6 | r.mapcalc(expression="dist_cost=10./cos(slope)", overwrite=True) 7 | r.cost(input='dist_cost', output='distance_from_streets', outdir='direction', start_rast='streets', overwrite=True, flags=['k']) 8 | 9 | # 10 | # Exercise 2 11 | # 12 | from grass.pygrass.modules import general as g 13 | import subprocess as sub 14 | gregion = g.region 15 | 16 | 17 | def get_region(): 18 | gregion(flags='p', stdout_=sub.PIPE) 19 | reg = {} 20 | for row in gregion.outputs.stdout.splitlines(): 21 | key, value = row.split(':') 22 | reg[key.strip()] = value.strip() 23 | return reg 24 | 25 | get_region() 26 | -------------------------------------------------------------------------------- /solutions/02_vector.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from grass.pygrass.vector import VectorTopo 3 | # import the random function 4 | import random 5 | 6 | # import the Point and Region functions? 7 | from grass.pygrass.vector.geometry import Point 8 | from grass.pygrass.gis.region import Region 9 | 10 | # define a function to produce random points 11 | def get_random_points(num): 12 | # inside current GRASS' region of course 13 | reg = Region() 14 | # loop over a series of numbers from 0 up to... 15 | for _ in xrange(0, num): 16 | # use the function randrange() to get both x and y random numbers 17 | x = random.randrange(reg.south, reg.north) 18 | y = random.randrange(reg.west, reg.east) 19 | # at the end of each loop we need to explicitly catch the pairs of x and y numbers 20 | # in order to produce a point 21 | yield Point(x, y) 22 | 23 | 24 | def rand_vect_points(name, npoints=10, overwrite=True): 25 | new = VectorTopo(name) 26 | new.open('w', overwrite=overwrite) 27 | for pnt in get_random_points(npoints): 28 | new.write(pnt) 29 | new.close() 30 | return new 31 | -------------------------------------------------------------------------------- /solutions/03_raster.py: -------------------------------------------------------------------------------- 1 | # 2 | # Exercise 1 3 | # 4 | elev.open() 5 | new = RasterRow('new') 6 | new.open('w', overwrite=True) 7 | for row in elev: 8 | new.put_row(row * (row > 100)) 9 | new.close() --------------------------------------------------------------------------------