[GRASS-SVN] r72581 - grass-addons/grass7/raster/r.spread.sod

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Mar 26 15:33:18 PDT 2018


Author: wenzeslaus
Date: 2018-03-26 15:33:18 -0700 (Mon, 26 Mar 2018)
New Revision: 72581

Modified:
   grass-addons/grass7/raster/r.spread.sod/CHANGELOG.md
   grass-addons/grass7/raster/r.spread.sod/main.cpp
Log:
r.spread.sod: probability and signle run outputs

Plus overall sync with upstream branch single_species
(https://github.com/ncsu-landscape-dynamics/SOD-modeling-cpp)
which was updated with changes from here.


Modified: grass-addons/grass7/raster/r.spread.sod/CHANGELOG.md
===================================================================
--- grass-addons/grass7/raster/r.spread.sod/CHANGELOG.md	2018-03-26 21:27:59 UTC (rev 72580)
+++ grass-addons/grass7/raster/r.spread.sod/CHANGELOG.md	2018-03-26 22:33:18 UTC (rev 72581)
@@ -4,6 +4,16 @@
 
 The format is based on [Keep a Changelog](http://keepachangelog.com/).
 
+## 2017-09-05 - March 2018 update
+
+### Changed
+
+- Changes for automatic compilation in GRASS GIS Addons (Vaclav Petras)
+ - GDAL support optional using ifdef
+ - NetCDF support optional using ifdef
+ - Explicitly include necessary standard C++ headers
+ - Add formalities: basic documentation and a proper GRASS module name
+
 ## 2017-09-05 - September 2017 update
 
 ### Added
@@ -17,11 +27,14 @@
    can be used multiple times, i.e. temporal oversampling is possible).
  - Weather rasters are now automatically resampled on the fly to the
    raster grid based the computational region.
+- Output probability of cell being infected (Vaclav Petras)
+- Optionally output one run for series instead of an average (Vaclav Petras)
 
 ### Changed
 
 - Spread of SOD based on a single species (Anna Petrasova)
  - Spread for UMCA and oak replaced by single species, assumed tanoak.
+- Final infected trees output is now optional (Vaclav Petras)
 
 ### Fixed
 

Modified: grass-addons/grass7/raster/r.spread.sod/main.cpp
===================================================================
--- grass-addons/grass7/raster/r.spread.sod/main.cpp	2018-03-26 21:27:59 UTC (rev 72580)
+++ grass-addons/grass7/raster/r.spread.sod/main.cpp	2018-03-26 22:33:18 UTC (rev 72581)
@@ -43,6 +43,8 @@
 #include <sstream>
 #include <string>
 
+#include <sys/stat.h>
+
 using std::string;
 using std::cout;
 using std::cerr;
@@ -51,6 +53,18 @@
 
 #define DIM 1
 
+// check if a file exists
+inline bool file_exists(const char* name) {
+  struct stat buffer;
+  return (stat(name, &buffer) == 0);
+}
+
+inline void file_exists_or_fatal_error(struct Option* option) {
+    if (option->answer && !file_exists(option->answer))
+        G_fatal_error(_("Option %s: File %s does not exist"),
+                      option->key, option->answer);
+}
+
 // Initialize infected trees for each species
 // needed unless empirical info is available
 static Img initialize(Img& img1,Img& img2) {
@@ -234,11 +248,13 @@
     struct Option *seed, *runs, *threads;
     struct Option *output, *output_series;
     struct Option *stddev, *stddev_series;
+    struct Option *output_probability;
 };
 
 struct SodFlags
 {
     struct Flag *generate_seed;
+    struct Flag *series_as_single_run;
 };
 
 
@@ -275,6 +291,7 @@
 
     opt.output = G_define_standard_option(G_OPT_R_OUTPUT);
     opt.output->guisection = _("Output");
+    opt.output->required = NO;
 
     opt.output_series = G_define_standard_option(G_OPT_R_BASENAME_OUTPUT);
     opt.output_series->key = "output_series";
@@ -295,6 +312,20 @@
     opt.stddev_series->required = NO;
     opt.stddev_series->guisection = _("Output");
 
+    flg.series_as_single_run = G_define_flag();
+    flg.series_as_single_run->key = 'l';
+    flg.series_as_single_run->label =
+        _("The output series as a single run only, not average");
+    flg.series_as_single_run->description =
+        _("The first run will be used for output instead of average");
+    flg.series_as_single_run->guisection = _("Output");
+
+    opt.output_probability = G_define_standard_option(G_OPT_R_OUTPUT);
+    opt.output_probability->key = "probability";
+    opt.output_probability->description = _("Infection probability (in percent)");
+    opt.output_probability->required = NO;
+    opt.output_probability->guisection = _("Output");
+
     opt.outside_spores = G_define_standard_option(G_OPT_V_OUTPUT);
     opt.outside_spores->key = "outside_spores";
     opt.outside_spores->required = NO;
@@ -459,6 +490,9 @@
     opt.threads->options = "1-";
     opt.threads->guisection = _("Randomness");
 
+    G_option_required(opt.output, opt.output_series, opt.output_probability,
+                      opt.outside_spores, NULL);
+
     G_option_exclusive(opt.seed, flg.generate_seed, NULL);
     G_option_required(opt.seed, flg.generate_seed, NULL);
 
@@ -480,6 +514,11 @@
     if (opt.threads->answer)
         threads = std::stoul(opt.threads->answer);
 
+    // check for file existence
+    file_exists_or_fatal_error(opt.moisture_file);
+    file_exists_or_fatal_error(opt.temperature_file);
+    file_exists_or_fatal_error(opt.weather_file);
+
     // Seasonality: Do you want the spread to be limited to certain months?
     bool ss = seasonality_from_string(opt.seasonality->answer);
 
@@ -685,18 +724,22 @@
                 }
                 unresolved_weeks.clear();
             }
-            if (opt.output_series->answer || opt.stddev_series->answer) {
-                // aggregate
+            if ((opt.output_series->answer && !flg.series_as_single_run->answer)
+                     || opt.stddev_series->answer) {
+                // aggregate in the series
                 I_species_rast.zero();
                 for (unsigned i = 0; i < num_runs; i++)
                     I_species_rast += inf_species_rasts[i];
                 I_species_rast /= num_runs;
+            }
+            if (opt.output_series->answer) {
                 // write result
                 // date is always end of the year, even for seasonal spread
-                if (opt.output_series->answer) {
-                    string name = generate_name(opt.output_series->answer, dd_start);
+                string name = generate_name(opt.output_series->answer, dd_start);
+                if (flg.series_as_single_run->answer)
+                    inf_species_rasts[0].toGrassRaster(name.c_str());
+                else
                     I_species_rast.toGrassRaster(name.c_str());
-                }
             }
             if (opt.stddev_series->answer) {
                 Img stddev(I_species_rast.getWidth(), I_species_rast.getHeight(),
@@ -716,14 +759,17 @@
             break;
     }
 
-    // aggregate
-    I_species_rast.zero();
-    for (unsigned i = 0; i < num_runs; i++)
-        I_species_rast += inf_species_rasts[i];
-    I_species_rast /= num_runs;
-    // write final result
-    I_species_rast.toGrassRaster(opt.output->answer);
-
+    if (opt.output->answer || opt.stddev->answer) {
+        // aggregate
+        I_species_rast.zero();
+        for (unsigned i = 0; i < num_runs; i++)
+            I_species_rast += inf_species_rasts[i];
+        I_species_rast /= num_runs;
+    }
+    if (opt.output->answer) {
+        // write final result
+        I_species_rast.toGrassRaster(opt.output->answer);
+    }
     if (opt.stddev->answer) {
         Img stddev(I_species_rast.getWidth(), I_species_rast.getHeight(),
                    I_species_rast.getWEResolution(), I_species_rast.getNSResolution(), 0);
@@ -735,6 +781,18 @@
         stddev.for_each([](int& a){a = std::sqrt(a);});
         stddev.toGrassRaster(opt.stddev->answer);
     }
+    if (opt.output_probability->answer) {
+        Img probability(I_species_rast.getWidth(), I_species_rast.getHeight(),
+                        I_species_rast.getWEResolution(), I_species_rast.getNSResolution(), 0);
+        for (unsigned i = 0; i < num_runs; i++) {
+            Img tmp = inf_species_rasts[i];
+            tmp.for_each([](int& a){a = bool(a);});
+            probability += tmp;
+        }
+        probability *= 100;  // prob from 0 to 100 (using ints)
+        probability /= num_runs;
+        probability.toGrassRaster(opt.output_probability->answer);
+    }
     if (opt.outside_spores->answer) {
         Cell_head region;
         Rast_get_window(&region);



More information about the grass-commit mailing list