Introduction
GRASS GIS is a very versatile and powerful Geographic Information System. And it is Open Source. In this post you will learn how to call GRASS functions from a python module without actually starting GRASS.
GRASSDATA, location and mapset
One of the defining features of GRASS GIS is how spatial data is organized at three hierarchical levels:
- GRASSDATA,
- Location,
- MapSet
GRASSDATA is the root directory under which all GRASS related spatial data is stored. A Location is defined by a projection and a region, and thus each regional dataset you work with must be defined as a Location. As a region can be global, the GRASSDATA Location used for external calls need only define the projection; the region (map extent) will be defined with each external call. All actual data belonging to a Location is related to a MapSet, where the default MapSet is called PERMANENT. While GRASSDATA and Location must exist beforehand when calling GRASS from an external Python module, the MapSet can be created and changed on the fly.
Setting up GRASS for external calls
Before calling GRASS you must setup GRASSDATA and a Location. To use GRASS as part of Karttur’s GeoImagine Framework you must setup a Location for the projection system(s) you use (e.g. modis, ease2n, ease2t etc). This section illustrates how to setup GRASS for using the EASE-grid north (ease2n) projection system. The installation of GRASS is covered in another post.
Start GRASS
Start GRASS and wait for the Startup window.
GRASSDATA and Location
Click the button for
, and create a new folder called GRASSDATA (it can be called something else, but most users call it GRASSDATA). Then define a Location name and a description. The location name must be identical to the projection system you intend to use with Karttur´s GeoImagine Framework.Define Location
Click
to set the Location projection:Again click
to see the summary of your new location:Start and finish
When you click
in the window with the Location Summary, GRASS Graphical User Interface (GUI) should start. As this Location will be used for external calls you are done and can can Quit GRASS.Install grass.script
All the manuals start with importing grass.script, but not a single page explains how to install grass.script itself. A reference to a GitHub repo is broken.
Trial 1 pip install grass-session
The first trial to get this up and running is to install the package
$ $ conda activate geoimagine_date_pyversion
Then pip-install grass-session:
$ pip install grass-session
Trial 2 - Link GRASS python via Eclipse
In Eclipse you can add the folders with the GRASS builtin Python scripts to your environment (see the GRASSwiki Using Eclipse to develop GRASS Python programs for more details and other operating systems). Go via the preferences menu to open the Python interpreter of your project (see figure below):
In the lower of the two sub-windows in the Preferences window, click on the Libraries button.
For macOS add the following folder:
/Applications/GRASS-7.8.app/Resources/MacOS/lib
/Applications/GRASS-7.8.app/Resources/MacOS/etc
/Applications/GRASS-7.8.app/Resources/MacOS/bin
/Applications/GRASS-7.8.app/Resources/MacOS/etc/python
For other Operating system, please see the [GRASSwiki Using Eclipse to develop GRASS Python programs.
Finish the isntallation by
.Set up the GRASS environment
Before you can call the GRASS commands from Python you need to define GRASS environmental variables. The easiest way to achieve that is to start a GRASS session with the GRASSDATA and Location that you defined above. Thus start <spanclas=’app’>GRASS</span> and go to the Terminal prompt and export all the variables:
> export
GRASS 7.8.3 (ease2n):~ > export
export GDAL_DATA="/Applications/GRASS-7.8.app/Contents/Resources/share/gdal"
export GISBASE="/Applications/GRASS-7.8.app/Contents/Resources"
export GISBASE_SYSTEM="/Library/GRASS/7.8"
export GISBASE_USER="/Users/thomasgumbricht/Library/GRASS/7.8"
export GISRC="/tmp/grass7-thomasgumbricht-61909/gisrc"
export GIS_LOCK="61909"
export GRASS_ADDON_BASE="/Users/thomasgumbricht/Library/GRASS/7.8/Modules"
export GRASS_ADDON_ETC="/Users/thomasgumbricht/Library/GRASS/7.8/Modules/etc:/Library/GRASS/7.8/Modules/etc"
export GRASS_FONT_CAP="/Users/thomasgumbricht/Library/GRASS/7.8/Modules/etc/fontcap"
export GRASS_GNUPLOT="gnuplot -persist"
export GRASS_HTML_BROWSER="/Applications/GRASS-7.8.app/Contents/Resources/etc/html_browser_mac.sh"
export GRASS_HTML_BROWSER_MACOSX="-b com.apple.helpviewer"
export GRASS_OS_STARTUP="Mac.app"
export GRASS_PAGER="more"
export GRASS_PROJSHARE="/Applications/GRASS-7.8.app/Contents/Resources/share/proj"
export GRASS_PYTHON="/Applications/GRASS-7.8.app/Contents/Resources/bin/pythonw"
export GRASS_PYTHONWX="/Applications/GRASS-7.8.app/Contents/Resources/bin/pythonw"
export GRASS_VERSION="7.8.3"
export HOME="/Users/thomasgumbricht"
export LD_RUN_PATH="/Applications/GRASS-7.8.app/Contents/Resources/lib"
export MANPATH="/Applications/GRASS-7.8.app/Contents/Resources/docs/man:/Users/thomasgumbricht/Library/GRASS/7.8/Modules/docs/man:/Applications/GRASS-7.8.app/Contents/Resources/share/man:/usr/share/man:/usr/local/share/man:/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/share/man:/Library/Developer/CommandLineTools/usr/share/man"
export OLDPWD
export PATH="/Applications/GRASS-7.8.app/Contents/Resources/bin:/Applications/GRASS-7.8.app/Contents/Resources/scripts:/Users/thomasgumbricht/Library/GRASS/7.8/Modules/bin:/Users/thomasgumbricht/Library/GRASS/7.8/Modules/scripts:/usr/bin:/bin:/usr/sbin:/etc:/usr/lib"
export PS1="GRASS 7.8.3 (ease2n):\\w > "
export PWD="/Users/thomasgumbricht"
export PYTHONEXECUTABLE="/Applications/GRASS-7.8.app/Contents/Resources/bin/python"
export PYTHONPATH="/Applications/GRASS-7.8.app/Contents/Resources/etc/python"
export SHELL="sh"
export SHLVL="3"
export TMPDIR="/tmp/grass7-thomasgumbricht-61909"
export _="/Applications/GRASS-7.8.app/Contents/Resources/python.app/Contents/MacOS/python"
Environment settings
To get GRASS to work from Python you must alter some Operating System Environment parameters. I think (but am not sure) that you can do this either using softcoding on the fly, or hardcoding at startup. I opted for doing a soft coding in the __init__.py module that initiated the grass package in Karttur´s GeoImagine Framework.
"""
Created 4 Apr 2021
GRASS
==========================================
Package belonging to Karttur´s GeoImagine Framework.
Author
------
Thomas Gumbricht (thomas.gumbricht@karttur.com)
"""
import os
import sys
from .version import __version__, VERSION, metadataD
os.environ['GRASSBIN']=r"/Applications/GRASS-7.8.app/Contents/MacOS/Grass"
os.environ['GISBASE'] = "/Applications/GRASS-7.8.app/Contents/Resources"
os.environ['GISRC']="/tmp/grass7-thomasgumbricht-61909/gisrc"
os.environ['PATH'] = "/Applications/GRASS-7.8.app/Contents/Resources/bin:/Applications/GRASS-7.8.app/Contents/Resources/scripts:/Users/thomasgumbricht/Library/GRASS/7.8/Modules/bin:/Users/thomasgumbricht/Library/GRASS/7.8/Modules/scripts:/usr/bin:/bin:/usr/sbin:/etc:/usr/lib"
os.environ['PYTHONPATH']="/Applications/GRASS-7.8.app/Contents/Resources/etc/python"
sys.path.append("/Applications/GRASS-7.8.app/Contents/Resources/etc/python")
from .grass02 import ProcessGRASS
I think that you can alternatively for instance set the environment using Eclipse
Resources
GRASS wiki Using Eclipse to develop GRASS Python programs
Working with GRASS without starting it explicitly
GRASS Python Scripting Library
GRASS 7 environment setup for Python
Stackexchange
Connecting Python script external to Grass GIS 7 program in Windows 10?