diff --git a/general/g.region/Makefile b/general/g.region/Makefile index a288c856113..9d6c871c9f4 100644 --- a/general/g.region/Makefile +++ b/general/g.region/Makefile @@ -2,7 +2,7 @@ MODULE_TOPDIR = ../.. PGM = g.region -LIBES = $(GPROJLIB) $(VECTORLIB) $(DIG2LIB) $(RASTER3DLIB) $(RASTERLIB) $(GISLIB) $(MATHLIB) $(PROJLIB) +LIBES = $(GPROJLIB) $(VECTORLIB) $(DIG2LIB) $(RASTER3DLIB) $(RASTERLIB) $(GISLIB) $(MATHLIB) $(PROJLIB) $(PARSONLIB) DEPENDENCIES = $(GPROJDEP) $(VECTORDEP) $(DIG2DEP) $(RASTER3DDEP) $(RASTERDEP) $(GISDEP) EXTRA_INC = $(VECT_INC) $(PROJINC) EXTRA_CFLAGS = $(VECT_CFLAGS) diff --git a/general/g.region/g.region.html b/general/g.region/g.region.html index 4716aee2e38..85d75a058df 100644 --- a/general/g.region/g.region.html +++ b/general/g.region/g.region.html @@ -457,6 +457,59 @@

Using g.region in a shell in combination with GDAL

Here the input raster map does not have to match the project's coordinate reference system since it is reprojected on the fly. +

JSON Output

+
+g.region -p format=json
+
+
+{
+    "projection": "99 (Lambert Conformal Conic)",
+    "zone": 0,
+    "datum": "nad83",
+    "ellipsoid": "a=6378137 es=0.006694380022900787",
+    "region": {
+        "north": 320000,
+        "south": 10000,
+        "west": 120000,
+        "east": 935000,
+        "ns-res": 500,
+        "ns-res3": 1000,
+        "ew-res": 500,
+        "ew-res3": 1000
+    },
+    "top": 500,
+    "bottom": -500,
+    "tbres": 100,
+    "rows": 620,
+    "rows3": 310,
+    "cols": 1630,
+    "cols3": 815,
+    "depths": 10,
+    "cells": 1010600,
+    "cells3": 2526500
+}
+
+ +
+g.region -l format=json
+
+
+{
+    "nw_long": -78.688888505507336,
+    "nw_lat": 35.743893244701788,
+    "ne_long": -78.669097826118957,
+    "ne_lat": 35.743841072010554,
+    "se_long": -78.669158624787542,
+    "se_lat": 35.728968779193615,
+    "sw_long": -78.688945667963168,
+    "sw_lat": 35.729020942542441,
+    "center_long": -78.679022655614958,
+    "center_lat": 35.736431420327719,
+    "rows": 165,
+    "cols": 179
+}
+
+

SEE ALSO

diff --git a/general/g.region/local_proto.h b/general/g.region/local_proto.h index 781fce01e81..31c1bd21e65 100644 --- a/general/g.region/local_proto.h +++ b/general/g.region/local_proto.h @@ -13,10 +13,15 @@ #define PRINT_GMT 0x200 #define PRINT_WMS 0x400 +#include + +enum OutputFormat { PLAIN, SHELL, JSON }; + /* zoom.c */ int zoom(struct Cell_head *, const char *, const char *); /* printwindow.c */ -void print_window(struct Cell_head *, int, int); +void print_window(struct Cell_head *, int, int, enum OutputFormat, + JSON_Object *); #endif diff --git a/general/g.region/main.c b/general/g.region/main.c index 06c33a2e8ce..c36eabe4c36 100644 --- a/general/g.region/main.c +++ b/general/g.region/main.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "local_proto.h" @@ -41,6 +42,9 @@ int main(int argc, char *argv[]) char **rast_ptr, **vect_ptr; int pix; bool update_file = false; + enum OutputFormat format; + JSON_Value *root_value; + JSON_Object *root_object; struct GModule *module; struct { @@ -51,7 +55,7 @@ int main(int argc, char *argv[]) struct { struct Option *north, *south, *east, *west, *top, *bottom, *res, *nsres, *ewres, *res3, *tbres, *rows, *cols, *save, *region, *raster, - *raster3d, *align, *zoom, *vect, *grow; + *raster3d, *align, *zoom, *vect, *grow, *format; } parm; G_gisinit(argv[0]); @@ -358,6 +362,13 @@ int main(int argc, char *argv[]) parm.save->gisprompt = "new,windows,region"; parm.save->guisection = _("Effects"); + parm.format = G_define_standard_option(G_OPT_F_FORMAT); + parm.format->options = "plain,shell,json"; + parm.format->descriptions = _("plain;Plain text output;" + "shell;shell script style output;" + "json;JSON (JavaScript Object Notation);"); + parm.format->guisection = _("Print"); + G_option_required( flag.dflt, flag.savedefault, flag.print, flag.lprint, flag.eprint, flag.center, flag.gmt_style, flag.wms_style, flag.dist_res, flag.nangle, @@ -421,6 +432,24 @@ int main(int argc, char *argv[]) print_flag |= PRINT_REG; } + if (strcmp(parm.format->answer, "json") == 0) { + format = JSON; + root_value = json_value_init_object(); + if (root_value == NULL) { + G_fatal_error( + _("Failed to initialize JSON object. Out of memory?")); + } + root_object = json_object(root_value); + } + else if (strcmp(parm.format->answer, "shell") == 0 || + (print_flag & PRINT_SH)) { + format = SHELL; + print_flag |= PRINT_SH; + } + else { + format = PLAIN; + } + if (flag.dflt->answer) update_file = true; else @@ -903,7 +932,18 @@ int main(int argc, char *argv[]) } /* / flag.savedefault->answer */ if (print_flag) - print_window(&window, print_flag, flat_flag); + print_window(&window, print_flag, flat_flag, format, root_object); + + if (format == JSON) { + char *serialized_string = NULL; + serialized_string = json_serialize_to_string_pretty(root_value); + if (serialized_string == NULL) { + G_fatal_error(_("Failed to initialize pretty JSON string.")); + } + puts(serialized_string); + json_free_serialized_string(serialized_string); + json_value_free(root_value); + } exit(EXIT_SUCCESS); } diff --git a/general/g.region/printwindow.c b/general/g.region/printwindow.c index 9d8d91cb447..c36600864ff 100644 --- a/general/g.region/printwindow.c +++ b/general/g.region/printwindow.c @@ -21,7 +21,8 @@ static double get_shift(double east) return shift; } -void print_window(struct Cell_head *window, int print_flag, int flat_flag) +void print_window(struct Cell_head *window, int print_flag, int flat_flag, + enum OutputFormat format, JSON_Object *root_object) { const char *prj, *datum, *ellps; int x, width = 11; @@ -31,9 +32,13 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) char buf[50]; char *sep = "\n"; + double d_nsres, d_ewres, d_nsres3, d_ewres3, d_tbres; double ew_dist1, ew_dist2, ns_dist1, ns_dist2; double longitude, latitude; + JSON_Value *region_value; + JSON_Object *region; + if (print_flag & PRINT_SH) { x = G_projection() == PROJECTION_LL ? -1 : 0; if (flat_flag) @@ -46,6 +51,12 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) G_format_northing(window->south, south, x); G_format_easting(window->east, east, x); G_format_easting(window->west, west, x); + + d_ewres = window->ew_res; + d_ewres3 = window->ew_res3; + d_nsres = window->ns_res; + d_nsres3 = window->ns_res3; + d_tbres = window->tb_res; G_format_resolution(window->ew_res, ewres, x); G_format_resolution(window->ew_res3, ewres3, x); G_format_resolution(window->ns_res, nsres, x); @@ -81,15 +92,20 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) /* flag.dist_res */ if (print_flag & PRINT_METERS) { - sprintf(ewres, "%.8f", ((ew_dist1 + ew_dist2) / 2) / window->cols); + d_ewres = ((ew_dist1 + ew_dist2) / 2) / window->cols; + sprintf(ewres, "%.8f", d_ewres); G_trim_decimal(ewres); - sprintf(ewres3, "%.8f", ((ew_dist1 + ew_dist2) / 2) / window->cols3); + d_ewres3 = ((ew_dist1 + ew_dist2) / 2) / window->cols3; + sprintf(ewres3, "%.8f", d_ewres3); G_trim_decimal(ewres3); - sprintf(nsres, "%.8f", ((ns_dist1 + ns_dist2) / 2) / window->rows); + d_nsres = ((ns_dist1 + ns_dist2) / 2) / window->rows; + sprintf(nsres, "%.8f", d_nsres); G_trim_decimal(nsres); - sprintf(nsres3, "%.8f", ((ns_dist1 + ns_dist2) / 2) / window->rows3); + d_nsres3 = ((ns_dist1 + ns_dist2) / 2) / window->rows3; + sprintf(nsres3, "%.8f", d_nsres3); G_trim_decimal(nsres3); - sprintf(tbres, "%.8f", (window->top - window->bottom) / window->depths); + d_tbres = (window->top - window->bottom) / window->depths; + sprintf(tbres, "%.8f", d_tbres); G_trim_decimal(tbres); } @@ -99,14 +115,22 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) if (!prj) prj = "** unknown **"; - if (print_flag & PRINT_SH) { + switch (format) { + case SHELL: fprintf(stdout, "projection=%d%s", window->proj, sep); fprintf(stdout, "zone=%d%s", window->zone, sep); - } - else { + break; + case PLAIN: fprintf(stdout, "%-*s %d (%s)\n", width, "projection:", window->proj, prj); fprintf(stdout, "%-*s %d\n", width, "zone:", window->zone); + break; + case JSON: + json_object_dotset_number(root_object, "projection.code", + window->proj); + json_object_dotset_string(root_object, "projection.name", prj); + json_object_set_number(root_object, "zone", window->zone); + break; } /* don't print datum/ellipsoid in XY-Locations */ @@ -140,13 +164,22 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) } */ - if (!(print_flag & PRINT_SH)) { - fprintf(stdout, "%-*s %s\n", width, "datum:", datum); - fprintf(stdout, "%-*s %s\n", width, "ellipsoid:", ellps); + switch (format) { + case JSON: + json_object_set_string(root_object, "datum", datum); + json_object_set_string(root_object, "ellipsoid", ellps); + break; + default: + if (!(print_flag & PRINT_SH)) { + fprintf(stdout, "%-*s %s\n", width, "datum:", datum); + fprintf(stdout, "%-*s %s\n", width, "ellipsoid:", ellps); + } + break; } } - if (print_flag & PRINT_SH) { + switch (format) { + case SHELL: fprintf(stdout, "n=%s%s", north, sep); fprintf(stdout, "s=%s%s", south, sep); fprintf(stdout, "w=%s%s", west, sep); @@ -188,8 +221,8 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) (long)window->rows3 * window->cols3 * window->depths, sep); #endif - } - else { + break; + case PLAIN: fprintf(stdout, "%-*s %s\n", width, "north:", north); fprintf(stdout, "%-*s %s\n", width, "south:", south); fprintf(stdout, "%-*s %s\n", width, "west:", west); @@ -232,6 +265,42 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) fprintf(stdout, "%-*s %ld\n", width, "cells3:", (long)window->rows3 * window->cols3 * window->depths); #endif + break; + case JSON: + region_value = json_value_init_object(); + region = json_object(region_value); + json_object_set_number(region, "north", window->north); + json_object_set_number(region, "south", window->south); + json_object_set_number(region, "west", window->west); + json_object_set_number(region, "east", window->east); + json_object_set_number(region, "ns-res", d_nsres); + json_object_set_number(region, "ns-res3", d_nsres3); + json_object_set_number(region, "ew-res", d_ewres); + json_object_set_number(region, "ew-res3", d_ewres3); + json_object_set_value(root_object, "region", region_value); + json_object_set_number(root_object, "top", window->top); + json_object_set_number(root_object, "bottom", window->bottom); + json_object_set_number(root_object, "tbres", d_tbres); + json_object_set_number(root_object, "rows", window->rows); + json_object_set_number(root_object, "rows3", window->rows3); + json_object_set_number(root_object, "cols", window->cols); + json_object_set_number(root_object, "cols3", window->cols3); + json_object_set_number(root_object, "depths", window->depths); + +#ifdef HAVE_LONG_LONG_INT + json_object_set_number(root_object, "cells", + (long long)window->rows * window->cols); + json_object_set_number(root_object, "cells3", + (long long)window->rows3 * window->cols3 * + window->depths); +#else + json_object_set_number(root_object, "cells", + (long)window->rows * window->cols); + json_object_set_number(root_object, "cells3", + (long)window->rows3 * window->cols3 * + window->depths); +#endif + break; } } @@ -337,7 +406,8 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) loc = longitude; lac = latitude; - if (print_flag & PRINT_SH) { + switch (format) { + case SHELL: fprintf(stdout, "nw_long=%.8f%snw_lat=%.8f%s", lo1, sep, la1, sep); fprintf(stdout, "ne_long=%.8f%sne_lat=%.8f%s", lo2, sep, la2, @@ -348,8 +418,8 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) sep); fprintf(stdout, "center_long=%.8f%s", loc, sep); fprintf(stdout, "center_lat=%.8f%s", lac, sep); - } - else { + break; + case PLAIN: G_format_easting(lo1, buf, PROJECTION_LL); fprintf(stdout, "%-*s long: %s ", width, "north-west corner:", buf); @@ -379,16 +449,35 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) G_format_northing(lac, buf, PROJECTION_LL); fprintf(stdout, "%-*s %11s\n", width, "center latitude:", buf); + break; + case JSON: + json_object_set_number(root_object, "nw_long", lo1); + json_object_set_number(root_object, "nw_lat", la1); + json_object_set_number(root_object, "ne_long", lo2); + json_object_set_number(root_object, "ne_lat", la2); + json_object_set_number(root_object, "se_long", lo3); + json_object_set_number(root_object, "se_lat", la3); + json_object_set_number(root_object, "sw_long", lo4); + json_object_set_number(root_object, "sw_lat", la4); + json_object_set_number(root_object, "center_long", loc); + json_object_set_number(root_object, "center_lat", lac); + break; } if (!(print_flag & PRINT_REG)) { - if (print_flag & PRINT_SH) { + switch (format) { + case SHELL: fprintf(stdout, "rows=%d%s", window->rows, sep); fprintf(stdout, "cols=%d%s", window->cols, sep); - } - else { + break; + case PLAIN: fprintf(stdout, "%-*s %d\n", width, "rows:", window->rows); fprintf(stdout, "%-*s %d\n", width, "cols:", window->cols); + break; + case JSON: + json_object_set_number(root_object, "rows", window->rows); + json_object_set_number(root_object, "cols", window->cols); + break; } } } @@ -406,12 +495,13 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) /* flag.eprint */ if (print_flag & PRINT_EXTENT) { - if (print_flag & PRINT_SH) { + switch (format) { + case SHELL: fprintf(stdout, "ns_extent=%f%s", window->north - window->south, sep); fprintf(stdout, "ew_extent=%f%s", window->east - window->west, sep); - } - else { + break; + case PLAIN: if (G_projection() != PROJECTION_LL) { fprintf(stdout, "%-*s %f\n", width, "north-south extent:", window->north - window->south); @@ -426,18 +516,26 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) PROJECTION_LL); fprintf(stdout, "%-*s %s\n", width, "east-west extent:", buf); } + break; + case JSON: + json_object_set_number(root_object, "ns_extent", + window->north - window->south); + json_object_set_number(root_object, "ew_extent", + window->east - window->west); + break; } } /* flag.center */ if (print_flag & PRINT_CENTER) { - if (print_flag & PRINT_SH) { + switch (format) { + case SHELL: fprintf(stdout, "center_easting=%f%s", (window->west + window->east) / 2., sep); fprintf(stdout, "center_northing=%f%s", (window->north + window->south) / 2., sep); - } - else { + break; + case PLAIN: if (G_projection() != PROJECTION_LL) { fprintf(stdout, "%-*s %f\n", width, "center easting:", (window->west + window->east) / 2.); @@ -452,20 +550,47 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) PROJECTION_LL); fprintf(stdout, "%-*s %s\n", width, "east-west center:", buf); } + break; + case JSON: + json_object_set_number(root_object, "center_easting", + (window->west + window->east) / 2.); + json_object_set_number(root_object, "center_northing", + (window->north + window->south) / 2.); + break; } } /* flag.gmt_style */ - if (print_flag & PRINT_GMT) - fprintf(stdout, "%s/%s/%s/%s\n", west, east, south, north); + if (print_flag & PRINT_GMT) { + char gmt[120]; + switch (format) { + case JSON: + snprintf(gmt, 120, "%s/%s/%s/%s", west, east, south, north); + json_object_set_string(root_object, "GMT", gmt); + break; + default: + fprintf(stdout, "%s/%s/%s/%s\n", west, east, south, north); + break; + } + } /* flag.wms_style */ if (print_flag & PRINT_WMS) { - G_format_northing(window->north, north, -1); - G_format_northing(window->south, south, -1); - G_format_easting(window->east, east, -1); - G_format_easting(window->west, west, -1); - fprintf(stdout, "bbox=%s,%s,%s,%s%s", west, south, east, north, sep); + char wms[150]; + switch (format) { + case JSON: + snprintf(wms, 150, "bbox=%s,%s,%s,%s", west, south, east, north); + json_object_set_string(root_object, "WMS", wms); + break; + default: + G_format_northing(window->north, north, -1); + G_format_northing(window->south, south, -1); + G_format_easting(window->east, east, -1); + G_format_easting(window->west, west, -1); + fprintf(stdout, "bbox=%s,%s,%s,%s%s", west, south, east, north, + sep); + break; + } } /* flag.nangle */ @@ -540,11 +665,17 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) #endif } - if (print_flag & PRINT_SH) + switch (format) { + case SHELL: fprintf(stdout, "converge_angle=%f%s", convergence, sep); - else + break; + case PLAIN: fprintf(stdout, "%-*s %f\n", width, "convergence angle:", convergence); + break; + case JSON: + json_object_set_number(root_object, "converge_angle", convergence); + } } /* flag.bbox @@ -722,7 +853,8 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) sh_ll_e += get_shift(sh_ll_e); /* print the largest bounding box */ - if (print_flag & PRINT_SH) { + switch (format) { + case SHELL: fprintf(stdout, "ll_n=%.8f%s", sh_ll_n, sep); fprintf(stdout, "ll_s=%.8f%s", sh_ll_s, sep); fprintf(stdout, "ll_w=%.8f%s", sh_ll_w, sep); @@ -731,8 +863,8 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) fprintf(stdout, "ll_clon=%.8f%s", loc, sep); fprintf(stdout, "ll_clat=%.8f%s", (sh_ll_n + sh_ll_s) / 2., sep); - } - else { + break; + case PLAIN: G_format_northing(sh_ll_n, buf, PROJECTION_LL); fprintf(stdout, "%-*s %s\n", width, "north latitude:", buf); G_format_northing(sh_ll_s, buf, PROJECTION_LL); @@ -746,6 +878,16 @@ void print_window(struct Cell_head *window, int print_flag, int flat_flag) fprintf(stdout, "%-*s %s\n", width, "center longitude:", buf); G_format_northing((sh_ll_n + sh_ll_s) / 2., buf, PROJECTION_LL); fprintf(stdout, "%-*s %s\n", width, "center latitude:", buf); + break; + case JSON: + json_object_set_number(root_object, "ll_n", sh_ll_n); + json_object_set_number(root_object, "ll_s", sh_ll_s); + json_object_set_number(root_object, "ll_w", sh_ll_w); + json_object_set_number(root_object, "ll_e", sh_ll_e); + /* center of the largest bounding box */ + json_object_set_number(root_object, "ll_clon", loc); + json_object_set_number(root_object, "ll_clat", + (sh_ll_n + sh_ll_s) / 2.); } /*It should be calculated which number of rows and cols we have in diff --git a/general/g.region/testsuite/test_g_region.py b/general/g.region/testsuite/test_g_region.py index 7362c062f1d..f174c19af67 100644 --- a/general/g.region/testsuite/test_g_region.py +++ b/general/g.region/testsuite/test_g_region.py @@ -3,6 +3,8 @@ @author Anna Petrasova """ +import json + from grass.gunittest.case import TestCase from grass.gunittest.gmodules import call_module import grass.script as gs @@ -46,6 +48,74 @@ def test_f_flag(self): line = call_module("g.region", flags="fglecn3", capture_stdout=True) self.assertEqual(1, len(line.splitlines())) + def test_format_json(self): + """Test json format""" + expected = { + "projection": {"code": 99, "name": "Lambert Conformal Conic"}, + "zone": 0, + "datum": "nad83", + "ellipsoid": "a=6378137 es=0.006694380022900787", + "region": { + "north": 320000, + "south": 10000, + "west": 120000, + "east": 935000, + "ns-res": 500, + "ns-res3": 1000, + "ew-res": 500, + "ew-res3": 1000, + }, + "top": 500, + "bottom": -500, + "tbres": 100, + "rows": 620, + "rows3": 310, + "cols": 1630, + "cols3": 815, + "depths": 10, + "cells": 1010600, + "cells3": 2526500, + "GMT": "120000/935000/10000/320000", + "WMS": "bbox=120000,10000,935000,320000", + "se_lat": 33.78822598716895, + "se_long": -75.48643633119754, + "sw_lat": 33.722662075471355, + "sw_long": -84.28378827453474, + "ew_extent": 815000, + "ll_clat": 35.17852919352316, + "ll_clon": -79.91588285974797, + "ll_e": -75.36388301356145, + "ll_n": 36.634396311574974, + "ll_s": 33.722662075471355, + "ll_w": -84.46788270593447, + "ne_lat": 36.58069555564894, + "ne_long": -75.36388301356145, + "ns_extent": 310000, + "nw_lat": 36.51287343603797, + "nw_long": -84.46788270593447, + "center_easting": 527500, + "center_lat": 35.23406270825775, + "center_long": -79.90206638014922, + "center_northing": 165000, + "converge_angle": -0.5206458828734528, + } + + output = call_module("g.region", flags="plectwmn3b", format="json") + output_json = json.loads(output) + + expected_ellps = expected.pop("ellipsoid").split(" ") + received_ellps = output_json.pop("ellipsoid").split(" ") + self.assertEqual(expected_ellps[0], received_ellps[0]) + self.assertAlmostEqual( + float(expected_ellps[1][3:]), float(received_ellps[1][3:]), places=6 + ) + self.assertCountEqual(list(expected.keys()), list(output_json.keys())) + for key in expected: + if isinstance(expected[key], float): + self.assertAlmostEqual(expected[key], output_json[key], places=6) + else: + self.assertEqual(expected[key], output_json[key]) + if __name__ == "__main__": from grass.gunittest.main import test diff --git a/python/grass/pygrass/modules/interface/module.py b/python/grass/pygrass/modules/interface/module.py index b9c298b4a6f..c8a1e723a05 100644 --- a/python/grass/pygrass/modules/interface/module.py +++ b/python/grass/pygrass/modules/interface/module.py @@ -334,11 +334,11 @@ class Module: >>> region.flags.u = True >>> region.flags["3"].value = True # set numeric flags >>> region.get_bash() - 'g.region -p -3 -u' + 'g.region format=plain -p -3 -u' >>> new_region = copy.deepcopy(region) >>> new_region.inputs.res = "10" >>> new_region.get_bash() - 'g.region res=10 -p -3 -u' + 'g.region res=10 format=plain -p -3 -u' >>> neighbors = Module("r.neighbors") >>> neighbors.inputs.input = "mapA" @@ -952,7 +952,8 @@ class MultiModule: ... set_temp_region=True, ... ) >>> str(mm) - 'g.region -p ; g.region -p ; g.region -p ; g.region -p ; g.region -p' + 'g.region format=plain -p ; g.region format=plain -p ; g.region format=plain -p ; \ +g.region format=plain -p ; g.region format=plain -p' >>> t = mm.run() >>> isinstance(t, Process) True