From 7f4aabffb350c6d12ef5d27f954a95f7d1de3be4 Mon Sep 17 00:00:00 2001 From: Kriti Birda <164247895+kritibirda26@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:24:52 +0530 Subject: [PATCH] r.profile: add JSON support (#3872) Use parson to add json output format support to the r.profile module. --- raster/r.profile/Makefile | 2 +- raster/r.profile/local_proto.h | 10 +- raster/r.profile/main.c | 72 ++- raster/r.profile/r.profile.html | 103 ++++ raster/r.profile/read_rast.c | 86 ++- .../r.profile/testsuite/test_profile_ncspm.py | 556 ++++++++++++++++++ 6 files changed, 791 insertions(+), 38 deletions(-) diff --git a/raster/r.profile/Makefile b/raster/r.profile/Makefile index 3b37dbd1f2a..b5fc2578565 100644 --- a/raster/r.profile/Makefile +++ b/raster/r.profile/Makefile @@ -2,7 +2,7 @@ MODULE_TOPDIR = ../.. PGM = r.profile -LIBES = $(RASTERLIB) $(GISLIB) $(MATHLIB) +LIBES = $(RASTERLIB) $(GISLIB) $(MATHLIB) $(PARSONLIB) DEPENDENCIES = $(RASTERDEP) $(GISDEP) include $(MODULE_TOPDIR)/include/Make/Module.make diff --git a/raster/r.profile/local_proto.h b/raster/r.profile/local_proto.h index 4b11584ae76..b559192046a 100644 --- a/raster/r.profile/local_proto.h +++ b/raster/r.profile/local_proto.h @@ -2,16 +2,20 @@ #include #include #include +#include #include #include +enum OutputFormat { PLAIN, JSON }; + /* main.c */ int do_profile(double, double, double, double, int, double, int, int, FILE *, - char *, const char *, double); + char *, const char *, double, enum OutputFormat, char *, + JSON_Array *); /* read_rast.c */ -int read_rast(double, double, double, int, int, RASTER_MAP_TYPE, FILE *, - char *); +int read_rast(double, double, double, int, int, RASTER_MAP_TYPE, FILE *, char *, + enum OutputFormat, char *, JSON_Array *); /* input.c */ int input(char *, char *, char *, char *, char *, FILE *); diff --git a/raster/r.profile/main.c b/raster/r.profile/main.c index 2a0701398e8..fafa57421e0 100644 --- a/raster/r.profile/main.c +++ b/raster/r.profile/main.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -39,10 +40,13 @@ int main(int argc, char *argv[]) struct Cell_head window; struct { struct Option *opt1, *profile, *res, *output, *null_str, *coord_file, - *units; + *units, *format; struct Flag *g, *c, *m; } parm; struct GModule *module; + enum OutputFormat format; + JSON_Value *array_value; + JSON_Array *array; G_gisinit(argv[0]); @@ -102,6 +106,9 @@ int main(int argc, char *argv[]) _("If units are not specified, current project units are used. " "Meters are used by default in geographic (latlon) projects."); + parm.format = G_define_standard_option(G_OPT_F_FORMAT); + parm.units->guisection = _("Print"); + if (G_parser(argc, argv)) exit(EXIT_FAILURE); @@ -147,6 +154,15 @@ int main(int argc, char *argv[]) res = (window.ew_res + window.ns_res) / 2; } + if (strcmp(parm.format->answer, "json") == 0) { + format = JSON; + array_value = json_value_init_array(); + array = json_array(array_value); + } + else { + format = PLAIN; + } + G_message(_("Using resolution: %g [%s]"), res / factor, unit); G_begin_distance_calculations(); @@ -177,17 +193,19 @@ int main(int argc, char *argv[]) data_type = Rast_get_map_type(fd); /* Done with file */ - /* Show message giving output format */ - G_message(_("Output columns:")); - if (coords == 1) - sprintf(formatbuff, - _("Easting, Northing, Along track dist. [%s], Elevation"), - unit); - else - sprintf(formatbuff, _("Along track dist. [%s], Elevation"), unit); - if (clr) - strcat(formatbuff, _(" RGB color")); - G_message("%s", formatbuff); + if (format == PLAIN) { + /* Show message giving output format */ + G_message(_("Output columns:")); + if (coords == 1) + sprintf(formatbuff, + _("Easting, Northing, Along track dist. [%s], Elevation"), + unit); + else + sprintf(formatbuff, _("Along track dist. [%s], Elevation"), unit); + if (clr) + strcat(formatbuff, _(" RGB color")); + G_message("%s", formatbuff); + } /* Get Profile Start Coords */ if (parm.coord_file->answer) { @@ -207,7 +225,7 @@ int main(int argc, char *argv[]) if (havefirst) do_profile(e1, e2, n1, n2, coords, res, fd, data_type, fp, - null_string, unit, factor); + null_string, unit, factor, format, name, array); e1 = e2; n1 = n2; havefirst = TRUE; @@ -232,7 +250,7 @@ int main(int argc, char *argv[]) /* Get profile info */ do_profile(e1, e2, n1, n2, coords, res, fd, data_type, fp, - null_string, unit, factor); + null_string, unit, factor, format, name, array); } else { for (i = 0; i <= k - 2; i += 2) { @@ -246,11 +264,21 @@ int main(int argc, char *argv[]) /* Get profile info */ do_profile(e1, e2, n1, n2, coords, res, fd, data_type, fp, - null_string, unit, factor); + null_string, unit, factor, format, name, array); } } } + if (format == JSON) { + char *serialized_string = json_serialize_to_string_pretty(array_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(array_value); + } + Rast_close(fd); fclose(fp); @@ -264,7 +292,8 @@ int main(int argc, char *argv[]) /* Establish parameters */ int do_profile(double e1, double e2, double n1, double n2, int coords, double res, int fd, int data_type, FILE *fp, char *null_string, - const char *unit, double factor) + const char *unit, double factor, enum OutputFormat format, + char *name, JSON_Array *array) { double rows, cols, LEN; double Y, X, k; @@ -284,7 +313,8 @@ int do_profile(double e1, double e2, double n1, double n2, int coords, /* Special case for no movement */ e = e1; n = n1; - read_rast(e, n, dist / factor, fd, coords, data_type, fp, null_string); + read_rast(e, n, dist / factor, fd, coords, data_type, fp, null_string, + format, name, array); } k = res / hypot(rows, cols); @@ -303,7 +333,7 @@ int do_profile(double e1, double e2, double n1, double n2, int coords, /* SE Quad or due east */ for (e = e1, n = n1; e < e2 || n > n2; e += X, n -= Y) { read_rast(e, n, dist / factor, fd, coords, data_type, fp, - null_string); + null_string, format, name, array); /* d+=res; */ dist += G_distance(e - X, n + Y, e, n); } @@ -313,7 +343,7 @@ int do_profile(double e1, double e2, double n1, double n2, int coords, /* NE Quad or due north */ for (e = e1, n = n1; e < e2 || n < n2; e += X, n += Y) { read_rast(e, n, dist / factor, fd, coords, data_type, fp, - null_string); + null_string, format, name, array); /* d+=res; */ dist += G_distance(e - X, n - Y, e, n); } @@ -323,7 +353,7 @@ int do_profile(double e1, double e2, double n1, double n2, int coords, /* SW Quad or due south */ for (e = e1, n = n1; e > e2 || n > n2; e -= X, n -= Y) { read_rast(e, n, dist / factor, fd, coords, data_type, fp, - null_string); + null_string, format, name, array); /* d+=res; */ dist += G_distance(e + X, n + Y, e, n); } @@ -333,7 +363,7 @@ int do_profile(double e1, double e2, double n1, double n2, int coords, /* NW Quad or due west */ for (e = e1, n = n1; e > e2 || n < n2; e -= X, n += Y) { read_rast(e, n, dist / factor, fd, coords, data_type, fp, - null_string); + null_string, format, name, array); /* d+=res; */ dist += G_distance(e + X, n - Y, e, n); } diff --git a/raster/r.profile/r.profile.html b/raster/r.profile/r.profile.html index 096bee7f52c..b5801a28055 100644 --- a/raster/r.profile/r.profile.html +++ b/raster/r.profile/r.profile.html @@ -48,6 +48,8 @@

OUTPUT FORMAT

If the units are not specified, current coordinate reference system's units will be used. In case of geographic CRS (latitude/longitude), meters are used as default unit. +Finally, the output from r.info can be output in JSON by passing the format=json option. +

NOTES

The profile resolution is measured exactly from the supplied end or @@ -151,6 +153,107 @@

Extraction of values along profile defined by coordinates (variant 2)

4054.027749 73.988029 +

JSON Output

+
+r.profile -g input=elevation coordinates=641712,226095,641546,224138,641546,222048,641049,221186 -c format=json resolution=1000
+
+ +The output looks as follows: + +
+[
+    {
+        "easting": 641712,
+        "northing": 226095,
+        "distance": 0,
+        "elevation": 84.661506652832031,
+        "red": 113,
+        "green": 255,
+        "blue": 0
+    },
+    {
+        "easting": 641627.47980925441,
+        "northing": 225098.57823319823,
+        "distance": 1000.0000000000125,
+        "elevation": 98.179061889648438,
+        "red": 255,
+        "green": 241,
+        "blue": 0
+    },
+    {
+        "easting": 641546,
+        "northing": 224138,
+        "distance": 1964.0277492948007,
+        "elevation": 83.638137817382812,
+        "red": 100,
+        "green": 255,
+        "blue": 0
+    },
+    {
+        "easting": 641546,
+        "northing": 223138,
+        "distance": 2964.0277492948007,
+        "elevation": 89.141029357910156,
+        "red": 169,
+        "green": 255,
+        "blue": 0
+    },
+    {
+        "easting": 641546,
+        "northing": 222138,
+        "distance": 3964.0277492948007,
+        "elevation": 78.497756958007812,
+        "red": 35,
+        "green": 255,
+        "blue": 0
+    },
+    {
+        "easting": 641546,
+        "northing": 222048,
+        "distance": 4054.0277492948007,
+        "elevation": 73.988029479980469,
+        "red": 0,
+        "green": 249,
+        "blue": 17
+    }
+]
+
+ +

Using JSON output with Python for plotting data

+ +The JSON output makes for ease of integration with popular python data science libraries. For instance, here +is an example of creating a scatterplot of distance vs elevation with color coding. + +
+import grass.script as gs
+import pandas as pd
+import matplotlib.pyplot as plt
+
+# Run r.profile command
+elevation = gs.read_command(
+    "r.profile",
+    input="elevation",
+    coordinates="641712,226095,641546,224138,641546,222048,641049,221186",
+    format="json",
+    flags="gc"
+)
+
+# Load the JSON data into a dataframe
+df = pd.read_json(elevation)
+
+# Convert the RGB color values to hex format for matplotlib
+df["color"] = df.apply(lambda x: "#{:02x}{:02x}{:02x}".format(int(x["red"]), int(x["green"]), int(x["blue"])), axis=1)
+
+# Create the scatter plot
+plt.figure(figsize=(10, 6))
+plt.scatter(df['distance'], df['elevation'], c=df['color'], marker='o')
+plt.title('Profile of Distance vs. Elevation with Color Coding')
+plt.xlabel('Distance (meters)')
+plt.ylabel('Elevation')
+plt.grid(True)
+plt.show()
+
+

SEE ALSO

diff --git a/raster/r.profile/read_rast.c b/raster/r.profile/read_rast.c index dedc7524b71..7d2a5e77ecb 100644 --- a/raster/r.profile/read_rast.c +++ b/raster/r.profile/read_rast.c @@ -10,10 +10,12 @@ #include #include #include +#include #include "local_proto.h" int read_rast(double east, double north, double dist, int fd, int coords, - RASTER_MAP_TYPE data_type, FILE *fp, char *null_string) + RASTER_MAP_TYPE data_type, FILE *fp, char *null_string, + enum OutputFormat format, char *name, JSON_Array *array) { static DCELL *dcell; static int cur_row = -1; @@ -22,6 +24,13 @@ int read_rast(double east, double north, double dist, int fd, int coords, static struct Cell_head window; int row, col; int outofbounds = FALSE; + JSON_Object *object; + JSON_Value *value; + + if (format == JSON) { + value = json_value_init_object(); + object = json_object(value); + } if (!dcell) { Rast_set_c_null_value(&nullcell, 1); @@ -44,18 +53,54 @@ int read_rast(double east, double north, double dist, int fd, int coords, cur_row = row; } - if (coords) - fprintf(fp, "%f %f", east, north); + switch (format) { + case JSON: + if (coords) { + json_object_set_number(object, "easting", east); + json_object_set_number(object, "northing", north); + } + json_object_set_number(object, "distance", dist); + break; + case PLAIN: + if (coords) + fprintf(fp, "%f %f", east, north); - fprintf(fp, " %f", dist); + fprintf(fp, " %f", dist); + break; + } - if (outofbounds || Rast_is_d_null_value(&dcell[col])) - fprintf(fp, " %s", null_string); + if (outofbounds || Rast_is_d_null_value(&dcell[col])) { + switch (format) { + case JSON: + json_object_set_null(object, name); + break; + case PLAIN: + fprintf(fp, " %s", null_string); + break; + } + } else { - if (data_type == CELL_TYPE) - fprintf(fp, " %d", (int)dcell[col]); - else - fprintf(fp, " %f", dcell[col]); + if (data_type == CELL_TYPE) { + int dvalue = (int)dcell[col]; + switch (format) { + case JSON: + json_object_set_number(object, name, dvalue); + break; + case PLAIN: + fprintf(fp, " %d", dvalue); + break; + } + } + else { + switch (format) { + case JSON: + json_object_set_number(object, name, dcell[col]); + break; + case PLAIN: + fprintf(fp, " %f", dcell[col]); + break; + } + } } if (clr) { @@ -65,11 +110,26 @@ int read_rast(double east, double north, double dist, int fd, int coords, Rast_get_c_color(&nullcell, &red, &green, &blue, &colors); else Rast_get_d_color(&dcell[col], &red, &green, &blue, &colors); - - fprintf(fp, " %03d:%03d:%03d", red, green, blue); + switch (format) { + case JSON: + json_object_set_number(object, "red", red); + json_object_set_number(object, "green", green); + json_object_set_number(object, "blue", blue); + break; + case PLAIN: + fprintf(fp, " %03d:%03d:%03d", red, green, blue); + break; + } } - fprintf(fp, "\n"); + switch (format) { + case JSON: + json_array_append_value(array, value); + break; + case PLAIN: + fprintf(fp, "\n"); + break; + } return 0; } diff --git a/raster/r.profile/testsuite/test_profile_ncspm.py b/raster/r.profile/testsuite/test_profile_ncspm.py index e3706bb6851..41c8c722105 100644 --- a/raster/r.profile/testsuite/test_profile_ncspm.py +++ b/raster/r.profile/testsuite/test_profile_ncspm.py @@ -3,6 +3,9 @@ from grass.gunittest.gmodules import SimpleModule import grass.script.core as gcore +import json +from itertools import zip_longest + # not used yet LOCATION = "nc_spm" @@ -129,6 +132,486 @@ 635746.431136 222663.350636 508.676634 117.672462 """ +output_json_with_color = [ + { + "easting": 635747, + "northing": 222664, + "distance": 0, + "elevation": 117.67246246337891, + "red": 250, + "green": 127, + "blue": 5, + }, + { + "easting": 635738.87009513902, + "northing": 222669.8227696977, + "distance": 10.000000000050347, + "elevation": 116.41721343994141, + "red": 254, + "green": 127, + "blue": 1, + }, + { + "easting": 635730.74019027804, + "northing": 222675.64553939539, + "distance": 20.000000000100695, + "elevation": 115.63948059082031, + "red": 255, + "green": 130, + "blue": 0, + }, + { + "easting": 635722.61028541706, + "northing": 222681.46830909309, + "distance": 30.00000000015104, + "elevation": 112.83534240722656, + "red": 255, + "green": 148, + "blue": 0, + }, + { + "easting": 635714.48038055608, + "northing": 222687.29107879079, + "distance": 40.000000000201389, + "elevation": 111.32489013671875, + "red": 255, + "green": 157, + "blue": 0, + }, + { + "easting": 635706.3504756951, + "northing": 222693.11384848849, + "distance": 50.000000000251738, + "elevation": 108.61228179931641, + "red": 255, + "green": 175, + "blue": 0, + }, + { + "easting": 635698.22057083412, + "northing": 222698.93661818618, + "distance": 60.000000000302087, + "elevation": 106.31334686279297, + "red": 255, + "green": 189, + "blue": 0, + }, + { + "easting": 635690.09066597314, + "northing": 222704.75938788388, + "distance": 70.000000000352429, + "elevation": 104.91566467285156, + "red": 255, + "green": 198, + "blue": 0, + }, + { + "easting": 635681.96076111216, + "northing": 222710.58215758158, + "distance": 80.000000000402778, + "elevation": 102.87860107421875, + "red": 255, + "green": 211, + "blue": 0, + }, + { + "easting": 635673.83085625118, + "northing": 222716.40492727928, + "distance": 90.000000000453127, + "elevation": 102.93507385253906, + "red": 255, + "green": 211, + "blue": 0, + }, + { + "easting": 635673, + "northing": 222717, + "distance": 91.021975368588883, + "elevation": 102.93507385253906, + "red": 255, + "green": 211, + "blue": 0, + }, + { + "easting": 635665.01745017618, + "northing": 222710.97680331473, + "distance": 101.02197536855223, + "elevation": 102.93221282958984, + "red": 255, + "green": 211, + "blue": 0, + }, + { + "easting": 635657.03490035236, + "northing": 222704.95360662945, + "distance": 111.02197536851558, + "elevation": 102.93115234375, + "red": 255, + "green": 211, + "blue": 0, + }, + { + "easting": 635649.05235052854, + "northing": 222698.93040994418, + "distance": 121.02197536847893, + "elevation": 102.93221282958984, + "red": 255, + "green": 211, + "blue": 0, + }, + { + "easting": 635641.06980070472, + "northing": 222692.90721325891, + "distance": 131.02197536844227, + "elevation": 102.93221282958984, + "red": 255, + "green": 211, + "blue": 0, + }, + { + "easting": 635633.0872508809, + "northing": 222686.88401657363, + "distance": 141.02197536840561, + "elevation": 102.93164825439453, + "red": 255, + "green": 211, + "blue": 0, + }, + { + "easting": 635625.10470105708, + "northing": 222680.86081988836, + "distance": 151.02197536836894, + "elevation": 102.936767578125, + "red": 255, + "green": 211, + "blue": 0, + }, + { + "easting": 635617.12215123326, + "northing": 222674.83762320309, + "distance": 161.02197536833228, + "elevation": 102.90335845947266, + "red": 255, + "green": 211, + "blue": 0, + }, + { + "easting": 635609.13960140944, + "northing": 222668.81442651781, + "distance": 171.02197536829561, + "elevation": 105.44782257080078, + "red": 255, + "green": 195, + "blue": 0, + }, + { + "easting": 635601.15705158561, + "northing": 222662.79122983254, + "distance": 181.02197536825895, + "elevation": 105.44782257080078, + "red": 255, + "green": 195, + "blue": 0, + }, + { + "easting": 635593.17450176179, + "northing": 222656.76803314727, + "distance": 191.02197536822229, + "elevation": 108.42352294921875, + "red": 255, + "green": 176, + "blue": 0, + }, + { + "easting": 635585.19195193797, + "northing": 222650.74483646199, + "distance": 201.02197536818562, + "elevation": 109.19235992431641, + "red": 255, + "green": 171, + "blue": 0, + }, + { + "easting": 635577.20940211415, + "northing": 222644.72163977672, + "distance": 211.02197536814896, + "elevation": 112.04276275634766, + "red": 255, + "green": 153, + "blue": 0, + }, + { + "easting": 635569.22685229033, + "northing": 222638.69844309145, + "distance": 221.02197536811229, + "elevation": 114.32113647460938, + "red": 255, + "green": 138, + "blue": 0, + }, + { + "easting": 635563, + "northing": 222634, + "distance": 228.82255591888975, + "elevation": 114.32113647460938, + "red": 255, + "green": 138, + "blue": 0, + }, + { + "easting": 635569.50791373453, + "northing": 222626.40743397636, + "distance": 238.82255591886044, + "elevation": 115.35729217529297, + "red": 255, + "green": 132, + "blue": 0, + }, + { + "easting": 635576.01582746906, + "northing": 222618.81486795272, + "distance": 248.82255591883114, + "elevation": 114.60910034179688, + "red": 255, + "green": 137, + "blue": 0, + }, + { + "easting": 635582.52374120359, + "northing": 222611.22230192908, + "distance": 258.82255591880187, + "elevation": 111.63629150390625, + "red": 255, + "green": 155, + "blue": 0, + }, + { + "easting": 635589.03165493812, + "northing": 222603.62973590544, + "distance": 268.82255591877259, + "elevation": 112.35543060302734, + "red": 255, + "green": 151, + "blue": 0, + }, + { + "easting": 635595.53956867266, + "northing": 222596.03716988181, + "distance": 278.82255591874332, + "elevation": 110.162841796875, + "red": 255, + "green": 165, + "blue": 0, + }, + { + "easting": 635602.04748240719, + "northing": 222588.44460385817, + "distance": 288.82255591871404, + "elevation": 109.17266845703125, + "red": 255, + "green": 171, + "blue": 0, + }, + { + "easting": 635608.55539614172, + "northing": 222580.85203783453, + "distance": 298.82255591868477, + "elevation": 109.17266845703125, + "red": 255, + "green": 171, + "blue": 0, + }, + { + "easting": 635615.06330987625, + "northing": 222573.25947181089, + "distance": 308.8225559186555, + "elevation": 108.03054046630859, + "red": 255, + "green": 178, + "blue": 0, + }, + { + "easting": 635621.57122361078, + "northing": 222565.66690578725, + "distance": 318.82255591862622, + "elevation": 105.67011260986328, + "red": 255, + "green": 193, + "blue": 0, + }, + { + "easting": 635628.07913734531, + "northing": 222558.07433976361, + "distance": 328.82255591859695, + "elevation": 105.77028656005859, + "red": 255, + "green": 193, + "blue": 0, + }, + { + "easting": 635634.58705107984, + "northing": 222550.48177373997, + "distance": 338.82255591856767, + "elevation": 105.16993713378906, + "red": 255, + "green": 196, + "blue": 0, + }, + { + "easting": 635641, + "northing": 222543, + "distance": 348.67663386369753, + "elevation": 105.41686248779297, + "red": 255, + "green": 195, + "blue": 0, + }, + { + "easting": 635647.58944598527, + "northing": 222550.52191475674, + "distance": 358.67663386372163, + "elevation": 105.01118469238281, + "red": 255, + "green": 197, + "blue": 0, + }, + { + "easting": 635654.17889197054, + "northing": 222558.04382951348, + "distance": 368.67663386374574, + "elevation": 104.85426330566406, + "red": 255, + "green": 198, + "blue": 0, + }, + { + "easting": 635660.76833795581, + "northing": 222565.56574427022, + "distance": 378.67663386376984, + "elevation": 104.57392120361328, + "red": 255, + "green": 200, + "blue": 0, + }, + { + "easting": 635667.35778394109, + "northing": 222573.08765902696, + "distance": 388.67663386379394, + "elevation": 103.41336059570312, + "red": 255, + "green": 208, + "blue": 0, + }, + { + "easting": 635673.94722992636, + "northing": 222580.6095737837, + "distance": 398.67663386381804, + "elevation": 105.48558807373047, + "red": 255, + "green": 194, + "blue": 0, + }, + { + "easting": 635680.53667591163, + "northing": 222588.13148854044, + "distance": 408.67663386384214, + "elevation": 109.791015625, + "red": 255, + "green": 167, + "blue": 0, + }, + { + "easting": 635687.1261218969, + "northing": 222595.65340329718, + "distance": 418.67663386386624, + "elevation": 109.70148468017578, + "red": 255, + "green": 168, + "blue": 0, + }, + { + "easting": 635693.71556788217, + "northing": 222603.17531805392, + "distance": 428.67663386389034, + "elevation": 112.1043701171875, + "red": 255, + "green": 152, + "blue": 0, + }, + { + "easting": 635700.30501386744, + "northing": 222610.69723281066, + "distance": 438.67663386391445, + "elevation": 113.68403625488281, + "red": 255, + "green": 142, + "blue": 0, + }, + { + "easting": 635706.89445985272, + "northing": 222618.2191475674, + "distance": 448.67663386393855, + "elevation": 113.68403625488281, + "red": 255, + "green": 142, + "blue": 0, + }, + { + "easting": 635713.48390583799, + "northing": 222625.74106232414, + "distance": 458.67663386396265, + "elevation": 114.25257873535156, + "red": 255, + "green": 139, + "blue": 0, + }, + { + "easting": 635720.07335182326, + "northing": 222633.26297708089, + "distance": 468.67663386398675, + "elevation": 114.11537933349609, + "red": 255, + "green": 140, + "blue": 0, + }, + { + "easting": 635726.66279780853, + "northing": 222640.78489183763, + "distance": 478.67663386401085, + "elevation": 114.12395477294922, + "red": 255, + "green": 140, + "blue": 0, + }, + { + "easting": 635733.2522437938, + "northing": 222648.30680659437, + "distance": 488.67663386403495, + "elevation": 115.76699829101562, + "red": 255, + "green": 129, + "blue": 0, + }, + { + "easting": 635739.84168977907, + "northing": 222655.82872135111, + "distance": 498.67663386405906, + "elevation": 116.54743957519531, + "red": 254, + "green": 127, + "blue": 1, + }, + { + "easting": 635746.43113576435, + "northing": 222663.35063610785, + "distance": 508.67663386408316, + "elevation": 117.67246246337891, + "red": 250, + "green": 127, + "blue": 5, + }, +] + class TestProfileNCSPM(TestCase): @classmethod @@ -217,6 +700,79 @@ def test_profile_directions(self): self.assertModule(rprofile) self.assertMultiLineEqual(rprofile.outputs.stdout.strip(), output5.strip()) + def test_profile_json(self): + module = SimpleModule( + "r.profile", + input="elevation", + flags="g", + format="json", + coordinates=[ + 635747, + 222664, + 635673, + 222717, + 635563, + 222634, + 635641, + 222543, + 635747, + 222664, + ], + ) + self.runModule(module) + + expected = [] + lines = output5.strip().split("\n") + for line in lines: + parts = line.split(" ") + expected.append( + { + "easting": float(parts[0]), + "northing": float(parts[1]), + "distance": float(parts[2]), + "elevation": float(parts[3]), + } + ) + result = json.loads(module.outputs.stdout) + + for entry1, entry2 in zip_longest(expected, result): + self.assertAlmostEqual(entry1["easting"], entry2["easting"], places=6) + self.assertAlmostEqual(entry1["northing"], entry2["northing"], places=6) + self.assertAlmostEqual(entry1["distance"], entry2["distance"], places=6) + self.assertAlmostEqual(entry1["elevation"], entry2["elevation"], places=6) + + def test_profile_json_color(self): + module = SimpleModule( + "r.profile", + input="elevation", + flags="gc", + format="json", + coordinates=[ + 635747, + 222664, + 635673, + 222717, + 635563, + 222634, + 635641, + 222543, + 635747, + 222664, + ], + ) + self.runModule(module) + + expected = output_json_with_color + result = json.loads(module.outputs.stdout) + for entry1, entry2 in zip_longest(expected, result): + self.assertAlmostEqual(entry1["easting"], entry2["easting"], places=6) + self.assertAlmostEqual(entry1["northing"], entry2["northing"], places=6) + self.assertAlmostEqual(entry1["distance"], entry2["distance"], places=6) + self.assertAlmostEqual(entry1["elevation"], entry2["elevation"], places=6) + self.assertEqual(entry1["red"], entry2["red"]) + self.assertEqual(entry1["blue"], entry2["blue"]) + self.assertEqual(entry1["green"], entry2["green"]) + if __name__ == "__main__": test()