[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(®ion);
More information about the grass-commit
mailing list