Unit 12 - Script User Interface

Standard input

There is one problem with our script from Unit 11 - PyGRASS scripting. Some modules (r.recode, r.colors) uses hardcoded paths to input files. This will not work when running script on different computer as we know. See code below (concretely rules options).

Module("r.recode",
       overwrite = True,
       input = "ndvi",
       output = "ndvi_class",
       rules = "/opt/grass-gis-irsae-winter-course-2018/_static/models/reclass.txt")

Module("r.colors",
       map = "ndvi_class",
       rules = "/opt/grass-gis-irsae-winter-course-2018/_static/models/colors.txt")

By PyGRASS a content of input file can be defined as a string object and transfered to the command via standard input (see stdin_, see sample code below.

Module("r.recode",
       overwrite = True,
       input = "ndvi",
       output = "ndvi_class",
       rules = "-",
       stdin_ = "-1:0.1:1\n0.1:0.5:2\n0.5:1:3")

Module(r.colors",
       map = "ndvi_class",
       rules = "-",
       stdin_ = "1 grey\n2 255 255 0\n3 green")

Note that most of GRASS modules allows sending data via standard input by option value - (dash). Here both commands with rules=- option.

We can also define cleanup routine which removes intermediate data by g.remove when compution is finished.

def cleanup():
    Module('g.remove', flags='f', name='region_mask', type='vector')

User interface (UI)

The script lacks user input, all input paramaters are hardcoded. We have to modify our script similarly as we did for model Unit 09 by its parameterization. Remember a first modification of script generated by Graphical Modeler in Unit 11 - PyGRASS scripting.

At first add previously removed lines back to the script.

#%module
#% description: NDVI model version 2
#%end

With these lines included a magic will happen, a standardized GUI dialog appears. Since only module description was defined and no parameters, the dialog offers only global flags like –verbose or –quiet.

../_images/ndvi-dialog.png

Fig. 82 Generated GUI dialog.

Let’s define parameters below:

  • region: vector map defining a computation region (required)
  • clouds: vector map with cloud mask features (optional)
  • red: input red channel (required)
  • nir: input nir channel (required)
  • threshold: threshold for removing small areas (optional)
  • basename: basename for output maps (required)

Related lines can look like as below.

#%option G_OPT_V_INPUT
#% key: region
#% description: Name of input vector region map 
#%end
#%option G_OPT_V_INPUT
#% key: clouds
#% description: Name of input vector clouds map 
#% required: no
#%end
#%option G_OPT_R_INPUT
#% key: red
#% description: Name of input red channel
#%end
#%option G_OPT_R_INPUT
#% key: nir
#% description: Name of input NIR channel
#%end
#%option
#% key: threshold
#% description: Threshold for removing small areas
#% answer: 1600
#%end
#%option G_OPT_V_OUTPUT
#%end
../_images/ndvi-dialog-params.png

Fig. 83 GUI dialog with input options.

In the script input parameters are still hardcoded, eg.

Module("v.overlay",
       overwrite = True,
       ainput = "oslo@PERMANENT",
       binput = "MaskFeature@PERMANENT",
       operator = "not",
       output = "region_mask")

The input parameters are accesible by options and flags objects which are generated by parse() function.

options, flags = parser()

Options and flags are dictionaries, where parameters are accessible by option keys, see example below.

Module("v.overlay",
       overwrite = True,
       ainput = options["region"],
       binput = options["clouds"],
       operator = "not",
       output = "region_mask")

The clouds option is not mandatory, so we will perform v.overlay module only when this option is given.

    if options["clouds"]:
        region_mask = "region_mask"
        Module("v.overlay",
               overwrite = True,
               ainput = "oslo@PERMANENT",
               alayer = "1",
               atype = "auto",
               binput = "MaskFeature@PERMANENT",
               blayer = "1",
               btype = "area",
               operator = "not",
               output = "region_mask",
               olayer = "1,0,0",
               snap = 1e-8)
    else:
        region_mask = options["region"]

    Module("g.region",
           overwrite = True,
           vector = region_mask,
           align = options["red"])

All other generated maps will be removed when computation finished.

def cleanup():
    Module('g.remove', flags='f', name='region_mask', type='vector')
    Module('g.remove', flags='f', name='ndvi', type='raster')
    Module('g.remove', flags='f', name='ndvi_class', type='raster')
    Module('g.remove', flags='f', name='ndvi_class', type='vector')
../_images/call-ndvi-script.png

Fig. 84 Improved NDVI script in action.

Sample script to download: ndvi-v3.py