[GRASS-SVN] r50997 - in grass-addons/grass6: . dst dst/include
dst/include/gt dst/lib dst/lib/gt_raster dst/lib/gt_stats
dst/lib/gt_vector dst/misc dst/misc/m.dst.create
dst/misc/m.dst.source dst/misc/m.dst.update
dst/misc/m.dst.view dst/misc/m.filter.gen dst/raster
dst/raster/r.categorize dst/raster/r.dst.combine
dst/raster/r.dst.predict.bpn dst/raster/r.dst.predict.run
dst/vector dst/vector/v.random.sample dst/vector/v.report.dist
svn_grass at osgeo.org
svn_grass at osgeo.org
Mon Mar 5 16:58:35 EST 2012
Author: neteler
Date: 2012-03-05 13:58:34 -0800 (Mon, 05 Mar 2012)
New Revision: 50997
Added:
grass-addons/grass6/dst/
grass-addons/grass6/dst/Makefile
grass-addons/grass6/dst/include/
grass-addons/grass6/dst/include/gt/
grass-addons/grass6/dst/include/gt/cat_engine.h
grass-addons/grass6/dst/include/gt/gstats_error.h
grass-addons/grass6/dst/include/gt/gstats_gain.h
grass-addons/grass6/dst/include/gt/gstats_global.h
grass-addons/grass6/dst/include/gt/gstats_tests.h
grass-addons/grass6/dst/include/gt/gt_vector.h
grass-addons/grass6/dst/include/gt/rowcache.h
grass-addons/grass6/dst/lib/
grass-addons/grass6/dst/lib/Makefile
grass-addons/grass6/dst/lib/gt_raster/
grass-addons/grass6/dst/lib/gt_raster/Makefile
grass-addons/grass6/dst/lib/gt_raster/cat_engine.c
grass-addons/grass6/dst/lib/gt_raster/rowcache.c
grass-addons/grass6/dst/lib/gt_stats/
grass-addons/grass6/dst/lib/gt_stats/Makefile
grass-addons/grass6/dst/lib/gt_stats/gstats_error.c
grass-addons/grass6/dst/lib/gt_stats/gstats_gain.c
grass-addons/grass6/dst/lib/gt_stats/gstats_tests.c
grass-addons/grass6/dst/lib/gt_vector/
grass-addons/grass6/dst/lib/gt_vector/Makefile
grass-addons/grass6/dst/lib/gt_vector/gt_vector.c
grass-addons/grass6/dst/misc/
grass-addons/grass6/dst/misc/Makefile
grass-addons/grass6/dst/misc/m.dst.create/
grass-addons/grass6/dst/misc/m.dst.create/Makefile
grass-addons/grass6/dst/misc/m.dst.create/description.html
grass-addons/grass6/dst/misc/m.dst.create/main.c
grass-addons/grass6/dst/misc/m.dst.source/
grass-addons/grass6/dst/misc/m.dst.source/Makefile
grass-addons/grass6/dst/misc/m.dst.source/description.html
grass-addons/grass6/dst/misc/m.dst.source/main.c
grass-addons/grass6/dst/misc/m.dst.update/
grass-addons/grass6/dst/misc/m.dst.update/Makefile
grass-addons/grass6/dst/misc/m.dst.update/description.html
grass-addons/grass6/dst/misc/m.dst.update/main.c
grass-addons/grass6/dst/misc/m.dst.view/
grass-addons/grass6/dst/misc/m.dst.view/Makefile
grass-addons/grass6/dst/misc/m.dst.view/description.html
grass-addons/grass6/dst/misc/m.dst.view/main.c
grass-addons/grass6/dst/misc/m.filter.gen/
grass-addons/grass6/dst/misc/m.filter.gen/gaussgen
grass-addons/grass6/dst/misc/m.filter.gen/main.c
grass-addons/grass6/dst/misc/m.filter.gen/main.org
grass-addons/grass6/dst/raster/
grass-addons/grass6/dst/raster/Makefile
grass-addons/grass6/dst/raster/r.categorize/
grass-addons/grass6/dst/raster/r.categorize/Makefile
grass-addons/grass6/dst/raster/r.categorize/description.html
grass-addons/grass6/dst/raster/r.categorize/main.c
grass-addons/grass6/dst/raster/r.dst.combine/
grass-addons/grass6/dst/raster/r.dst.combine/Makefile
grass-addons/grass6/dst/raster/r.dst.combine/defs.h
grass-addons/grass6/dst/raster/r.dst.combine/description.html
grass-addons/grass6/dst/raster/r.dst.combine/dst.c
grass-addons/grass6/dst/raster/r.dst.combine/dst.combine.001.png
grass-addons/grass6/dst/raster/r.dst.combine/dst.combine.002.png
grass-addons/grass6/dst/raster/r.dst.combine/dst.combine.003.png
grass-addons/grass6/dst/raster/r.dst.combine/dst.h
grass-addons/grass6/dst/raster/r.dst.combine/file_io.c
grass-addons/grass6/dst/raster/r.dst.combine/file_io.h
grass-addons/grass6/dst/raster/r.dst.combine/garbage.c
grass-addons/grass6/dst/raster/r.dst.combine/garbage.h
grass-addons/grass6/dst/raster/r.dst.combine/globals.h
grass-addons/grass6/dst/raster/r.dst.combine/main.c
grass-addons/grass6/dst/raster/r.dst.combine/main.h
grass-addons/grass6/dst/raster/r.dst.combine/print.c
grass-addons/grass6/dst/raster/r.dst.combine/print.h
grass-addons/grass6/dst/raster/r.dst.combine/readme
grass-addons/grass6/dst/raster/r.dst.combine/sets.c
grass-addons/grass6/dst/raster/r.dst.combine/sets.h
grass-addons/grass6/dst/raster/r.dst.combine/structs.h
grass-addons/grass6/dst/raster/r.dst.predict.bpn/
grass-addons/grass6/dst/raster/r.dst.predict.bpn/Makefile
grass-addons/grass6/dst/raster/r.dst.predict.bpn/description.html
grass-addons/grass6/dst/raster/r.dst.predict.bpn/main.c
grass-addons/grass6/dst/raster/r.dst.predict.bpn/r.dst.bpn.001.png
grass-addons/grass6/dst/raster/r.dst.predict.run/
grass-addons/grass6/dst/raster/r.dst.predict.run/Makefile
grass-addons/grass6/dst/raster/r.dst.predict.run/description.html
grass-addons/grass6/dst/raster/r.dst.predict.run/main.c
grass-addons/grass6/dst/vector/
grass-addons/grass6/dst/vector/Makefile
grass-addons/grass6/dst/vector/v.random.sample/
grass-addons/grass6/dst/vector/v.random.sample/Makefile
grass-addons/grass6/dst/vector/v.random.sample/description.html
grass-addons/grass6/dst/vector/v.random.sample/main.c
grass-addons/grass6/dst/vector/v.report.dist/
grass-addons/grass6/dst/vector/v.report.dist/Makefile
grass-addons/grass6/dst/vector/v.report.dist/description.html
grass-addons/grass6/dst/vector/v.report.dist/main.c
Log:
benjamin: DST (Dempster?\226?\128?\147Shafer) modelling
Added: grass-addons/grass6/dst/Makefile
===================================================================
--- grass-addons/grass6/dst/Makefile (rev 0)
+++ grass-addons/grass6/dst/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,15 @@
+MODULE_TOPDIR = ..
+
+SUBDIRS = \
+ lib \
+ misc \
+ raster \
+ vector
+
+include $(MODULE_TOPDIR)/include/Make/Dir.make
+
+default: htmldir
+
+htmldir: subdirs
+
+clean: cleansubdirs
Property changes on: grass-addons/grass6/dst/Makefile
___________________________________________________________________
Added: svn:mime-type
+ text/x-makefile
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/include/gt/cat_engine.h
===================================================================
--- grass-addons/grass6/dst/include/gt/cat_engine.h (rev 0)
+++ grass-addons/grass6/dst/include/gt/cat_engine.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,87 @@
+/* CAT_ENGINE.H */
+
+/* Part of the GRASS Toolkit (GT) functions collection */
+/* Purpose: provide functions for handling categories in GRASS raster maps. */
+
+/* Usage: 1. call GT_set_decdigits (unsigned int digits) (!) to set decimal precision (e.g. 3) */
+/* 2. use GT_get_stats () on a GRASS raster map to get basic category information */
+/* 3. use GT_get_* functions for more information */
+/* 4. use GT_set_* functions to create categories for a raster map */
+/* functions GT_set_f_* are for floating point rasters (FCELL ord DCELL) */
+/* functions GT_set_c_* are for integer rasters */
+/* functions GT_set_* determine mode automatically */
+/* 5. the output map will always be a CELL map with values 0..N, each being a category */
+/* output map is always fully categorised, i.e. each cell a category or NULL */
+/* Take a look at 'cat_engine.c' for detailed descriptions of functions */
+
+
+/* This file is licensed under the GPL (version 2 ) */
+/* see: http://www.gnu.org/copyleft/gpl.html */
+
+/* (c) Benjamin Ducke 2004 */
+/* benducke at compuserve.de */
+
+#ifndef GT_CAT_ENGINE_H
+#define GT_CAT_ENGINE_H
+
+unsigned int GT_DECDIGITS; /* number of decimal digits for statistics/logfile */
+
+/* USER MUST CALL THIS FUNCTION FIRST */
+/* to determine number of decimal digits in history files */
+/* and category labels. Otherwise it will be garbage! */
+void GT_set_decdigits (unsigned int digits);
+
+/* functions for any type of GRASS raster maps */
+/* these determine the map mode and automatically call map type */
+/* specific functions below */
+int GT_get_stats (char *name, char *mapset, long *null_count,
+ long *nocat_count, int print_progress);
+int GT_get_range (char *name, char *mapset, double *min,
+ double *max, int print_progress);
+long *GT_get_counts (char *name, char *mapset, int print_progress);
+char **GT_get_labels (char *name, char *mapset);
+int GT_set_cats_only (char *name, char *mapset, char *output, int fp, int print_progress);
+int GT_set_cats_num (char *name, char *mapset, char *output,
+ double rmin, double rmax, int num, int intout, int print_progress);
+int GT_set_cats_width (char *name, char *mapset, char *output,
+ double rmin, double rmax, double width, int round_cat,
+ int intout, int print_progress);
+
+/* functions for categories in CELL files */
+int GT_get_c_stats (char *name, char *mapset, long *null_count,
+ long *nocat_count, int print_progress);
+int GT_get_c_range (char *name, char *mapset, int *min,
+ int *max, int print_progress);
+long *GT_get_c_counts (char *name, char *mapset, int print_progress);
+char **GT_get_c_labels (char *name, char *mapset);
+int GT_set_c_cats_only (char *name, char *mapset, char *output, int print_progress);
+int GT_set_c_cats_scale (char *name, char *mapset, char *output,
+ int rmin, int rmax, int print_progress);
+int GT_set_c_cats_num (char *name, char *mapset, char *output,
+ int rmin, int rmax, int num, int print_progress);
+int GT_set_c_cats_width (char *name, char *mapset, char *output,
+ int rmin, int rmax, int width, int print_progress);
+
+/* functions for categories in DCELL/FCELL files */
+/* all of these work with double (DCELL) precision internally */
+int GT_get_f_stats (char *name, char *mapset, long *null_count,
+ long *nocat_count, int print_progress);
+int GT_get_f_range (char *name, char *mapset, double *min,
+ double *max, int print_progress);
+long *GT_get_f_counts (char *name, char *mapset, int print_progress);
+char **GT_get_f_labels (char *name, char *mapset);
+int GT_set_f_cats_only (char *name, char *mapset, char *output, int fp, int print_progress);
+int GT_set_f_cats_round (char *name, char *mapset, char *output,
+ double rmin, double rmax, int print_progress);
+int GT_set_f_cats_trunc (char *name, char *mapset, char *output,
+ double rmin, double rmax, int print_progress);
+int GT_set_f_cats_num (char *name, char *mapset, char *output,
+ double rmin, double rmax, int num, int intout, int print_progress);
+int GT_set_f_cats_width (char *name, char *mapset, char *output,
+ double rmin, double rmax, double width, int round_cat,
+ int intout, int print_progress);
+
+/* auxillary functions */
+int GT_write_hist (char *name, char* source, char *desc, char *comment);
+
+#endif /* GT_CAT_ENGINE_H */
Property changes on: grass-addons/grass6/dst/include/gt/cat_engine.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/include/gt/gstats_error.h
===================================================================
--- grass-addons/grass6/dst/include/gt/gstats_error.h (rev 0)
+++ grass-addons/grass6/dst/include/gt/gstats_error.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,10 @@
+/* A simple error handler */
+
+#ifndef __GSTATS_ERROR_H__
+#define __GSTATS_ERROR_H__
+
+void gstats_error ( char *message );
+void gstats_error_warning ( void );
+void gstats_error_fatal ( void );
+
+#endif /* __GSTATS_ERROR_H__ */
Property changes on: grass-addons/grass6/dst/include/gt/gstats_error.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/include/gt/gstats_gain.h
===================================================================
--- grass-addons/grass6/dst/include/gt/gstats_gain.h (rev 0)
+++ grass-addons/grass6/dst/include/gt/gstats_gain.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,9 @@
+/* Some high-level statistical tests */
+
+#ifndef __GSTATS_GAIN_H__
+#define __GSTATS_GAIN_H__
+
+double gstats_gain_K (double sample, double area);
+
+
+#endif /* __GSTATS_GAIN_H__ */
Property changes on: grass-addons/grass6/dst/include/gt/gstats_gain.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/include/gt/gstats_global.h
===================================================================
--- grass-addons/grass6/dst/include/gt/gstats_global.h (rev 0)
+++ grass-addons/grass6/dst/include/gt/gstats_global.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,8 @@
+/* Global vars and structs */
+
+#ifndef __GSTATS_GLOBAL_H__
+#define __GSTATS_GLOBAL_H__
+
+short int GSTATS_FATAL = 1;
+
+#endif /* __GSTATS_GLOBAL_H__ */
Property changes on: grass-addons/grass6/dst/include/gt/gstats_global.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/include/gt/gstats_tests.h
===================================================================
--- grass-addons/grass6/dst/include/gt/gstats_tests.h (rev 0)
+++ grass-addons/grass6/dst/include/gt/gstats_tests.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,13 @@
+/* Some high-level statistical tests */
+
+#ifndef __GSTATS_TESTS_H__
+#define __GSTATS_TESTS_H__
+
+double gstats_test_XF (int *observed, int *expected, int k, int df);
+double gstats_rtest_XF (int *observed, int *expected, int k, int df);
+double gstats_test_ZP2 (double p_sample, double p_population, int n);
+double gstats_test_ZPL (double p_sample, double p_population, int n);
+double gstats_test_ZPU (double p_sample, double p_population, int n);
+
+
+#endif /* __GSTATS_TESTS_H__ */
Property changes on: grass-addons/grass6/dst/include/gt/gstats_tests.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/include/gt/gt_vector.h
===================================================================
--- grass-addons/grass6/dst/include/gt/gt_vector.h (rev 0)
+++ grass-addons/grass6/dst/include/gt/gt_vector.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,176 @@
+/***************************************************************************
+ * gt_vector.h
+ *
+ * Mon Apr 18 15:23:06 2005
+ * Copyright 2005 Benjamin Ducke
+ ****************************************************************************/
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _GT_VECTOR_H
+#define _GT_VECTOR_H
+
+#include <grass/gis.h>
+#include <grass/dbmi.h>
+#include <grass/Vect.h>
+
+/* states for attribute caches */
+#define GVT_CACHE_DIRTY -1 /* means we have to rebuild the cache by reading in all attributes */
+#define GVT_CACHE_INIT 0 /* means we need to initialize this cache */
+#define GVT_CACHE_CLEAN 1 /* this cache is fine. Can use it to get attributes */
+#define GVT_CACHE_OFF 2 /* this cache is turned off: read attributes the slow way! */
+
+#define GVT_MAX_STRING_SIZE 4096
+#define GVT_EMPTY_SQL "GVT_SEQ_EMPTY"
+
+/* any type of attribute */
+#define GVT_ATT
+/* specific types of attributes. Thes mape 1:1 to the main types in grass/dbmi.h */
+#define GVT_DOUBLE DB_C_TYPE_DOUBLE
+#define GVT_INT DB_C_TYPE_INT
+#define GVT_STRING DB_C_TYPE_STRING
+#define GVT_DATETIME DB_C_TYPE_DATETIME
+
+/* any type of geometry */
+#define GVT_GEOM
+/* specific types of geometry. These map 1:1 to grass/vect/dig_defines.h */
+#define GVT_POINT GV_POINT
+#define GVT_LINE GV_LINE
+#define GVT_BOUNDARY GV_BOUNDARY
+#define GVT_CENTROID GV_CENTROID
+#define GVT_AREA GV_AREA
+/* 3D geometries */
+#define GVT_KERNEL GV_KERNEL
+#define GVT_FACE GV_FACE
+#define GVT_VOLUME GV_VOLUME
+/* Combination types */
+#define GV_2D_POINT (GVT_POINT | GVT_CENTROID)
+#define GV_2D_LINE (GVT_LINE | GVT_BOUNDARY)
+/* the following are additions for GVT */
+/* any 2D geometry */
+#define GVT_2D_GEOM (GVT_POINT | GVT_LINE | GVT_BOUNDARY | GVT_CENTROID | GVT_AREA)
+/* any 3D geometry */
+#define GVT_3D_GEOM (GVT_KERNEL | GVT_FACE | GVT_VOLUME)
+
+
+
+typedef struct GVT_map {
+ /* name and mapset in GRASS database */
+ char name[GVT_MAX_STRING_SIZE];
+ char mapset[GVT_MAX_STRING_SIZE];
+
+ /* set this to TRUE (1), if a vector map was opened successfully */
+ short int hasData;
+
+ /* infos on number of layers (DB link=table) and records (row of DB values=attributes) */
+ /* num_attributes is the number of columns (including CAT) in a table */
+ int num_layers; /* tables (layers) are called fields in the GRASS vect API */
+ long int num_records;
+ int num_attributes;
+
+ int current_layer; /* -1 means: parse ALL layers! */
+ long int current_record;
+
+ struct Map_info in_vect_map;
+ struct line_pnts *vect_points;
+ struct line_cats *vect_cats;
+ struct field_info *field; /* a pointer to the current table (=field=layer) */
+ int dbncols;
+ char sql_buf[GVT_MAX_STRING_SIZE];
+ dbString sql, str;
+ dbDriver *driver;
+ dbHandle handle;
+ dbCursor cursor;
+ dbTable *table;
+
+ /* topology properties */
+ short int open_level;
+
+ /* coordinate data properties */
+ short int is3d;
+ short int isLatLong;
+ short int type;
+
+ /* constraints */
+ double north, south, east, west, top, bottom;
+ int type_constraints;
+
+ /* attribute cache and memory ops */
+ char **att_names; /* list of attribute names */
+ short int *att_types; /* list of attribute types (GVT geometry types) */
+
+ short int *cache_status;
+ double **cache_double;
+ long int **cache_int;
+ char **cache_char;
+ char **cache_datetime;
+
+ /* this is for tracking the total amount of memory claimed by this map */
+ size_t mem_size;
+
+} GVT_map_s;
+
+
+/* these global variables are set to default values by GVT_init () */
+int GVT_NO_REGION_CONSTRAINTS;
+int GVT_NO_TYPE_CONSTRAINTS;
+int GVT_NO_SQL_CONSTRAINTS;
+
+int GVT_NO_ATTRIBUTE_CACHING;
+long int GVT_MAX_CACHE_SIZE;
+
+/* if set, GRASS module will terminate on file I/O errors */
+int GVT_FATAL_FILE_ERRORS;
+int GVT_FATAL_TYPE_ERRORS;
+int GVT_FATAL_MEM_ERRORS;
+
+int GVT_INIT_DONE;
+
+/**** FUNCTIONS *****/
+
+void GVT_init ( void );
+
+GVT_map_s *GVT_new_map ( void );
+int GVT_free_map ( GVT_map_s *map );
+
+int GVT_open_map ( char *mapname, int type, GVT_map_s *map );
+int GVT_open_map_points ( char *mapname, int type, GVT_map_s *map );
+void GVT_close_map ( GVT_map_s *map );
+
+int GVT_next ( GVT_map_s *map );
+int GVT_seek ( long int pos, GVT_map_s *map );
+void GVT_first ( GVT_map_s *map );
+void GVT_last ( GVT_map_s *map );
+void GVT_rewind ( GVT_map_s *map );
+long int GVT_get_current ( GVT_map_s *map );
+
+int GVT_attr_exists ( char *name, int type, GVT_map_s *map );
+int GVT_any_exists ( char *name, GVT_map_s *map );
+int GVT_double_exists ( char *name, GVT_map_s *map );
+int GVT_int_exists ( char *name, GVT_map_s *map );
+
+double GVT_get_double ( char *name, GVT_map_s *map);
+long int GVT_get_int ( char *name, GVT_map_s *map);
+int GVT_set_double ( char *name, double dvalue, GVT_map_s *map );
+int GVT_add_double ( char *name, GVT_map_s *map );
+
+long int GVT_get_num_objects ( GVT_map_s *map );
+
+double GVT_get_2D_point_distance ( double x, double y, GVT_map_s *map );
+
+
+#endif /* _GT_VECTOR_H */
Property changes on: grass-addons/grass6/dst/include/gt/gt_vector.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/include/gt/rowcache.h
===================================================================
--- grass-addons/grass6/dst/include/gt/rowcache.h (rev 0)
+++ grass-addons/grass6/dst/include/gt/rowcache.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,53 @@
+/* ROWCACHE.H */
+
+/* Part of the GRASS Toolkit (GT) functions collection */
+/* Purpose: provide a raster cache that retrieves rows from memory instead of disk, if possible. */
+/* This should speed up operations where the same row has to be read more than once. */
+
+/* Usage: 1. use GT_RC_open () to attach a row cache to any type of GRASS raster map */
+/* 2. instead of G_get_raster_row (), use GT_RC_get to get a row of raster data from the cache */
+/* 3. call GT_RC_done () instead of G_close () when done with raster operations */
+
+
+/* This file is licensed under the GPL (version 2) */
+/* see: http://www.gnu.org/copyleft/gpl.html */
+
+/* (c) Benjamin Ducke 2004 */
+/* benducke at compuserve.de */
+
+#ifndef GT_ROWCACHE_H
+#define GT_ROWCACHE_H
+
+#include <grass/gis.h>
+
+typedef struct
+{
+ long max; /* nax index of row in cache */
+ long allocated; /* number of rows currently in cache */
+ int fd; /* file descriptor: points to cached GRASS rast map */
+ long worst; /* index of the row that has had the most cache misses */
+ long region_rows; /* stores extent of current region for faster access */
+ long region_cols;
+ RASTER_MAP_TYPE data_type; /* CELL, DCELL or FCELL */
+ CELL **c_cache_area; /* n pointers to a row of FCELL, DCELL or CELL data */
+ DCELL **d_cache_area; /* n pointers to a row of FCELL, DCELL or CELL data */
+ FCELL **f_cache_area; /* n pointers to a row of FCELL, DCELL or CELL data */
+ long *misses; /* records the number of cache misses for each row */
+ long *allocated_lookup; /* contains row numbers of all rows currently in cache */
+ short int off;
+} GT_Row_cache_t;
+
+/* initialise row cache. */
+/* n is the number of rows to keep in cache */
+/* fd is the file to be cached */
+/* 0 = success */
+/* -1 = failure */
+int GT_RC_open (GT_Row_cache_t *cache, long n, int fd, RASTER_MAP_TYPE data_type);
+
+/* retreives a row from the cache */
+void* GT_RC_get (GT_Row_cache_t *cache, long i);
+
+/* closes cache, frees allocated memory */
+void GT_RC_close (GT_Row_cache_t *cache);
+
+#endif /* GT_ROWCACHE_H */
Property changes on: grass-addons/grass6/dst/include/gt/rowcache.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/lib/Makefile
===================================================================
--- grass-addons/grass6/dst/lib/Makefile (rev 0)
+++ grass-addons/grass6/dst/lib/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,14 @@
+MODULE_TOPDIR = ..
+
+SUBDIRS = \
+ gt_raster \
+ gt_stats \
+ gt_vector
+
+include $(MODULE_TOPDIR)/include/Make/Dir.make
+
+default: htmldir
+
+htmldir: subdirs
+
+clean: cleansubdirs
Added: grass-addons/grass6/dst/lib/gt_raster/Makefile
===================================================================
--- grass-addons/grass6/dst/lib/gt_raster/Makefile (rev 0)
+++ grass-addons/grass6/dst/lib/gt_raster/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,15 @@
+MODULE_TOPDIR = ../..
+
+LIB_NAME = gt_raster
+LIB_OBJS = cat_engine.o rowcache.o
+EXTRA_CFLAGS = -I../../include
+EXTRA_LIBS = $(GISLIB) $(MATHLIB)
+
+include $(MODULE_TOPDIR)/include/Make/Lib.make
+
+default: lib headers
+
+headers:
+ if [ ! -d $(GISBASE)/include ]; then $(MKDIR) $(GISBASE)/include; fi
+ if [ ! -d $(GISBASE)/include/gt ]; then $(MKDIR) $(GISBASE)/include/gt; fi
+ $(INSTALL) -m 644 ../../include/gt/*.h $(GISBASE)/include/gt/
Added: grass-addons/grass6/dst/lib/gt_raster/cat_engine.c
===================================================================
--- grass-addons/grass6/dst/lib/gt_raster/cat_engine.c (rev 0)
+++ grass-addons/grass6/dst/lib/gt_raster/cat_engine.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,2791 @@
+/* CAT_ENGINE.C */
+
+/* Purpose: Provides functions for easy categorisation of GRASS raster */
+/* maps in CELL, DCELL or FCELL format. */
+/* FCELL maps will be treated with double precision. */
+
+/* TODO: copy FP color tables 1:1 when using 'clean' operation on an */
+/* FP map with FP output. */
+
+/* This file is licensed under the GPL (version 2) */
+/* see: http://www.gnu.org/copyleft/gpl.html */
+
+/* (c) Benjamin Ducke 2004 */
+/* benducke at compuserve.de */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <grass/gis.h>
+#include "gt/cat_engine.h"
+
+
+/* GT_get_stats () */
+/* Read basic category information from any GRASS raster map.
+
+ ARGS: name = name of GRASS raster map
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ null_count = number of NULL cells
+ nocat_count = number of cells that do not match a category
+ (i.e. do not lie within the range 0-highest cat num)
+ print_progress = set this to '1' to have a status display
+ RETURN: number of categories, OR:
+ 0 = no categories defined
+ -1 = file open error
+ NOTE: this function calls GT_get_c_stats() or GT_get_f_stats(),
+ according to the type of input map
+*/
+int GT_get_stats (char *name, char *mapset,
+ long *null_count, long *nocat_count,
+ int print_progress) {
+
+ int fd;
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-1);
+ }
+
+ if (G_raster_map_is_fp (name, mapset)) {
+ return (GT_get_f_stats (name, mapset, null_count, nocat_count, print_progress));
+
+ } else {
+ return (GT_get_c_stats (name, mapset, null_count, nocat_count, print_progress));
+ }
+
+ return (0);
+}
+
+
+/* GT_get_c_stats () */
+/* Read basic category information from a grass CELL map.
+
+ ARGS: name = name of GRASS raster map
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ null_count = number of NULL cells
+ nocat_count = number of cells that do not match a category
+ (i.e. do not lie within the range 0-highest cat num)
+ print_progress = set this to '1' to have a status display
+ RETURN: number of categories, OR:
+ 0 = no categories defined
+ -1 = map not in CELL format
+ -2 = general file open error
+
+ NOTE: both null_count and nocat_count will be set to -1 if no categories are defined
+ in the input map!
+*/
+int GT_get_c_stats (char *name, char *mapset,
+ long *null_count, long *nocat_count,
+ int print_progress) {
+ int fd;
+ int error;
+ struct Categories cats;
+ int n_cats = 0;
+ int i,j;
+ int rows, cols;
+ CELL *cellbuf;
+ CELL value;
+
+ rows = G_window_rows ();
+ cols = G_window_cols ();
+ *null_count = 0;
+ *nocat_count = 0;
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-2);
+ }
+
+ if (G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ return (-1);
+ }
+
+ /* now, open map and get number of defined categories */
+ G_init_cats (0, "", &cats);
+ error = G_read_cats (name, mapset, &cats);
+ if (error != 0) {
+ /* no categories found */
+ G_close_cell (fd);
+ *null_count = -1;
+ *nocat_count = -1;
+ return (0);
+ }
+
+ /* this is the number of categories in the map from 0 to n_cats */
+ /* note that there might be cagefories in between 0 and n_cats */
+ /* which are undefined (including category 0). */
+ n_cats = G_number_of_cats (name, mapset) + 1;
+
+ /* now, analyse raster file */
+ if (print_progress) {
+ fprintf (stdout, "Gathering category information: \n");
+ }
+ cellbuf = G_allocate_raster_buf (CELL_TYPE);
+ for (i=0; i< rows; i++) {
+ error = G_get_raster_row (fd, cellbuf, i, CELL_TYPE);
+ for (j=0; j<cols; j++) {
+ /* check for NULL value */
+ if ( G_is_c_null_value (&cellbuf[j]) == 1) {
+ *null_count = *null_count + 1;
+ } else {
+ /* check for value outside of category range */
+ value = cellbuf[j];
+ if ( ( value < 0 ) || ( value > n_cats - 1) ) {
+ *nocat_count = *nocat_count + 1;
+ }
+ }
+ }
+ if (print_progress) {
+ G_percent (i, rows-1, 1);
+ fflush (stdout);
+ }
+ }
+
+ if (print_progress) {
+ fprintf (stdout,"\n");
+ fflush (stdout);
+ }
+ G_free (cellbuf);
+ G_close_cell (fd);
+ return (n_cats);
+}
+
+
+/* GT_get_f_stats () */
+/* Read basic category information from a grass FCELL or DCELL map.
+
+ ARGS: name = name of GRASS raster map
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ null_count = number of NULL cells
+ nocat_count = number of cells that do not match a category
+ (i.e. do not lie within the range 0-highest cat num)
+ print_progress = set this to '1' to have a status display
+ RETURN: number of categories, OR:
+ 0 = no categories defined
+ -1 = map not in FCELL or DCELL format
+ -2 = general file open error
+*/
+int GT_get_f_stats (char *name, char *mapset,
+ long *null_count, long *nocat_count,
+ int print_progress) {
+ int fd;
+ int error;
+ struct Categories cats;
+ int n_cats = 0;
+ int i,j;
+ int rows, cols;
+ DCELL *dcellbuf;
+ DCELL dvalue;
+ CELL value;
+ rows = G_window_rows ();
+ cols = G_window_cols ();
+ *null_count = 0;
+ *nocat_count = 0;
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-2);
+ }
+
+ if (!G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ return (-1);
+ }
+
+ /* now, open map and get number of defined categories */
+ G_init_cats (0, "", &cats);
+ error = G_read_cats (name, mapset, &cats);
+ if (error != 0) {
+ /* no categories found */
+ G_close_cell (fd);
+ *null_count = -1;
+ *nocat_count = -1;
+ return (0);
+ }
+
+ /* this is the number of defined (i.e labeled) categories in the map */
+ /* if it is zero, we might just as well return to caller. */
+ n_cats = G_number_of_raster_cats (&cats);
+ if (n_cats == 0) {
+ G_close_cell (fd);
+ *null_count = -1;
+ *nocat_count = -1;
+ return (0);
+ }
+
+ /* now, analyse raster file */
+ if (print_progress) {
+ fprintf (stdout, "Gathering category information: \n");
+ }
+ dcellbuf = G_allocate_raster_buf (DCELL_TYPE);
+ for (i=0; i< rows; i++) {
+ error = G_get_raster_row (fd, dcellbuf, i, DCELL_TYPE);
+ for (j=0; j<cols; j++) {
+ /* check for NULL value */
+ if ( G_is_d_null_value (&dcellbuf[j]) == 1) {
+ *null_count = *null_count + 1;
+ } else {
+ /* check for value outside of category range */
+ dvalue = dcellbuf[j];
+ value = G_quant_get_cell_value (&cats.q, dvalue);
+ if ( ( value < 0 ) || ( value > n_cats -1) ) {
+ *nocat_count = *nocat_count + 1;
+ }
+ }
+ }
+ if (print_progress) {
+ G_percent (i, rows-1, 1);
+ fflush (stdout);
+ }
+ }
+
+ G_free (dcellbuf);
+ G_close_cell (fd);
+ return (n_cats);
+}
+
+/* GT_get_range () */
+/* Find minimum and maximum values in a GRASS raster map of any type.
+
+ ARGS: name = name of GRASS raster map
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ *min = stores minimum value
+ *max = stores maximum value
+ print_progress = set this to '1' to have a status display
+ RETURN: 0 on success
+ -1 = invalid map format
+ -2 = general file open error
+ NOTE: min and max values in CELL maps will be returned as double values
+*/
+int GT_get_range (char *name, char *mapset, double *min, double *max,
+ int print_progress) {
+
+ int fd;
+ int imin;
+ int imax;
+ int error;
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-1);
+ }
+
+ if (G_raster_map_is_fp (name, mapset)) {
+ return (GT_get_f_range (name, mapset, min, max, print_progress));
+
+ } else {
+ error = GT_get_c_range (name, mapset, &imin, &imax, print_progress);
+ *min = (double) imin;
+ *max = (double) imax;
+ return (error);
+ }
+
+ return (0);
+}
+
+
+/* GT_get_c_range () */
+/* Find minimum and maximum values in a grass CELL map.
+
+ ARGS: name = name of GRASS raster map
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ *min = stores minimum value
+ *max = stores maximum value
+ print_progress = set this to '1' to have a status display
+ RETURN: 0 on success
+ -1 = map not in CELL format
+ -2 = general file open error
+*/
+int GT_get_c_range (char *name, char *mapset, int *min, int *max,
+ int print_progress) {
+ int fd;
+ int error;
+ int i,j;
+ int rows, cols;
+ CELL *cellbuf;
+ CELL value;
+ /* a few flags to control quantification of the output map */
+ int firstpass = 1;
+
+ rows = G_window_rows ();
+ cols = G_window_cols ();
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-2);
+ }
+
+ if (G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ return (-1);
+ }
+
+ /* Analyse raster file and get min and max ints */
+ cellbuf = G_allocate_raster_buf (CELL_TYPE);
+ if (print_progress) {
+ fprintf (stdout, "Finding min and max raster values: \n");
+ }
+ for (i=0; i< rows; i++) {
+ error = G_get_raster_row (fd, cellbuf, i, CELL_TYPE);
+ for (j=0; j<cols; j++) {
+ /* check for NULL value and update min and max */
+ if ( !G_is_c_null_value (&cellbuf[j]) == 1) {
+ value = cellbuf[j];
+ if ( value < *min ) {
+ *min = value;
+ }
+ if ( value > *max ) {
+ *max = value;
+ }
+ if ( firstpass ) {
+ *min = value;
+ *max = value;
+ firstpass = 0;
+ }
+ }
+ }
+ if (print_progress) {
+ G_percent (i, rows-1, 1);
+ fflush (stdout);
+ }
+ }
+
+ if (print_progress) {
+ fprintf (stdout,"\n");
+ }
+
+ G_free (cellbuf);
+ G_close_cell (fd);
+ return (0);
+}
+
+
+/* GT_get_f_range () */
+/* Find minimum and maximum values in a GRASS DCELL/FCELL map.
+
+ ARGS: name = name of GRASS raster map
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ *min = stores minimum value
+ *max = stores maximum value
+ print_progress = set this to '1' to have a status display
+ RETURN: 0 on success
+ -1 = map not in DCELL/FCELL format
+ -2 = general file open error
+*/
+int GT_get_f_range (char *name, char *mapset, double *min, double *max,
+ int print_progress) {
+ int fd;
+ int error;
+ int i,j;
+ int rows, cols;
+ DCELL *dcellbuf;
+ DCELL dvalue;
+ /* a few flags to control quantification of the output map */
+ int firstpass = 1;
+
+ rows = G_window_rows ();
+ cols = G_window_cols ();
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-2);
+ }
+
+ if (!G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ return (-1);
+ }
+
+ /* Analyse raster file and get min and max ints */
+ dcellbuf = G_allocate_raster_buf (DCELL_TYPE);
+ if (print_progress) {
+ fprintf (stdout, "Finding min and max raster values: \n");
+ }
+ for (i=0; i< rows; i++) {
+ error = G_get_raster_row (fd, dcellbuf, i, DCELL_TYPE);
+ for (j=0; j<cols; j++) {
+ /* check for NULL value and update min and max */
+ if ( !G_is_d_null_value (&dcellbuf[j]) == 1) {
+ dvalue = dcellbuf[j];
+ if ( dvalue < *min ) {
+ *min = dvalue;
+ }
+ if ( dvalue > *max ) {
+ *max = dvalue;
+ }
+ if ( firstpass ) {
+ *min = dvalue;
+ *max = dvalue;
+ firstpass = 0;
+ }
+ }
+ }
+ if (print_progress) {
+ G_percent (i, rows-1, 1);
+ fflush (stdout);
+ }
+ }
+
+ if (print_progress) {
+ fprintf (stdout,"\n");
+ }
+
+ G_free (dcellbuf);
+ G_close_cell (fd);
+ return (0);
+}
+
+
+/* GT_get_counts () */
+/* Read occurence counts of categories from any GRASS raster map.
+
+ ARGS: name = name of GRASS raster map
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ print_progress = set this to '1' to have a status display
+ RETURN: a pointer to an array of ints with category counts
+ (0 .. N)
+ NULL = no categories defined or general file error
+
+ NOTE: Number of categories in the array (i.e. array length) can
+ be obtained using get_cell_stats().
+ Memory for returned int array must not be pre-allocated by caller.
+ Memory must be free'd by caller!
+*/
+long *GT_get_counts (char *name, char *mapset, int print_progress) {
+
+ int fd;
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (NULL);
+ }
+
+ if (G_raster_map_is_fp (name, mapset)) {
+ return (GT_get_f_counts (name, mapset, print_progress));
+ } else {
+ return (GT_get_c_counts (name, mapset, print_progress));
+ }
+
+ return (NULL);
+}
+
+
+/* GT_get_c_counts() */
+/* Read occurence counts of categories from a grass CELL map.
+
+ ARGS: name = name of GRASS raster map
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ print_progress = set this to '1' to have a status display
+ RETURN: a pointer to an array of ints with category counts
+ (0 .. N)
+ NULL = no categories defined or general file error
+
+ NOTE: Number of categories in the array, i.e. array length can
+ be obtained using get_cell_stats().
+ Memory for returned int array must not be pre-allocated by caller.
+ Memory must be free'd by caller!
+*/
+long *GT_get_c_counts (char *name, char *mapset, int print_progress) {
+ int fd;
+ int error;
+ struct Categories cats;
+ int n_cats = 0;
+ int i,j;
+ int rows, cols;
+ CELL *cellbuf;
+ CELL value;
+ long *categories;
+
+ rows = G_window_rows ();
+ cols = G_window_cols ();
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (NULL);
+ }
+
+ if (G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ return (NULL);
+ }
+
+ /* now, open map and get number of defined categories */
+ G_init_cats (0, "", &cats);
+ error = G_read_cats (name, mapset, &cats);
+ if (error != 0) {
+ /* no categories found */
+ G_close_cell (fd);
+ return (NULL);
+ }
+ n_cats = G_number_of_cats (name, mapset) + 1;
+
+ /* allocate mem to store category counts */
+ categories = G_calloc (n_cats, sizeof (long));
+ for (i=0; i < n_cats; i++) {
+ categories [i] = 0;
+ }
+
+ /* now, analyse raster file and count category frequencies */
+ cellbuf = G_allocate_raster_buf (CELL_TYPE);
+ if (print_progress) {
+ fprintf (stdout, "Counting category frequencies: \n");
+ }
+ for (i=0; i< rows; i++) {
+ error = G_get_raster_row (fd, cellbuf, i, CELL_TYPE);
+ for (j=0; j<cols; j++) {
+ /* check for NULL value */
+ if ( G_is_c_null_value (&cellbuf[j]) == 1) {
+ /* do nothing */
+ } else {
+ /* check for value outside of category range */
+ value = cellbuf[j];
+ if ( ! (( value < 0 ) || ( value > n_cats -1)) ) {
+ categories[value] = categories[value] + 1;
+ }
+ }
+ }
+ if (print_progress) {
+ G_percent (i, rows-1, 1);
+ fflush (stdout);
+ }
+ }
+
+ if (print_progress) {
+ fprintf (stdout,"\n");
+ fflush (stdout);
+ }
+
+ G_free (cellbuf);
+ G_close_cell (fd);
+ return (categories);
+}
+
+
+/* GT_get_f_counts () */
+/* Read occurence counts of categories from a grass FCELL or DCELL map.
+
+ ARGS: name = name of GRASS raster map
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ print_progress = set this to '1' to have a status display
+ RETURN: a pointer to an array of ints with category counts
+ (0 .. N)
+ NULL = no categories defined or general file error
+
+ NOTE: Number of categories in the array, i.e. array length can
+ be obtained using get_cell_stats().
+ Memory for returned int array must not be pre-allocated by caller.
+ Memory must be free'd by caller!
+*/
+long *GT_get_f_counts (char *name, char *mapset, int print_progress) {
+ int fd;
+ int error;
+ struct Categories cats;
+ int n_cats = 0;
+ int i,j;
+ int rows, cols;
+ DCELL *dcellbuf;
+ DCELL dvalue;
+ CELL value;
+ long *categories;
+
+ rows = G_window_rows ();
+ cols = G_window_cols ();
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (NULL);
+ }
+
+ if (!G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ return (NULL);
+ }
+
+ /* now, open map and get number of defined categories */
+ G_init_cats (0, "", &cats);
+ error = G_read_cats (name, mapset, &cats);
+ if (error != 0) {
+ /* no categories found */
+ G_close_cell (fd);
+ return (NULL);
+ }
+
+ /* this is the number of defined (i.e labeled) categories in the map */
+ /* if it is zero, we might just as well return to caller. */
+ n_cats = G_number_of_raster_cats (&cats);
+ if (n_cats == 0) {
+ G_close_cell (fd);
+ return (NULL);
+ }
+
+ /* allocate mem to store category counts */
+ categories = G_calloc (n_cats, sizeof (long));
+ for (i=0; i<n_cats; i++) {
+ categories [i] = 0;
+ }
+
+ /* now, analyse raster file and count category frequencies */
+ dcellbuf = G_allocate_raster_buf (DCELL_TYPE);
+ if (print_progress) {
+ fprintf (stdout, "Counting category frequencies: \n");
+ }
+ for (i=0; i< rows; i++) {
+ error = G_get_raster_row (fd, dcellbuf, i, DCELL_TYPE);
+ for (j=0; j<cols; j++) {
+ /* check for NULL value */
+ if ( G_is_d_null_value (&dcellbuf[j]) == 0) {
+ /* check for value outside of category range */
+ dvalue = dcellbuf[j];
+ value = G_quant_get_cell_value (&cats.q, dvalue);
+ if ( ! (( value < 0 ) || ( value > n_cats -1)) ) {
+ categories[value] = categories[value] + 1;
+ }
+ }
+ }
+ if (print_progress) {
+ G_percent (i, rows-1, 1);
+ fflush (stdout);
+ }
+ }
+
+ if (print_progress) {
+ fprintf (stdout,"\n");
+ fflush (stdout);
+ }
+ G_free (dcellbuf);
+ G_close_cell (fd);
+ return (categories);
+}
+
+
+/* GT_get_labels () */
+/* Read category labels from a grass raster map of any type.
+
+ ARGS: name = name of GRASS raster map
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ print_progress = set this to '1' to have a status display
+ RETURN: a pointer to an array of *char with labels
+ (0 .. N)
+ NULL = no labels defined or general file error
+
+ NOTE: Number of categories in the array, i.e. array length can
+ be obtained using get_cell_stats().
+ Memory for returned char array must not be pre-allocated by caller.
+ Memory must be free'd by caller
+*/
+char **GT_get_labels (char *name, char *mapset) {
+
+ int fd;
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (NULL);
+ }
+
+ if (G_raster_map_is_fp (name, mapset)) {
+ return (GT_get_f_labels (name, mapset));
+
+ } else {
+ return (GT_get_c_labels (name, mapset));
+ }
+
+ return (NULL);
+}
+
+
+/* GT_get_c_labels () */
+/* Read category labels from a grass CELL map.
+
+ ARGS: name = name of GRASS raster map
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ print_progress = set this to '1' to have a status display
+ RETURN: a pointer to an array of *char with labels
+ (0 .. N)
+ NULL = no labels defined or general file error
+
+ NOTE: Number of categories in the array, i.e. array length can
+ be obtained using get_cell_stats().
+ Memory for returned char array must not be pre-allocated by caller.
+ Memory must be free'd by caller
+*/
+char **GT_get_c_labels (char *name, char *mapset) {
+ int fd;
+ int error;
+ struct Categories cats;
+ int n_cats = 0;
+ int i;
+ char **labels;
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (NULL);
+ }
+
+ if (G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ return (NULL);
+ }
+
+ /* now, open map and get number of defined categories */
+ G_init_cats (0, "", &cats);
+ error = G_read_cats (name, mapset, &cats);
+ if (error != 0) {
+ /* no categories found */
+ G_close_cell (fd);
+ return (NULL);
+ }
+ n_cats = G_number_of_cats (name, mapset) + 1;
+
+ /* allocate mem to store description strings for cats */
+ /* every valid category also has a label. */
+ /* if the user does not provide/delete a label using 'r.support', */
+ /* GRASS will delete that category entry from the header */
+ labels = G_calloc (n_cats, sizeof (char*));
+ for (i=0; i < n_cats; i++) {
+ labels[i] = G_calloc ((signed int) strlen(G_get_c_raster_cat ((CELL*) &i, &cats)) + 1, sizeof(char));
+ strcpy (labels[i], G_get_c_raster_cat ((CELL*) &i, &cats));
+ }
+
+ G_close_cell (fd);
+ return (labels);
+}
+
+
+/* GT_get_f_labels () */
+/* Read category labels from a GRASS DCELL/FCELL map.
+
+ ARGS: name = name of GRASS raster map
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ print_progress = set this to '1' to have a status display
+ RETURN: a pointer to an array of *char with labels
+ (0 .. N)
+ NULL = no labels defined or general file error
+
+ NOTE: Number of categories in the array, i.e. array length can
+ be obtained using get_cell_stats().
+ Memory for returned char array must not be pre-allocated by caller.
+ Memory must be free'd by caller
+*/
+char **GT_get_f_labels (char *name, char *mapset) {
+ int fd;
+ int error;
+ struct Categories cats;
+ int n_cats = 0;
+ int i;
+ char **labels;
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (NULL);
+ }
+
+ if (!G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ return (NULL);
+ }
+
+ /* now, open map and get number of defined categories */
+ G_init_cats (0, "", &cats);
+ error = G_read_cats (name, mapset, &cats);
+ if (error != 0) {
+ /* no categories found */
+ G_close_cell (fd);
+ return (NULL);
+ }
+
+ /* this is the number of defined (i.e labeled) categories in the map */
+ /* if it is zero, we might just as well return to caller. */
+ n_cats = G_number_of_raster_cats (&cats);
+ if (n_cats == 0) {
+ G_close_cell (fd);
+ return (NULL);
+ }
+
+ /* allocate mem to store description strings for cats */
+ /* every valid category also has a label. */
+ /* if the user does not provide/delete a label using 'r.support', */
+ /* GRASS will delete that category entry from the header */
+ labels = G_calloc (n_cats, sizeof (char*));
+ for (i=0; i < n_cats; i++) {
+ labels[i] = G_calloc ((signed int) strlen (cats.labels[i]) + 1, sizeof(char));
+ strcpy (labels[i], cats.labels[i]);
+ }
+
+ G_close_cell (fd);
+ return (labels);
+}
+
+
+/* GT_set_cats_only () */
+/* Create a new CELL raster map with categories ranging from 0 .. N
+ Input map can be a partly categorised GRASS raster map of any type.
+ All values in the input map that are not mapped to a
+ category will be replaced by NULL values in the output map.
+
+ ARGS: name = name of GRASS raster map to read in
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ output = name of result raster map (will always be stored
+ in the user's current mapset).
+ intout = set to '1' to create a CELL (integer) output map
+ print_progress = set this to '1' to have a status display
+
+ RETURN:
+ 0 = OK
+ -1 = ivalid map format
+ -2 = input map read error
+ -3 = output map write error
+ -4 = no categories in input map
+
+ NOTE: for the output map, it is guaranteed that each cell will
+ either be within the category range 0..n or NULL.
+*/
+int GT_set_cats_only (char *name, char *mapset, char *output, int intout, int print_progress) {
+ int fd;
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-1);
+ }
+
+ if (G_raster_map_is_fp (name, mapset)) {
+ return (GT_set_f_cats_only (name, mapset, output, intout, print_progress));
+
+ } else {
+ return (GT_set_c_cats_only (name, mapset, output, print_progress));
+ }
+
+ return (0);
+}
+
+
+/* GT_set_c_cats_only () */
+/* Create a new CELL raster map with categories ranging from 0 .. N
+ Input map must be of type CELL.
+ All values in the input map that are not mapped to a
+ category will be replaced by NULL values in the output map.
+
+ ARGS: name = name of GRASS raster map to read in
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ output = name of result raster map (will always be stored
+ in the user's current mapset).
+ print_progress = set this to '1' to have a status display
+
+ RETURN:
+ Number of categories in output map, or:
+ 0 = no categories written to output map
+ -1 = input map not in CELL format
+ -2 = input map read error
+ -3 = output map write error
+ -4 = no categories in input map
+
+ NOTE: for the output map, it is guaranteed that each cell will
+ either be within the category range 0..n or NULL.
+*/
+int GT_set_c_cats_only (char *name, char *mapset, char *output, int print_progress) {
+ int fd, outfd;
+ int error;
+ struct Categories cats;
+ int n_cats = 0;
+ int i,j;
+ int rows, cols;
+ CELL *cellbuf;
+ CELL value;
+ char *strbuf, *strbuf2;
+
+ rows = G_window_rows ();
+ cols = G_window_cols ();
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-2);
+ }
+
+ /* try to open new CELL map for output */
+ outfd = G_open_cell_new (output);
+ if ( outfd < 0 ) {
+ return (-3);
+ }
+
+ if (G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ return (-1);
+ }
+
+ /* now, open map and get number of defined categories */
+ G_init_cats (0, "", &cats);
+ error = G_read_cats (name, mapset, &cats);
+ if (error != 0) {
+ /* no categories found */
+ G_close_cell (fd);
+ return (-4);
+ }
+ n_cats = G_number_of_cats (name, mapset) + 1;
+
+ cellbuf = G_allocate_raster_buf (CELL_TYPE);
+ if (print_progress) {
+ fprintf (stdout, "Converting cells outside category range to NULL: \n");
+ }
+ for (i=0; i< rows; i++) {
+ error = G_get_raster_row (fd, cellbuf, i, CELL_TYPE);
+ for (j=0; j<cols; j++) {
+ /* check for NULL value */
+ if ( G_is_c_null_value (&cellbuf[j]) == 1) {
+ /* copy NULL value through */
+ G_set_c_null_value (&cellbuf[j],1);
+ } else {
+ /* check for value outside of category range */
+ value = cellbuf[j];
+ if ( (( value < 0 ) || ( value > n_cats - 1)) ) {
+ G_set_c_null_value (&cellbuf[j],1);
+ }
+ }
+ }
+ /* write one line of output map */
+ G_put_c_raster_row (outfd,cellbuf);
+ if (print_progress) {
+ G_percent (i, rows-1, 1);
+ fflush (stdout);
+ }
+ }
+ if (print_progress) {
+ fprintf (stdout,"\n");
+ fflush (stdout);
+ }
+
+ G_free (cellbuf);
+ G_close_cell (fd);
+ G_close_cell (outfd);
+
+ /* copy category file to new output map */
+ G_write_cats (output, &cats);
+
+ /* write some comments into the history file */
+ strbuf = G_calloc (255, sizeof (char));
+ strbuf2 = G_calloc (255, sizeof (char));
+ sprintf (strbuf,"%s@%s",name,mapset);
+ sprintf (strbuf2,"r.categorise mode=clean");
+ GT_write_hist (output,strbuf,"Selected only those INT cells that match a category.",
+ strbuf2);
+ G_free (strbuf);
+ G_free (strbuf2);
+
+ return (n_cats);
+}
+
+
+/* GT_set_f_cats_only () */
+/* Create a new CELL raster map with categories ranging from 0 .. N
+ Input map must be of type DCELL or FCELL.
+ All values in the input map that are not mapped to a
+ category will be replaced by NULL values in the output map.
+
+ ARGS: name = name of GRASS raster map to read in
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ output = name of result raster map (will always be stored
+ in the user's current mapset).
+ intout = set to '1' to create a CELL (integer) output map
+ print_progress = set this to '1' to have a status display
+
+ RETURN:
+ Number of categories in output map, or:
+ 0 = no categories written to output map
+ -1 = input map not in CELL format
+ -2 = input map read error
+ -3 = output map write error
+ -4 = no categories in input map
+
+ NOTE: for the output map, it is guaranteed that each cell will
+ either be within the category range 0..n or NULL.
+*/
+int GT_set_f_cats_only (char *name, char *mapset, char *output, int intout, int print_progress) {
+ int fd, outfd;
+ int error;
+ struct Categories cats;
+ struct Categories int_cats;
+ struct Colors srcColor;
+ struct Colors dstColor;
+ int n_cats = 0;
+ int n_colors = 0;
+ int i,j;
+ int rows, cols;
+ DCELL *dcellbuf;
+ DCELL dvalue;
+ DCELL from, to;
+ CELL *outcellbuf;
+ DCELL *doutcellbuf;
+ CELL value;
+ char *label;
+ char *strbuf, *strbuf2;
+ int map_type;
+ unsigned char red, green, blue;
+
+ rows = G_window_rows ();
+ cols = G_window_cols ();
+
+ /* to prevent compiler warnings */
+ outcellbuf = NULL;
+ doutcellbuf = NULL;
+ label = NULL;
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-2);
+ }
+
+ /* determine default mode of output map */
+ if (! G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ return (-1);
+ }
+ map_type = G_raster_map_type (name, mapset);
+ G_set_fp_type (map_type);
+
+ /* open new map for output */
+ if ( intout == 1 ) outfd = G_open_cell_new (output);
+ else outfd = G_open_fp_cell_new (output);
+ if ( outfd < 0 ) {
+ return (-3);
+ }
+
+ /* now, open map and get number of defined categories */
+ G_init_cats (0, "tmp", &cats); /* source categories */
+ error = G_read_cats (name, mapset, &cats);
+ if (error != 0) {
+ /* category file cannot be opened */
+ G_close_cell (fd);
+ return (-4);
+ }
+
+ /* this is the number of defined (i.e labeled) categories in the map */
+ /* if it is zero, we might just as well return to caller. */
+ n_cats = G_number_of_raster_cats (&cats);
+ if (n_cats == 0) {
+ G_close_cell (fd);
+ return (0);
+ }
+
+ dcellbuf = G_allocate_raster_buf (DCELL_TYPE);
+ if ( intout == 1 ) outcellbuf = G_allocate_raster_buf (CELL_TYPE);
+ else doutcellbuf = G_allocate_raster_buf (DCELL_TYPE);
+
+ if (print_progress) {
+ fprintf (stdout, "Converting cells outside category range to NULL: \n");
+ }
+ for (i=0; i< rows; i++) {
+ error = G_get_raster_row (fd, dcellbuf, i, DCELL_TYPE);
+ /* write entire row of output map as NULL files, first */
+ if ( intout == 1 ) G_set_c_null_value (outcellbuf, cols);
+ else G_set_d_null_value (doutcellbuf, cols);
+
+ for (j=0; j<cols; j++) {
+ /* check for NULL value */
+ if ( !G_is_d_null_value (&dcellbuf[j]) == 1) {
+ dvalue = dcellbuf[j];
+ value = G_quant_get_cell_value (&cats.q, dvalue);
+ /* write map value only, if it is within category range */
+ if ( !(( value < 0 ) || ( value > n_cats - 1)) ) {
+ if ( intout == 1 ) outcellbuf[j] = value;
+ else doutcellbuf[j] = dvalue;
+ }
+ }
+ }
+ /* write one line of output map */
+ if ( intout == 1 ) G_put_c_raster_row (outfd,outcellbuf);
+ else
+ {
+ G_put_d_raster_row (outfd,doutcellbuf);
+ }
+ if (print_progress) {
+ G_percent (i, rows-1, 1);
+ fflush (stdout);
+ }
+ }
+ if (print_progress) {
+ fprintf (stdout,"\n");
+ fflush (stdout);
+ }
+ G_free (dcellbuf);
+ if ( intout == 1 ) G_free (outcellbuf);
+ else G_free (doutcellbuf);
+
+ G_close_cell (outfd);
+
+ /* allocate some string buffers */
+ strbuf = G_calloc (255,sizeof(char));
+ strbuf2 = G_calloc (255,sizeof(char));
+
+ /* copy category labels to new output map */
+ G_init_cats (0, "", &int_cats); /* destination categories */
+ sprintf (strbuf,"Categorised cells only, from %s@%s.",name,mapset);
+ G_set_cats_title (strbuf,&int_cats);
+ for (i=0; i<n_cats; i++) {
+ label = G_get_ith_d_raster_cat (&cats, i, &from, &to);
+ if (intout) {
+ G_set_cat (i, label, &int_cats);
+ } else {
+ G_set_d_raster_cat(&from, &to, label, &int_cats);
+ }
+ }
+ error = G_write_cats (output, &int_cats);
+
+ /* copy color table if present */
+ error = G_read_colors (name, mapset, &srcColor);
+ n_colors = srcColor.fixed.n_rules; /* number of colors in table */
+ if (error == 1) {
+ /* src map has a color table: let's copy it */
+ G_init_colors (&dstColor);
+ for (i=0; i<n_colors; i++) {
+ /* dummy calls to get limits of cat color range */
+ label = G_get_ith_d_raster_cat (&cats, i, &from, &to);
+ G_get_d_raster_color (&from, (int*) &red, (int*) &green, (int*) &blue, &srcColor);
+ if (intout) {
+ /* integer maps: we can only copy a truncated color map, i.e.
+ each integer category will be assigned only the start RGB values
+ of the original FP category color range
+ */
+ G_add_color_rule (i, red, green, blue, i, red, green, blue, &dstColor);
+ } else {
+ /* floating point maps: copy color table 1:1 */
+ /* TODO: NOT YET WORKING */
+ /*
+ label = G_get_ith_d_raster_cat (&cats, i, &from, &to);
+ G_get_d_raster_color (&to, (int*) &red2, (int*) &green2, (int*) &blue2, &srcColor);
+ fprintf (stderr,"FROM %f TO %f: %i,%i,%i - %i,%i,%i\n", from, to, red, green, blue,
+ red2, green2, blue2);
+ G_add_d_raster_color_rule (&from, red, green, blue, &to, red2, green2, blue2,
+ &dstColor);
+ */
+ }
+ }
+ /* write color table to output map */
+ G_write_colors (output, mapset, &dstColor);
+ }
+
+ /* write some comments into the history file */
+ sprintf (strbuf,"%s@%s",name,mapset);
+ sprintf (strbuf2,"r.categorise mode=clean");
+ GT_write_hist (output,strbuf,"Selected only those FP cells that match a category.",
+ strbuf2);
+ G_free (label);
+ G_free (strbuf);
+ G_free (strbuf2);
+
+ /* close input raster map */
+ G_close_cell (fd);
+ return (n_cats);
+}
+
+
+/* GT_set_cats_num */
+/* Create a new CELL raster map with categories ranging from 0 .. N
+ Let the user specify N.
+
+ ARGS: name = name of GRASS raster map to read in
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ output = name of result raster map (will always be stored
+ in the user's current mapset).
+ min, max = set to different values to cut the output range
+ (see NOTE)
+ num = number of categories (N) to generate
+ intout = set to '1' to create a CELL (integer) output map
+ print_progress = set this to '1' to have a status display
+ RETURN: number of categories created (N)
+ 0 = no categories created
+ -1 = invalid input map format
+ -2 = input map read error
+ -3 = output map write error
+
+ NOTE: Maps values: divides the entire range of values in the input
+ map into a user-specified number of intervals, all of the
+ same width. Each interval will become a category in the
+ output map.
+ Range of categories can be cut by passing 'min' and 'max'
+ paremeters != -1. All values outside the range in the input map
+ will be replaced with NULL-values in the output map.
+*/
+int GT_set_cats_num (char *name, char *mapset, char *output,
+ double rmin, double rmax, int num, int intout, int print_progress) {
+ int fd;
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-1);
+ }
+
+ if (G_raster_map_is_fp (name, mapset)) {
+ return (GT_set_f_cats_num (name, mapset, output, rmin, rmax, num, intout, print_progress));
+
+ } else {
+ return (GT_set_c_cats_num (name, mapset, output, (int) rmin, (int) rmax, num, print_progress));
+ }
+
+ return (0);
+}
+
+
+/* GT_set_c_cats_num */
+/* Create a new CELL raster map with categories ranging from 0 .. N
+ Let the user specify N.
+
+ ARGS: name = name of GRASS raster map to read in
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ output = name of result raster map (will always be stored
+ in the user's current mapset).
+ min, max = set to different values to cut the output range
+ (see NOTE)
+ num = number of categories (N) to generate
+ print_progress = set this to '1' to have a status display
+ RETURN: number of categories created (N)
+ 0 = no categories created
+ -1 = input map not in CELL format
+ -2 = input map error
+ -3 = output map write error
+
+ NOTE: Maps values: divides the entire range of CELL values in the input
+ map into a user-specified number of intervals, all of the
+ same width. Each interval will become a category in the
+ output map.
+ Range of categories can be cut by passing 'min' and 'max'
+ paremeters != -1. All values outside the range in the input map
+ will be replaced with NULL-values in the output map.
+*/
+int GT_set_c_cats_num (char *name, char *mapset, char *output,
+ int rmin, int rmax, int num, int print_progress) {
+ int fd, outfd;
+ int error;
+ struct Categories cats;
+ int i,j;
+ int rows, cols;
+ CELL *cellbuf, *outcellbuf;
+ CELL value;
+ int divisor;
+ int min, max;
+ char *strbuf, *strbuf2;
+ /* a flag to control quantification of the output map */
+ int cutrange = 0;
+
+ rows = G_window_rows ();
+ cols = G_window_cols ();
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-2);
+ }
+
+ /* try to open new CELL map for output */
+ outfd = G_open_cell_new (output);
+ if ( outfd < 0 ) {
+ return (-3);
+ }
+
+ if (G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ G_close_cell (outfd);
+ return (-1);
+ }
+
+ if ( num < 2 ) {
+ G_fatal_error ("GT_set_c_cats_num(): Number of categories must be at least 2.");
+ }
+
+ /* FIRST PASS: analyse raster file and get min and max ints */
+ GT_get_c_range (name, mapset, &min, &max, print_progress);
+
+ /* check, if user wants to cut range and if min and max have been
+ set to sane values */
+ if ( rmin != rmax ) {
+ cutrange = 1; /* user wants to cut. Let's check ... */
+ if ( rmin > rmax ) {
+ G_warning ("User specified 'min' of input range larger than 'max'. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ if ( (rmin < min) && (cutrange == 1)) {
+ G_warning ("User specified 'min' of input range smaller than minimum CELL value. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ if ( (rmax > max) && (cutrange == 1)) {
+ G_warning ("User specified 'max' of input range larger than maximum CELL value. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ }
+
+ /* SECOND PASS: remap values, create labels and write output map */
+ cellbuf = G_allocate_raster_buf (CELL_TYPE);
+ outcellbuf = G_allocate_raster_buf (CELL_TYPE);
+ if (print_progress) {
+ fprintf (stdout, "Mapping categories: \n");
+ }
+ divisor = (int) rint (((float)max - (float)min) / (float)num);
+ if ( divisor < 2 ) {
+ G_fatal_error ("GT_set_c_cats_num(): Category width must be at least 2.");
+ }
+ for (i=0; i< rows; i++) {
+ error = G_get_raster_row (fd, cellbuf, i, CELL_TYPE);
+ for (j=0; j<cols; j++) {
+ /* check for NULL values and update min and max */
+ if ( G_is_c_null_value (&cellbuf[j]) == 1) {
+ /* pass NULL values through to output map */
+ G_set_c_null_value (&outcellbuf[j],1);
+ } else {
+ /* check if any range cutting has to be done */
+ if ( cutrange ) {
+ if ( (cellbuf[j] < rmin) || (cellbuf[j] > rmax) ) {
+ G_set_c_null_value (&outcellbuf[j],1);
+ } else {
+ value = abs(min) + cellbuf[j] + 1;
+ outcellbuf[j] = (int) ceil ( (double) value / (double) divisor ) -1;
+ /* last category may be slightly larger */
+ if (outcellbuf[j] > (num-1)) {
+ outcellbuf[j] = (num-1);
+ }
+ }
+ } else {
+ /* just write mapped value */
+ value = abs(min) + cellbuf[j] + 1;
+ outcellbuf[j] = (int) ceil ( (double) value / (double) divisor ) -1;
+ /* last category may be slightly larger */
+ if (outcellbuf[j] > (num-1)) {
+ outcellbuf[j] = (num-1);
+ }
+ }
+ }
+ }
+ /* write output row */
+ G_put_c_raster_row (outfd,outcellbuf);
+ if (print_progress) {
+ G_percent (i, rows-1, 1);
+ fflush (stdout);
+ }
+ }
+ if (print_progress) {
+ fprintf (stdout,"\n");
+ fflush (stdout);
+ }
+
+ /* create categories and category labels */
+ G_init_cats (0, "", &cats);
+ strbuf = G_calloc (255, sizeof (char));
+ strbuf2 = G_calloc (255, sizeof (char));
+ if ( cutrange ) {
+ sprintf (strbuf,"Categories mapped from %i to %i. Cut range = %i to %i ",
+ min, max, rmin, rmax);
+ } else {
+ sprintf (strbuf,"Categories mapped from %i to %i.", min , max);
+ }
+ G_set_cats_title (strbuf, &cats);
+ for (i=0; i<num; i++) {
+ sprintf (strbuf,"%i to %i", (min + i*divisor), ((min + i*divisor) + divisor));
+ /* last category may be slightly wider */
+ if (i == num-1 ) {
+ sprintf (strbuf,"%i to %i", (min + i*divisor), max);
+ }
+ G_set_cat (i, strbuf, &cats);
+ }
+ G_free (cellbuf);
+ G_close_cell (fd);
+ G_free (outcellbuf);
+ G_close_cell (outfd);
+
+ /* write category file */
+ G_write_cats (output, &cats);
+
+ /* write some comments into the history file */
+ sprintf (strbuf,"%s@%s",name,mapset);
+ if ( rmin != rmax ) {
+ sprintf (strbuf2,"r.categorise mode=num,%i min=%i max=%i",num, rmin, rmax);
+ } else {
+ sprintf (strbuf2,"r.categorise mode=num,%i",num);
+ }
+ GT_write_hist (output,strbuf,"Original INT data range categorised using fixed number of categories.",
+ strbuf2);
+ G_free (strbuf);
+ G_free (strbuf2);
+
+ return (num);
+}
+
+
+/* GT_set_f_cats_num () */
+/* Create a new raster map with categories ranging from 0 .. N
+ Let the user specify N.
+
+ ARGS: name = name of GRASS raster map to read in
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ output = name of result raster map (will always be stored
+ in the user's current mapset).
+ min, max = set to different values to cut the output range
+ (see NOTE)
+ num = number of categories to generate
+ intout = set to '1' to create a CELL (integer) output map
+ print_progress = set this to '1' to have a status display
+ RETURN: number of categories created (N)
+ 0 = no categories created
+ -1 = input map not in CELL format
+ -2 = input map error
+ -3 = output map write error
+
+ NOTE: Maps values: divides range of DCELL/FCELL values in the input
+ into N intervals of user specified, equal width
+ Each interval will become a category in the output map.
+ Range of categories can be cut by passing 'min' and 'max'
+ paremeters != -1. All values outside the range in the input map
+ will be replaced with NULL-values in the output map.
+ The last category in the output map might end up wider than the
+ actual maximum value in the input map.
+ To improve legibility of map legends, the intervals will start at
+ an integer offset, if 'round_cat=1'
+*/
+int GT_set_f_cats_num (char *name, char *mapset, char *output,
+ double rmin, double rmax, int num, int intout, int print_progress) {
+ int fd, outfd;
+ int error;
+ struct Categories cats;
+ int i,j;
+ int rows, cols;
+ DCELL *dcellbuf;
+ CELL *outcellbuf;
+ DCELL *doutcellbuf;
+ DCELL dvalue;
+ DCELL dmin, dmax;
+ FCELL fmin, fmax;
+ double divisor;
+ double min, max;
+ char *strbuf, *strbuf2;
+ int map_type;
+
+ /* a flag to control quantification of the output map */
+ int cutrange = 0;
+
+ rows = G_window_rows ();
+ cols = G_window_cols ();
+
+ /* to disable compiler warnings */
+ outcellbuf = NULL;
+ doutcellbuf = NULL;
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-2);
+ }
+
+ /* determine default mode of output map */
+ if (!G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ return (-1);
+ }
+ map_type = G_raster_map_type (name, mapset);
+ G_set_fp_type (map_type);
+
+ /* open new map for output */
+ if ( intout == 1 ) outfd = G_open_cell_new (output);
+ else outfd = G_open_fp_cell_new (output);
+ if ( outfd < 0 ) {
+ return (-3);
+ }
+
+ if ( num < 2 ) {
+ G_fatal_error ("GT_set_f_cats_num(): Number of categories must be at least 2.");
+ }
+
+ /* FIRST PASS: analyse raster file and get min and max ints */
+ GT_get_f_range (name, mapset, &min, &max, print_progress);
+
+ /* check, if user wants to cut range and if min and max have been
+ set to sane values */
+ if ( rmin != rmax ) {
+ cutrange = 1; /* user wants to cut. Let's check ... */
+ if ( rmin > rmax ) {
+ G_warning ("User specified 'min' of input range larger than 'max'. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ if ( (rmin < min) && (cutrange == 1)) {
+ G_warning ("User specified 'min' of input range smaller than minimum CELL value. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ if ( (rmax > max) && (cutrange == 1)) {
+ G_warning ("User specified 'max' of input range larger than maximum CELL value. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ }
+
+ /* SECOND PASS: remap values, create labels and write output map */
+ dcellbuf = G_allocate_raster_buf (DCELL_TYPE);
+ if ( intout == 1 ) outcellbuf = G_allocate_raster_buf (CELL_TYPE);
+ else doutcellbuf = G_allocate_raster_buf (DCELL_TYPE);
+
+ if (print_progress) {
+ fprintf (stdout, "Mapping categories: \n");
+ }
+ divisor = (max-min) / num;
+
+ for (i=0; i< rows; i++) {
+ error = G_get_raster_row (fd, dcellbuf, i, DCELL_TYPE);
+ for (j=0; j<cols; j++) {
+ /* check for NULL values and update min and max */
+ if ( G_is_d_null_value (&dcellbuf[j]) == 1) {
+ /* pass NULL values through to output map */
+ if ( intout == 1 ) G_set_c_null_value (&outcellbuf[j],1);
+ else G_set_d_null_value (&doutcellbuf[j],1);
+ } else {
+ /* check if any range cutting has to be done */
+ if ( cutrange ) {
+ if ( (dcellbuf[j] < rmin) || (dcellbuf[j] > rmax) ) {
+ if ( intout == 1 ) G_set_c_null_value (&outcellbuf[j],1);
+ else G_set_d_null_value (&doutcellbuf[j],1);
+ } else {
+ dvalue = dcellbuf[j] - min;
+ if ( intout == 1 ) outcellbuf[j] = (CELL) floor (dvalue / divisor);
+ else doutcellbuf[j] = dcellbuf[j];
+ /* maximum value must be forced into highest category */
+ if ( intout == 1 ) {
+ if ( outcellbuf[j] > (num -1) ) {
+ outcellbuf[j] --;
+ }
+ }
+ }
+ } else {
+ dvalue = dcellbuf[j] - min;
+ if ( intout == 1 ) outcellbuf[j] = (CELL) floor (dvalue / divisor);
+ else doutcellbuf[j] = dcellbuf[j];
+ /* maximum value must be forced into highest category */
+ if ( intout == 1 ) {
+ if ( outcellbuf[j] > (num -1) ) {
+ outcellbuf[j] --;
+ }
+ }
+ }
+ }
+ }
+ /* write output row */
+ if ( intout == 1) G_put_c_raster_row (outfd,outcellbuf);
+ else G_put_d_raster_row (outfd,doutcellbuf);
+ if (print_progress) {
+ G_percent (i, rows-1, 1);
+ fflush (stdout);
+ }
+ }
+ if (print_progress) {
+ fprintf (stdout,"\n");
+ fflush (stdout);
+ }
+
+ G_free (dcellbuf);
+ G_close_cell (fd);
+ if (intout == 1) G_free (outcellbuf);
+ else G_free (doutcellbuf);
+ G_close_cell (outfd);
+
+ /* create categories and category labels */
+ G_init_cats (num, "", &cats);
+ strbuf = G_calloc (255,sizeof (char));
+ strbuf2 = G_calloc (255,sizeof (char));
+ if ( cutrange ) {
+ sprintf (strbuf,"Cut range=%2$.*1$f to %3$.*1$f ",
+ GT_DECDIGITS, rmin, rmax);
+ } else {
+ sprintf (strbuf,"Full range of source map");
+ }
+ G_set_cats_title (strbuf, &cats);
+ for (i=0; i<num; i++) {
+ sprintf (strbuf,"%2$.*1$f to %3$.*1$f", GT_DECDIGITS, (min + i*divisor),
+ ((min + i*divisor) + divisor));
+ if ( intout == 1 ) G_set_cat (i, strbuf, &cats); /* integer cats */
+ else {
+ /* create floating point category ranges */
+ if ( map_type == DCELL_TYPE ) {
+ dmin = (min + i*divisor);
+ dmax = (min + i*divisor) + divisor;
+ G_set_d_raster_cat (&dmin, &dmax, strbuf, &cats);
+ }
+ if ( map_type == FCELL_TYPE ) {
+ fmin = (min + i*divisor);
+ fmax = (min + i*divisor) + divisor;
+ G_set_f_raster_cat (&fmin, &fmax, strbuf, &cats);
+ }
+ }
+ }
+
+ /* write category file */
+ G_write_cats (output, &cats);
+
+ /* write some comments into the history file */
+ sprintf (strbuf,"%s@%s",name,mapset);
+ if ( rmin != rmax ) {
+ sprintf (strbuf2,"r.categorise mode=num,%i min=%.3f max=%.3f",num, rmin, rmax);
+ } else {
+ sprintf (strbuf2,"r.categorise mode=num,%i", num);
+ }
+ GT_write_hist (output,strbuf,"Original FP data range categorised using fixed number of intervals.",
+ strbuf2);
+ G_free (strbuf);
+ G_free (strbuf2);
+
+ return (num);
+}
+
+
+/* GT_set_cats_width () */
+/* Create a new CELL raster map with categories ranging from 0 .. N
+ Let the user specify category width. N will then be
+ determined automatically.
+ Input map can be of any GRASS raster type.
+
+ ARGS: name = name of GRASS raster map to read in
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ output = name of result raster map (will always be stored
+ in the user's current mapset).
+ min, max = set to different values to cut the output range
+ (see NOTE)
+ width = width of categories to generate
+ round_cat = set to '1' to start category 0 at the nearest integer
+ value (floor).
+ intout = set to '1' to force integer (CELL) map output
+ print_progress = set this to '1' to have a status display
+ RETURN: number of categories created (N)
+ 0 = no categories created
+ -1 = invalid input map format
+ -2 = input map error
+ -3 = output map write error
+
+ NOTE: Maps values: divides range of DCELL/FCELL values in the input
+ into N intervals of user specified, equal width
+ Each interval will become a category in the output map.
+ Range of categories can be cut by passing 'min' and 'max'
+ paremeters != -1. All values outside the range in the input map
+ will be replaced with NULL-values in the output map.
+ The last category in the output map might end up wider than the
+ actual maximum value in the input map.
+ To improve legibility of map legends, the intervals will start at
+ an integer offset, if 'round_cat=1' (DCELL and FCELL maps only)
+*/
+int GT_set_cats_width (char *name, char *mapset, char *output,
+ double rmin, double rmax, double width, int round_cat,
+ int intout, int print_progress) {
+ int fd;
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-1);
+ }
+
+ if (G_raster_map_is_fp (name, mapset)) {
+ return (GT_set_f_cats_width (name, mapset, output, rmin, rmax,
+ width, round_cat, intout, print_progress));
+
+ } else {
+ return (GT_set_c_cats_width (name, mapset, output, (int) rmin, (int) rmax,
+ (int) width, print_progress));
+ }
+
+ return (0);
+}
+
+
+/* GT_set_c_cats_width () */
+/* Create a new CELL raster map with categories ranging from 0 .. N
+ Let the user specify category width. N will then be determined
+ automatically.
+
+ ARGS: name = name of GRASS raster map to read in
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ output = name of result raster map (will always be stored
+ in the user's current mapset).
+ min, max = set to different values to cut the output range
+ (see NOTE)
+ width = width of each category
+ print_progress = set this to '1' to have a status display
+ RETURN: number of categories created (N)
+ 0 = no categories created
+ -1 = input map not in CELL format
+ -2 = input map error
+ -3 = output map write error
+
+ NOTE: Maps values: divides the entire range of CELL values in the input
+ map into N categories of user-specified width.
+ Range of categories can be cut by passing 'min' and 'max'
+ paremeters != -1. All values outside the range in the input map
+ will be replaced with NULL-values in the output map.
+*/
+int GT_set_c_cats_width (char *name, char *mapset, char *output,
+ int rmin, int rmax, int width, int print_progress) {
+ int fd, outfd;
+ int error;
+ struct Categories cats;
+ int i,j;
+ int rows, cols;
+ CELL *cellbuf, *outcellbuf;
+ CELL value;
+ int divisor;
+ int min, max;
+ int num;
+ char *strbuf, *strbuf2;
+ /* a flag to control quantification of the output map */
+ int cutrange = 0;
+
+ rows = G_window_rows ();
+ cols = G_window_cols ();
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-2);
+ }
+
+ /* try to open new CELL map for output */
+ outfd = G_open_cell_new (output);
+ if ( fd < 0 ) {
+ return (-3);
+ }
+
+ if (G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ G_close_cell (outfd);
+ return (-1);
+ }
+
+ if ( width < 2 ) {
+ G_fatal_error ("GT_set_c_cats_width(): Width of categories must be at least 2.");
+ }
+
+ G_init_cats (0, "", &cats);
+
+ /* FIRST PASS: analyse raster file and get min and max ints */
+ GT_get_c_range (name, mapset, &min, &max, print_progress);
+
+ /* check, if user wants to cut range and if min and max have been
+ set to sane values */
+ if ( rmin != rmax ) {
+ cutrange = 1; /* user wants to cut. Let's check ... */
+ if ( rmin > rmax ) {
+ G_warning ("User specified 'min' of input range larger than 'max'. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ if ( (rmin < min) && (cutrange == 1)) {
+ G_warning ("User specified 'min' of input range smaller than minimum CELL value. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ if ( (rmax > max) && (cutrange == 1)) {
+ G_warning ("User specified 'max' of input range larger than maximum CELL value. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ }
+
+ /* SECOND PASS: remap values, create labels and write output map */
+ cellbuf = G_allocate_raster_buf (CELL_TYPE);
+ outcellbuf = G_allocate_raster_buf (CELL_TYPE);
+ if (print_progress) {
+ fprintf (stdout, "Mapping categories: \n");
+ }
+ divisor = width;
+ num = (max - min) / width;
+ if ( num < 2 ) {
+ G_fatal_error ("GT_set_c_cats_width(): Category number must be at least 2.");
+ }
+ for (i=0; i< rows; i++) {
+ error = G_get_raster_row (fd, cellbuf, i, CELL_TYPE);
+ for (j=0; j<cols; j++) {
+ /* check for NULL values and update min and max */
+ if ( G_is_c_null_value (&cellbuf[j]) == 1) {
+ /* pass NULL values through to output map */
+ G_set_c_null_value (&outcellbuf[j],1);
+ } else {
+ /* check if any range cutting has to be done */
+ if ( cutrange ) {
+ if ( (cellbuf[j] < rmin) || (cellbuf[j] > rmax) ) {
+ G_set_c_null_value (&outcellbuf[j],1);
+ } else {
+ /* map */
+ value = abs(min) + cellbuf[j] + 1;
+ outcellbuf[j] = (int) ceil ( (double) value / (double) divisor ) - 1;
+ /* last category may be slightly larger */
+ if (outcellbuf[j] > (num-1)) {
+ outcellbuf[j] = (num-1);
+ }
+ }
+ } else {
+ /* just mapped value */
+ value = abs(min) + cellbuf[j] + 1;
+ outcellbuf[j] = (int) ceil ( (double) value / (double) divisor ) - 1;
+ /* last category may be slightly larger */
+ if (outcellbuf[j] > (num-1)) {
+ outcellbuf[j] = (num-1);
+ }
+ }
+ }
+ }
+ /* write output row */
+ G_put_c_raster_row (outfd,outcellbuf);
+ if (print_progress) {
+ G_percent (i,rows-1,1);
+ fflush (stdout);
+ }
+ }
+ if (print_progress) {
+ fprintf (stdout,"\n");
+ fflush (stdout);
+ }
+
+ /* create categories and category labels */
+ strbuf = G_calloc (255, sizeof(char));
+ strbuf2 = G_calloc (255, sizeof(char));
+ if ( cutrange ) {
+ sprintf (strbuf,"Categories mapped from %i to %i. Cut range = %i to %i ",
+ min, max, rmin, rmax);
+ } else {
+ sprintf (strbuf,"Categories mapped from %i to %i.", min , max);
+ }
+ G_set_cats_title (strbuf, &cats);
+ for (i=0; i<num; i++) {
+ sprintf (strbuf,"%i to %i", (min + i*divisor), ((min + i*divisor) + divisor));
+ /* last category may be slightly wider */
+ if (i == num-1 ) {
+ sprintf (strbuf,"%i to %i", (min + i*divisor), max);
+ }
+ G_set_cat (i, strbuf, &cats);
+ }
+
+ G_free (cellbuf);
+ G_close_cell (fd);
+ G_free (outcellbuf);
+ G_close_cell (outfd);
+ /* write category file */
+ G_write_cats (output, &cats);
+ /* write some comments into the history file */
+ sprintf (strbuf,"%s@%s",name,mapset);
+ if ( rmin != rmax ) {
+ sprintf (strbuf2,"r.categorise mode=width,%i min=%i max=%i",width, rmin, rmax);
+ } else {
+ sprintf (strbuf2,"r.categorise mode=width,%i",width);
+ }
+ GT_write_hist (output,strbuf,"Original INT data range categorised using fixed width intervals.",
+ strbuf2);
+ G_free (strbuf);
+ G_free (strbuf2);
+
+ return (num);
+}
+
+
+/* GT_set_f_cats_width () */
+/* Create a new raster map with categories ranging from 0 .. N
+ Let the user specify category width. N will then be
+ determined automatically.
+
+ ARGS: name = name of GRASS raster map to read in
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ output = name of result raster map (will always be stored
+ in the user's current mapset).
+ min, max = set to different values to cut the output range
+ (see NOTE)
+ width = width of categories to generate
+ round_cat = set to '1' to start category 0 at the nearest integer
+ value (floor).
+ intout = set to '1' to force integer (CELL) map output.
+ print_progress = set this to '1' to have a status display
+ RETURN: number of categories created (N)
+ 0 = no categories created
+ -1 = input map not in CELL format
+ -2 = input map error
+ -3 = output map write error
+
+ NOTE: Maps values: divides range of DCELL/FCELL values in the input
+ into N intervals of user specified, equal width
+ Each interval will become a category in the output map.
+ Range of categories can be cut by passing 'min' and 'max'
+ paremeters != -1. All values outside the range in the input map
+ will be replaced with NULL-values in the output map.
+ The last category in the output map might end up wider than the
+ actual maximum value in the input map.
+ To improve legibility of map legends, the intervals will start at
+ an integer offset, if 'round_cat=1'
+*/
+int GT_set_f_cats_width (char *name, char *mapset, char *output,
+ double rmin, double rmax, double width, int round_cat,
+ int intout, int print_progress) {
+ int fd, outfd;
+ int error;
+ int num;
+ struct Categories cats;
+ int i,j;
+ int rows, cols;
+ DCELL *dcellbuf;
+ CELL *outcellbuf;
+ DCELL *doutcellbuf;
+ DCELL dvalue;
+ DCELL dmin, dmax;
+ FCELL fmin, fmax;
+ double divisor;
+ double min, max;
+ char *strbuf, *strbuf2;
+ int cutrange = 0;
+ int map_type;
+
+ rows = G_window_rows ();
+ cols = G_window_cols ();
+
+ /* to disable compiler warnings */
+ outcellbuf = NULL;
+ doutcellbuf = NULL;
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-2);
+ }
+
+ /* determine mode of output map */
+ if (!G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ return (-1);
+ }
+ map_type = G_raster_map_type (name, mapset);
+ G_set_fp_type (map_type);
+
+ /* open new map for output */
+ if ( intout == 1 ) outfd = G_open_cell_new (output);
+ else outfd = G_open_fp_cell_new (output);
+ if ( outfd < 0 ) {
+ return (-3);
+ }
+
+ if ( width <= 0 ) {
+ G_fatal_error ("GT_set_f_cats_width(): Width of categories must be > 0.");
+ }
+
+ /* FIRST PASS: analyse raster file and get min and max ints */
+ GT_get_f_range (name, mapset, &min, &max, print_progress);
+
+ /* check, if user wants to cut range and if min and max have been
+ set to sane values */
+ if ( rmin != rmax ) {
+ cutrange = 1; /* user wants to cut. Let's check ... */
+ if ( rmin > rmax ) {
+ G_warning ("User specified 'min' of input range larger than 'max'. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ if ( (rmin < min) && (cutrange == 1)) {
+ G_warning ("User specified 'min' of input range smaller than minimum CELL value. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ if ( (rmax > max) && (cutrange == 1)) {
+ G_warning ("User specified 'max' of input range larger than maximum CELL value. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ }
+
+ /* do we want rounded lower category boundaries? */
+ if ( round_cat == 1 ) {
+ min = floor (min);
+ }
+
+ /* SECOND PASS: map values, create labels and write output map */
+ dcellbuf = G_allocate_raster_buf (DCELL_TYPE);
+ if ( intout == 1) outcellbuf = G_allocate_raster_buf (CELL_TYPE);
+ else {
+ doutcellbuf = G_allocate_raster_buf (DCELL_TYPE);
+ outcellbuf = NULL;
+ }
+ if (print_progress) {
+ fprintf (stdout, "Mapping categories: \n");
+ }
+ divisor = width;
+ num = (int) ((max - min) / width);
+ if ((width * num) < (max - min)) {
+ num ++;
+ }
+ if ( num < 2 ) {
+ G_fatal_error ("GT_set_f_cats_width(): Category number must be at least 2.");
+ }
+
+ for (i=0; i< rows; i++) {
+ error = G_get_raster_row (fd, dcellbuf, i, DCELL_TYPE);
+ for (j=0; j<cols; j++) {
+ /* check for NULL values and update min and max */
+ if ( G_is_d_null_value (&dcellbuf[j]) == 1) {
+ /* pass NULL values through to output map */
+ if ( intout == 1 ) G_set_c_null_value (&outcellbuf[j],1);
+ else G_set_d_null_value (&doutcellbuf[j],1);
+ } else {
+ /* check if any range cutting has to be done */
+ if ( cutrange ) {
+ if ( (dcellbuf[j] < rmin) || (dcellbuf[j] > rmax) ) {
+ if ( intout == 1 ) G_set_c_null_value (&outcellbuf[j],1);
+ else G_set_d_null_value (&doutcellbuf[j],1);
+ } else {
+ dvalue = dcellbuf[j] - min;
+ if ( intout == 1) outcellbuf[j] = (CELL) floor (dvalue / divisor);
+ else doutcellbuf[j] = dcellbuf[j];
+ if ( intout == 1 ) {
+ if ( dvalue == max ) {
+ outcellbuf[j] --;
+ }
+ }
+ }
+ } else {
+ /* just write mapped value */
+ dvalue = dcellbuf[j] - min;
+ if ( intout == 1) outcellbuf[j] = (CELL) floor (dvalue / divisor);
+ else doutcellbuf[j] = dcellbuf[j];
+ if ( intout == 1 ) {
+ if ( dvalue == max ) {
+ outcellbuf[j] --;
+ }
+ }
+ }
+ }
+ }
+ /* write output row */
+ if ( intout == 1) G_put_c_raster_row (outfd,outcellbuf);
+ else G_put_d_raster_row (outfd,doutcellbuf);
+ if (print_progress) {
+ G_percent (i, rows-1, 1);
+ fflush (stdout);
+ }
+ }
+ if (print_progress) {
+ fprintf (stdout,"\n");
+ fflush (stdout);
+ }
+ /* FIRST CLOSE RASTERS! */
+ G_free (dcellbuf);
+ G_close_cell (fd);
+ if ( intout == 1) G_free (outcellbuf);
+ else G_free (doutcellbuf);
+ G_close_cell (outfd);
+
+ /* create categories and category labels */
+ G_init_cats (num, "", &cats);
+ strbuf = G_calloc (255,sizeof(char));
+ strbuf2 = G_calloc (255,sizeof(char));
+ if ( cutrange ) {
+ sprintf (strbuf,"Categories mapped from %.3f to %.3f. Cut range = %.3f to %.3f ",
+ min, max, rmin, rmax);
+ } else {
+ sprintf (strbuf,"Categories mapped from %.3f to %.3f", min , max);
+ }
+ G_set_cats_title (strbuf, &cats);
+ for (i=0; i<num; i++) {
+ sprintf (strbuf,"%2$.*1$f to %3$.*1$f", GT_DECDIGITS, (min + i*divisor), ((min + i*divisor) + divisor));
+ if ( i == num-1 ) {
+ sprintf (strbuf,"%2$.*1$f to %3$.*1$f", GT_DECDIGITS, (min + i*divisor),
+ max);
+ }
+ if ( intout == 1 ) G_set_cat (i, strbuf, &cats); /* integer cats */
+ else {
+ /* create floating point category ranges */
+ if ( map_type == DCELL_TYPE ) {
+ dmin = (min + i*divisor);
+ dmax = (min + i*divisor) + divisor;
+ if ( i == num-1 ) {
+ dmax = (DCELL) max; /* last category always has max as roof */
+ }
+ G_set_d_raster_cat (&dmin, &dmax, strbuf, &cats);
+ }
+ if ( map_type == FCELL_TYPE ) {
+ fmin = (min + i*divisor);
+ fmax = (min + i*divisor) + divisor;
+ if ( i == num-1 ) {
+ fmax = (FCELL) max; /* last category always has max as roof */
+ }
+ G_set_f_raster_cat (&fmin, &fmax, strbuf, &cats);
+ }
+ }
+ }
+
+ /* write category file */
+ G_write_cats (output, &cats);
+
+ /* write some comments into the history file */
+ sprintf (strbuf,"%s@%s",name,mapset);
+ if ( rmin != rmax ) {
+ if ( round_cat == 0) {
+ sprintf (strbuf2,"r.categorise mode=width,%.3f min=%.3f max=%.3f",width, rmin, rmax);
+ } else {
+ sprintf (strbuf2,"r.categorise mode=rwidth,%.3f min=%.3f max=%.3f",width, rmin, rmax);
+ }
+ } else {
+ if ( round_cat == 0) {
+ sprintf (strbuf2,"r.categorise mode=width,%.3f",width);
+ } else {
+ sprintf (strbuf2,"r.categorise mode=rwidth,%.3f",width);
+ }
+ }
+ GT_write_hist (output,strbuf,"Original FP data range categorised using fixed width intervals.",
+ strbuf2);
+
+ G_free (strbuf);
+ G_free (strbuf2);
+
+ return (num);
+}
+
+
+/* GT_set_c_cats_scale () */
+/* Create a new CELL raster map with categories ranging from 0 .. N
+
+ ARGS: name = name of GRASS raster map to read in
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ output = name of result raster map (will always be stored
+ in the user's current mapset).
+ min, max = set to different values to cut the output range
+ (see NOTE)
+ print_progress = set this to '1' to have a status display
+ RETURN: number of categories created (N)
+ 0 = no categories created
+ -1 = input map not in CELL format
+ -2 = input map error
+ -3 = output map write error
+
+ NOTE: Rescales values: Smallest integer value found in the map will be
+ set to '0', largest integer will be 'N'.
+ Categories and labels will be automatically generated
+ for the entire range 0 .. N (!)
+ Range of categories can be cut by passing 'min' and 'max'
+ paremeters != -1. All values outside the range in the input map
+ will be replaced with NULL-values in the output map.
+*/
+int GT_set_c_cats_scale (char *name, char *mapset, char *output,
+ int rmin, int rmax, int print_progress) {
+ int fd, outfd;
+ int error;
+ struct Categories cats;
+ int i,j;
+ int rows, cols;
+ CELL *cellbuf, *outcellbuf;
+ int categories;
+ int min, max;
+ char *strbuf, *strbuf2;
+ /* a flag to control quantification of the output map */
+ int cutrange = 0;
+
+ rows = G_window_rows ();
+ cols = G_window_cols ();
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-2);
+ }
+
+ /* try to open new CELL map for output */
+ outfd = G_open_cell_new (output);
+ if ( outfd < 0 ) {
+ return (-3);
+ }
+
+ if (G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ G_close_cell (outfd);
+ return (-1);
+ }
+
+ /* FIRST PASS: analyse raster file and get min and max ints */
+ GT_get_c_range (name, mapset, &min, &max, print_progress);
+
+ /* check, if user wants to cut range and if min and max have been
+ set to sane values */
+ if ( rmin != rmax ) {
+ cutrange = 1; /* user wants to cut. Let's check ... */
+ if ( rmin > rmax ) {
+ G_warning ("User specified 'min' of input range larger than 'max'. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ if ( (rmin < min) && (cutrange == 1)) {
+ G_warning ("User specified 'min' of input range smaller than minimum CELL value. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ if ( (rmax > max) && (cutrange == 1)) {
+ G_warning ("User specified 'max' of input range larger than maximum CELL value. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ }
+
+ /* SECOND PASS: rescale values, create labels and write output map */
+ cellbuf = G_allocate_raster_buf (CELL_TYPE);
+ outcellbuf = G_allocate_raster_buf (CELL_TYPE);
+ if (print_progress) {
+ fprintf (stdout, "Rescaling categories: \n");
+ }
+ for (i=0; i< rows; i++) {
+ error = G_get_raster_row (fd, cellbuf, i, CELL_TYPE);
+ for (j=0; j<cols; j++) {
+ /* check for NULL values and update min and max */
+ if ( G_is_c_null_value (&cellbuf[j]) == 1) {
+ /* pass NULL values through to output map */
+ G_set_c_null_value (&outcellbuf[j],1);
+ } else {
+ /* check if any range cutting has to be done */
+ if ( cutrange ) {
+ if ( (cellbuf[j] < rmin) || (cellbuf[j] > rmax) ) {
+ G_set_c_null_value (&outcellbuf[j],1);
+ } else {
+ outcellbuf[j] = cellbuf[j] + abs (min);
+ }
+ } else {
+ /* just write rescaled value */
+ outcellbuf[j] = cellbuf[j] + abs (min);
+ }
+ }
+ }
+ /* write output row */
+ G_put_c_raster_row (outfd,outcellbuf);
+ if (print_progress) {
+ G_percent (i, rows-1,1);
+ fflush (stdout);
+ }
+ }
+ if (print_progress) {
+ fprintf (stdout,"\n");
+ fflush (stdout);
+ }
+
+ /* create categories and category labels */
+ G_init_cats (0, "", &cats);
+ strbuf = G_calloc (255,sizeof(char));
+ strbuf2 = G_calloc (255,sizeof(char));
+ if ( cutrange ) {
+ sprintf (strbuf,"Categories rescaled from %i to %i. Cut range = %i to %i ",
+ min, max, rmin, rmax);
+ } else {
+ sprintf (strbuf,"Categories rescaled from %i to %i.", min , max);
+ }
+ G_set_cats_title (strbuf, &cats);
+ categories = abs(min) + max + 1;
+ for (i=0; i < categories; i++) {
+ sprintf (strbuf,"%i",i);
+ G_set_cat (i, strbuf, &cats);
+ }
+ G_free (cellbuf);
+ G_close_cell (fd);
+ G_free (outcellbuf);
+ G_close_cell (outfd);
+
+ /* write category file */
+ G_write_cats (output, &cats);
+
+ /* write some comments into the history file */
+ sprintf (strbuf,"%s@%s",name,mapset);
+ if ( rmin != rmax ) {
+ sprintf (strbuf2,"r.categorise mode=scale min=%i max=%i",rmin, rmax);
+ } else {
+ sprintf (strbuf2,"r.categorise mode=scale");
+ }
+ GT_write_hist (output,strbuf,"Original INT data range rescaled from 0 to N.",
+ strbuf2);
+ G_free (strbuf);
+ G_free (strbuf2);
+
+ return (categories);
+}
+
+
+/* GT_set_f_cats_round () */
+/* Create a new CELL raster map with categories ranging from 0 .. N
+ Input map must be of type DCELL or FCELL.
+ Values in the input map are rounded to the nearest integer.
+
+ ARGS: name = name of GRASS raster map to read in
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ output = name of result raster map (will always be stored
+ in the user's current mapset).
+ min, max = set to different values to cut the output range
+ (see NOTE)
+ print_progress = set this to '1' to have a status display
+
+ RETURN: number of categories created (N)
+ 0 = no categories created
+ -1 = input map not in DCELL/FCELL format
+ -2 = input map error
+ -3 = output map write error
+
+ NOTE: Range of categories can be cut by passing 'min' and 'max'
+ paremeters != -1. All values outside the range in the input map
+ will be replaced with NULL-values in the output map.
+ This function uses the rintf() function for rounding, which
+ means that half-way values are rounded to the nearest even
+ integer.
+ The output map will contain as many categories as there can
+ be between the minimum and maximum rounded values in the input map.
+ Categories defined in the input map are disregarded.
+
+*/
+int GT_set_f_cats_round (char *name, char *mapset, char *output,
+ double rmin, double rmax, int print_progress) {
+ int fd, outfd;
+ int error;
+ struct Categories cats;
+ int n_cats = 0;
+ int i,j;
+ int rows, cols;
+ DCELL *dcellbuf;
+ DCELL dvalue;
+ CELL *outcellbuf;
+ char *strbuf, *strbuf2;
+ double min, max;
+ /* a flag to control quantification of the output map */
+ int cutrange = 0;
+
+ rows = G_window_rows ();
+ cols = G_window_cols ();
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-2);
+ }
+
+ /* try to open new CELL map for output */
+ outfd = G_open_cell_new (output);
+ if ( outfd < 0 ) {
+ return (-3);
+ }
+
+ if (! G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ return (-1);
+ }
+
+ dcellbuf = G_allocate_raster_buf (DCELL_TYPE);
+ outcellbuf = G_allocate_raster_buf (CELL_TYPE);
+
+ /* FIRST PASS: analyse raster file and get min and max ints */
+ GT_get_f_range (name, mapset, &min, &max, print_progress);
+
+ /* check, if user wants to cut range and if min and max have been
+ set to sane values */
+ if ( rmin != rmax ) {
+ cutrange = 1; /* user wants to cut. Let's check ... */
+ if ( rmin > rmax ) {
+ G_warning ("User specified 'min' of input range larger than 'max'. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ if ( (rmin < min) && (cutrange == 1)) {
+ G_warning ("User specified 'min' of input range smaller than minimum CELL value. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ if ( (rmax > max) && (cutrange == 1)) {
+ G_warning ("User specified 'max' of input range larger than maximum CELL value. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ }
+
+ /* SECOND PASS: do the rounding */
+ if (print_progress) {
+ fprintf (stdout, "Rounding floating point cells: \n");
+ }
+ for (i=0; i< rows; i++) {
+ error = G_get_raster_row (fd, dcellbuf, i, DCELL_TYPE);
+ /* write entire row of output map as NULL files, first */
+ G_set_c_null_value (outcellbuf, cols);
+ for (j=0; j<cols; j++) {
+ /* check for NULL value */
+ if ( !G_is_d_null_value (&dcellbuf[j]) == 1) {
+ dvalue = dcellbuf[j];
+ /* check for cutrange */
+ if ( (cutrange == 0) || ((dvalue >= rmin) && (dvalue <= rmax)) ) {
+ /* round floating point value */
+ outcellbuf[j] = (CELL) rint (dcellbuf[j]);
+ }
+ }
+ }
+ /* write one line of output map */
+ G_put_c_raster_row (outfd,outcellbuf);
+ if (print_progress) {
+ G_percent (i, rows-1, 1);
+ fflush (stdout);
+ }
+ }
+ if (print_progress) {
+ fprintf (stdout,"\n");
+ fflush (stdout);
+ }
+ G_free (dcellbuf);
+ G_close_cell (fd);
+ G_free (outcellbuf);
+ G_close_cell (outfd);
+
+ /* write N category labels to new output map */
+ n_cats = ((int) ceil (max) - (int) floor (min)) + 1;
+ G_init_cats (n_cats, "", &cats);
+ strbuf = G_calloc (255,sizeof(char));
+ for (i=0; i<n_cats; i++) {
+ sprintf (strbuf,"%i",i);
+ G_set_cat (i, strbuf, &cats);
+ }
+ sprintf (strbuf,"Rounded values from %s@%s.",name,mapset);
+ G_set_cats_title (strbuf,&cats);
+ G_write_cats (output, &cats);
+
+ /* write some comments into the history file */
+ sprintf (strbuf,"%s@%s",name,mapset);
+ strbuf2 = G_calloc (255,sizeof(char));
+ if ( rmin != rmax ) {
+ sprintf (strbuf2,"r.categorise mode=round min=%f max=%f",rmin, rmax);
+ } else {
+ sprintf (strbuf2,"r.categorise mode=round");
+ }
+ GT_write_hist (output,strbuf,"Original FP data range categorised by rounding values.",
+ strbuf2);
+ G_free (strbuf);
+ G_free (strbuf2);
+
+ return (n_cats);
+}
+
+
+/* GT_set_f_cats_trunc () */
+/* Create a new CELL raster map with categories ranging from 0 .. N
+ Input map must be of type DCELL or FCELL.
+ Values in the input map are truncated integer parts.
+
+ ARGS: name = name of GRASS raster map to read in
+ mapset = mapset to read map from (leave empty or NULL
+ for first matching map in search path)
+ output = name of result raster map (will always be stored
+ in the user's current mapset).
+ min, max = set to different values to cut the output range
+ (see NOTE)
+ print_progress = set this to '1' to have a status display
+
+ RETURN: number of categories created (N)
+ 0 = no categories created
+ -1 = input map not in DCELL/FCELL format
+ -2 = input map read error
+ -3 = output map write error
+
+ NOTE: Range of categories can be cut by passing 'min' and 'max'
+ paremeters != -1. All values outside the range in the input map
+ will be replaced with NULL-values in the output map.
+ The output map will contain as many categories as there can
+ be between the minimum and maximum truncated values in the input map.
+ Categories defined in the input map are disregarded.
+*/
+int GT_set_f_cats_trunc (char *name, char *mapset, char *output,
+ double rmin, double rmax, int print_progress) {
+
+ int fd, outfd;
+ int error;
+ struct Categories cats;
+ int n_cats = 0;
+ int i,j;
+ int rows, cols;
+ DCELL *dcellbuf;
+ DCELL dvalue;
+ CELL *outcellbuf;
+ char *strbuf, *strbuf2;
+ double min, max;
+ /* a flag to control quantification of the output map */
+ int cutrange = 0;
+
+ rows = G_window_rows ();
+ cols = G_window_cols ();
+
+ /* find first match in searchpath, if no path given */
+ if ((mapset == NULL) || (strcmp (mapset,"") == 0)) {
+ mapset = G_find_cell (name,"");
+ }
+
+ /* check for valid map */
+ fd = G_open_cell_old (name, mapset);
+ if ( fd < 0 ) {
+ return (-2);
+ }
+
+ /* try to open new CELL map for output */
+ outfd = G_open_cell_new (output);
+ if ( outfd < 0 ) {
+ return (-3);
+ }
+
+ if (! G_raster_map_is_fp (name, mapset)) {
+ G_close_cell (fd);
+ return (-1);
+ }
+
+ /* FIRST PASS: analyse raster file and get min and max ints */
+ GT_get_f_range (name, mapset, &min, &max, print_progress);
+
+ /* check, if user wants to cut range and if min and max have been
+ set to sane values */
+ if ( rmin != rmax ) {
+ cutrange = 1; /* user wants to cut. Let's check ... */
+ if ( rmin > rmax ) {
+ G_warning ("User specified 'min' of input range larger than 'max'. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ if ( (rmin < min) && (cutrange == 1)) {
+ G_warning ("User specified 'min' of input range smaller than minimum CELL value. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ if ( (rmax > max) && (cutrange == 1)) {
+ G_warning ("User specified 'max' of input range larger than maximum CELL value. Ignoring.");
+ cutrange = 0; /* cannot cut this range, so turn it off */
+ }
+ }
+
+ /* SECOND PASS: do the truncation */
+ dcellbuf = G_allocate_raster_buf (DCELL_TYPE);
+ outcellbuf = G_allocate_raster_buf (CELL_TYPE);
+ if (print_progress) {
+ fprintf (stdout, "Truncating floating point cells: \n");
+ }
+ for (i=0; i< rows; i++) {
+ error = G_get_raster_row (fd, dcellbuf, i, DCELL_TYPE);
+ /* write entire row of output map as NULL files, first */
+ G_set_c_null_value (outcellbuf, cols);
+ for (j=0; j<cols; j++) {
+ /* check for NULL value */
+ if ( !G_is_d_null_value (&dcellbuf[j]) == 1) {
+ dvalue = dcellbuf[j];
+ /* check for cutrange */
+ if ( (cutrange == 0) || ((dvalue >= rmin) && (dvalue <= rmax)) ) {
+ /* truncate floating point value */
+ outcellbuf[j] = (CELL) dcellbuf[j];
+ }
+ }
+ }
+ /* write one line of output map */
+ G_put_c_raster_row (outfd,outcellbuf);
+ if (print_progress) {
+ G_percent (i, rows-1, 1);
+ fflush (stdout);
+ }
+ }
+ if (print_progress) {
+ fprintf (stdout,"\n");
+ fflush (stdout);
+ }
+ G_free (dcellbuf);
+ G_close_cell (fd);
+ G_free (outcellbuf);
+ G_close_cell (outfd);
+
+ /* write N category labels to new output map */
+ n_cats = ((int) max - (int) min) + 1;
+ G_init_cats (n_cats, "", &cats);
+ strbuf = G_calloc (255,sizeof(char));
+ for (i=0; i<n_cats; i++) {
+ sprintf (strbuf,"%i",i);
+ G_set_cat (i, strbuf, &cats);
+ }
+ sprintf (strbuf,"Truncated values from %s@%s.",name,mapset);
+ G_set_cats_title (strbuf,&cats);
+ G_write_cats (output, &cats);
+
+ /* write some comments into the history file */
+ sprintf (strbuf,"%s@%s",name,mapset);
+ strbuf2 = G_calloc (255,sizeof(char));
+ if ( rmin != rmax ) {
+ sprintf (strbuf2,"r.categorise mode=trunc min=%f max=%f",rmin, rmax);
+ } else {
+ sprintf (strbuf2,"r.categorise mode=trunc");
+ }
+ GT_write_hist (output,strbuf,"Original FP data range categorised by rounding values.",
+ strbuf2);
+
+ G_free (strbuf);
+ G_free (strbuf2);
+
+ return (n_cats);
+}
+
+/* GT_write_hist () */
+/* A convenience function to add some simple metadata (history) to
+ a GRASS raster file in the user's current mapset.
+
+ ARGS: name = name of raster file
+ source = description of source file (e.g. raster file from
+ which the current one was derived)
+ desc = a one-line description of the data
+ comment = any one-line comment
+
+ NOTE: all char* arguments except 'name' may be NULL, in which
+ case the corresponding history entries will be left empty.
+ ALL HISTORY ENTRIES MAY BE AT MOST 80 CHARS LONG !!!
+*/
+int GT_write_hist (char *name, char* source, char *desc, char *comment) {
+
+ struct History hist;
+ int error;
+
+ error = G_short_history (name, "raster", &hist);
+ if (error != 1) return (error);
+
+ if ( source != NULL) strcpy (hist.datsrc_1, source);
+ if ( desc != NULL ) strcpy (hist.keywrd, desc);
+ hist.edlinecnt = 1;
+ if ( comment != NULL) strcpy (hist.edhist[0], comment);
+
+ error = G_write_history (name, &hist);
+ if (error != 0) return (error);
+
+ return (0);
+}
+
+/* GT_set_decdigits () */
+/* This function sets the global variable GT_DECDIGITS */
+/* which controls the number of decimal digits displayed */
+/* in the raster history files and category labels. */
+void GT_set_decdigits (unsigned int digits) {
+ GT_DECDIGITS = digits;
+}
Property changes on: grass-addons/grass6/dst/lib/gt_raster/cat_engine.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/lib/gt_raster/rowcache.c
===================================================================
--- grass-addons/grass6/dst/lib/gt_raster/rowcache.c (rev 0)
+++ grass-addons/grass6/dst/lib/gt_raster/rowcache.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,462 @@
+/* ROWCACHE.C */
+
+/* Part of the GRASS Toolkit (GT) functions collection */
+/* Purpose: provide a raster cache that retrieves rows from memory instead of disk, if possible. */
+/* This should speed up operations where the same row has to be read more than once. */
+
+/* This file is licensed under the GPL (version 2) */
+/* see: http://www.gnu.org/copyleft/gpl.html */
+
+/* (c) Benjamin Ducke 2004 */
+/* benducke at compuserve.de */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <grass/gis.h>
+#include "gt/rowcache.h"
+
+
+/* returns the slot number in the lookup table for a cached raster row */
+/* should actually be a hash function instead of this */
+/* return: lookup table index or -1 if row is not in cache */
+long GT_RC_lookup_slot (GT_Row_cache_t *cache, long row) {
+ int i = 0;
+ for (i=0; i <= cache->max; i++) {
+ if (cache->allocated_lookup[i] == row) {
+ return (i);
+ }
+ }
+ /* raster row not currently cached */
+ return (-1);
+}
+
+void GT_RC_update_worst (GT_Row_cache_t *cache, long hit) {
+ int i = 0;
+ int most_misses = 0;
+
+ cache->worst=cache->allocated_lookup[0];
+ /* the following loops act on every slot except 'hit' */
+ /* which is the only one that does not get its misses increased */
+ for ( i = 0; i <= cache->max; i++) {
+ if (cache->allocated_lookup[i] != hit) {
+ if (cache->data_type == CELL_TYPE) {
+ if ((cache->c_cache_area[cache->allocated_lookup[i]] != NULL) &&
+ (cache->allocated_lookup[i] > -1))
+ {
+ cache->misses[cache->allocated_lookup[i]]++;
+ if (cache->misses[cache->allocated_lookup[i]] > most_misses) {
+ most_misses = cache->misses[cache->allocated_lookup[i]];
+ cache->worst = cache->allocated_lookup[i];
+ }
+ }
+ }
+ if (cache->data_type == DCELL_TYPE) {
+ if ((cache->d_cache_area[cache->allocated_lookup[i]] != NULL) &&
+ (cache->allocated_lookup[i] > -1))
+ {
+ cache->misses[cache->allocated_lookup[i]]++;
+ if (cache->misses[cache->allocated_lookup[i]] > most_misses) {
+ most_misses = cache->misses[cache->allocated_lookup[i]];
+ cache->worst = cache->allocated_lookup[i];
+ }
+ }
+ }
+ if (cache->data_type == FCELL_TYPE) {
+ if ((cache->f_cache_area[cache->allocated_lookup[i]] != NULL) &&
+ (cache->allocated_lookup[i] > -1))
+ {
+ cache->misses[cache->allocated_lookup[i]]++;
+ if (cache->misses[cache->allocated_lookup[i]] > most_misses) {
+ most_misses = cache->misses[cache->allocated_lookup[i]];
+ cache->worst = cache->allocated_lookup[i];
+ }
+ }
+ }
+ }
+ }
+}
+
+long GT_RC_find_worst (GT_Row_cache_t *cache) {
+ return (cache->worst);
+}
+
+
+/* tries to allocate a block of n cache rows */
+/* no memory is actually allocated! This function */
+/* frees all allocated memory before exiting */
+/* returns n (same value), if enough mem is present, -1 otherwise */
+int GT_RC_try_alloc (long n, RASTER_MAP_TYPE data_type ) {
+
+ void *try;
+
+ if ( data_type == CELL_TYPE ) {
+ try = calloc ((unsigned long) n, sizeof (CELL*));
+ if (try == NULL) {
+ return (-1);
+ } else {
+ free (try);
+ }
+ }
+ if ( data_type == FCELL_TYPE ) {
+ try = calloc ((unsigned long) n, sizeof (FCELL*));
+ if (try == NULL) {
+ return (-1);
+ } else {
+ free (try);
+ }
+ }
+ if ( data_type == DCELL_TYPE ) {
+ try = calloc ((unsigned long)n, sizeof (DCELL*));
+ if (try == NULL) {
+ return (-1);
+ } else {
+ free (try);
+ }
+ }
+ return (0);
+}
+
+/* open a new row cache on a GRASS rast map */
+/* n = number of raster rows to store in cache */
+/* fd = file descriptor to associate with cache */
+/* NOTE: fd must NOT be closed by caller, it will be closed automatically */
+/* by GT_RC_close() */
+/* RASTER_MAP_TYPE may be CELL, DCELL or FCELL */
+int GT_RC_open (GT_Row_cache_t *cache, long n, int fd, RASTER_MAP_TYPE data_type) {
+ long i;
+ long rows;
+
+ /* turn cache on by defult */
+ cache->off = 0;
+
+ /* 1: see if user requested a certain size and if we have that much mem */
+ if ( n == 0 ) {
+ G_warning ("Cache has been turned off by user request.\n");
+ cache->off = 1;
+ n = 1; /* even a cache that was turned off needs to store one row */
+ }
+
+ if ( n > 0 ) {
+ if ( GT_RC_try_alloc (n, data_type) == -1) {
+ G_warning ("Requested cache size cannot be allocated.\n");
+ /* set to auto mode */
+ n = -1;
+ }
+ }
+ /* 2: else: fall back to auto mode, try 20% of total rows, than 10%, than 5% */
+ if ( n == -1 ) {
+ /* try 20 percent first */
+ n = (G_window_rows()/100) * 20;
+ if ( GT_RC_try_alloc (n, data_type) == -1) {
+ n = (G_window_rows() / 100) * 10;
+ if ( GT_RC_try_alloc (n, data_type) == -1) {
+ n = (G_window_rows() / 100) * 5;
+ if ( GT_RC_try_alloc (n, data_type) == -1) {
+ /* it's no longer any use: just turn off the cache! */
+ G_warning ("Insufficient memory for cache: turned off.\n");
+ cache->off = 1;
+ n = 1;
+ }
+ }
+ }
+ }
+
+ cache->max = n-1;
+ cache->allocated = 0;
+ cache->fd = fd;
+ cache->worst = 0;
+ cache->region_rows = G_window_rows(); /* store these values for faster access */
+ cache->region_cols = G_window_cols(); /* store these values for faster access */
+ cache->data_type = data_type;
+
+ rows = G_window_rows ();
+
+ cache->misses = G_calloc (rows, sizeof(long));
+ for (i=0; i<rows;i++) {
+ cache->misses[i] = 0;
+ }
+ /* allocate pointers according to type of raster */
+ if (data_type == CELL_TYPE) {
+ cache->c_cache_area = G_calloc (rows,sizeof (CELL*));
+ for (i = 0; i<n; i++) {
+ cache->c_cache_area[i] = NULL;
+ }
+ }
+ if (data_type == DCELL_TYPE) {
+ cache->d_cache_area = G_calloc (rows,sizeof (DCELL*));
+ for (i = 0; i<n; i++) {
+ cache->d_cache_area[i] = NULL;
+ }
+ }
+ if (data_type == FCELL_TYPE) {
+ cache->f_cache_area = G_calloc (rows,sizeof (FCELL*));
+ for (i = 0; i<n; i++) {
+ cache->f_cache_area[i] = NULL;
+ }
+ }
+
+ /* if cache turned off, we cannot dynamically allocate, so do it now! */
+ if ( cache->off == 1 ) {
+ if (data_type == CELL_TYPE) {
+ cache->c_cache_area[0] = G_allocate_raster_buf(CELL_TYPE);
+ }
+ if (data_type == DCELL_TYPE) {
+ cache->d_cache_area[0] = G_allocate_raster_buf(DCELL_TYPE);
+ }
+ if (data_type == FCELL_TYPE) {
+ cache->f_cache_area[0] = G_allocate_raster_buf(FCELL_TYPE);
+ }
+ }
+
+ cache->allocated_lookup = G_calloc (n, sizeof(long));
+ for (i=0;i<n;i++) {
+ cache->allocated_lookup[i] = -1; /* -1 marks free entry */
+ }
+ return (0);
+};
+
+/* retreives row 'i' from the cache */
+void* GT_RC_get (GT_Row_cache_t *cache, long i) {
+
+ int error;
+ char tmp[255];
+ struct Cell_head region;
+
+ /* if cache was turned off: just read row from disk and return it */
+ if ( cache->off == 1 ) {
+ if ( cache->data_type == CELL_TYPE ) {
+ error = G_get_c_raster_row (cache->fd,cache->c_cache_area[0],i);
+ if ( error == -1 ) {
+ G_get_window (®ion);
+ G_fatal_error ("Cache failure: could not read CELL raster row at %.2f.\n",
+ G_row_to_northing((float) i,®ion));
+ }
+ return (CELL*) (cache->c_cache_area[0]);
+ }
+ if ( cache->data_type == DCELL_TYPE ) {
+ error = G_get_d_raster_row (cache->fd,cache->d_cache_area[0],i);
+ if ( error == -1 ) {
+ G_get_window (®ion);
+ G_fatal_error ("Cache failure: could not read CELL raster row at %.2f.\n",
+ G_row_to_northing((float) i,®ion));
+ }
+ return (DCELL*) (cache->d_cache_area[0]);
+ }
+ if ( cache->data_type == FCELL_TYPE ) {
+ error = G_get_f_raster_row (cache->fd,cache->f_cache_area[0],i);
+ if ( error == -1 ) {
+ G_get_window (®ion);
+ G_fatal_error ("Cache failure: could not read CELL raster row at %.2f.\n",
+ G_row_to_northing((float) i,®ion));
+ }
+ return (FCELL*) (cache->f_cache_area[0]);
+ }
+ }
+
+ if ((i < 0) || (i >= cache->region_rows)) {
+ G_get_window (®ion);
+ sprintf (tmp,"Illegal cache request: row %i at Northing %.2f.\n",(int)i,
+ G_row_to_northing((float)i,®ion));
+ G_fatal_error ( "%s", (char*) tmp);
+ }
+
+ if (cache->data_type == CELL_TYPE) {
+ if (cache->c_cache_area[i] == NULL) {
+ /* case one: cache miss */
+ if (cache->allocated < (cache->max+1)) { /* still got spare slots in cache */
+ cache->c_cache_area[i] = G_allocate_raster_buf(CELL_TYPE);
+ /* put row into cache */
+ error = G_get_c_raster_row (cache->fd,cache->c_cache_area[i],i);
+ if ( error == -1 ) {
+ G_get_window (®ion);
+
+ G_fatal_error ("Cache failure: could not read CELL raster row at %.2f.\n",
+ G_row_to_northing((float)i,®ion));
+ }
+ cache->allocated_lookup[cache->allocated] = i;
+ cache->allocated ++;
+ cache->misses[i] = 0;
+ /* increase cache miss count on all other rows */
+ GT_RC_update_worst (cache, i);
+ return (CELL*) (cache->c_cache_area[i]);
+ } else {
+ /* if max cache allocated, we have to throw out one row */
+ /* find row with most misses and de-allocate it*/
+ G_free (cache->c_cache_area[GT_RC_find_worst(cache)]);
+ cache->c_cache_area[GT_RC_find_worst(cache)] = NULL;
+ /* put row into cache */
+ cache->c_cache_area[i] = G_allocate_raster_buf(CELL_TYPE);
+ error = G_get_c_raster_row (cache->fd,cache->c_cache_area[i],i);
+ if ( error == -1 ) {
+ G_get_window (®ion);
+ G_fatal_error ("Cache failure: could not read CELL raster row at %.2f.\n",
+ G_row_to_northing((float)i,®ion));
+ }
+ cache->allocated_lookup[GT_RC_lookup_slot(cache, GT_RC_find_worst (cache))] = i;
+ cache->misses[i] = 0;
+ /* increase cache miss count on all other rows */
+ GT_RC_update_worst (cache, i);
+ return (CELL*) (cache->c_cache_area[i]);
+ }
+ } else {
+ /* case two: row in cache */
+ /* that's good: we have to do nothing but return a pointer to the row */
+ cache->misses[i] = 0;
+ /* increase cache miss count on all other rows */
+ GT_RC_update_worst (cache, i);
+ return (CELL*) (cache->c_cache_area[i]);
+ }
+ }
+
+ if (cache->data_type == DCELL_TYPE) {
+ if (cache->d_cache_area[i] == NULL) {
+ /* case one: cache miss */
+ if (cache->allocated < (cache->max+1)) { /* still got spare slots in cache */
+ cache->d_cache_area[i] = G_allocate_raster_buf(DCELL_TYPE);
+ /* put row into cache */
+ error = G_get_d_raster_row (cache->fd,cache->d_cache_area[i],i);
+ if ( error == -1 ) {
+ G_get_window (®ion);
+ G_fatal_error ("Cache failure: could not read DCELL raster row at %.2f.\n",
+ G_row_to_northing((float)i,®ion));
+ }
+ cache->allocated_lookup[cache->allocated] = i;
+ cache->allocated ++;
+ cache->misses[i] = 0;
+ /* increase cache miss count on all other rows */
+ GT_RC_update_worst (cache, i);
+ return (DCELL*) (cache->d_cache_area[i]);
+ } else {
+ /* if max cache allocated, we have to throw out one row */
+ /* find row with most misses and de-allocate it*/
+ G_free (cache->d_cache_area[GT_RC_find_worst(cache)]);
+ cache->d_cache_area[GT_RC_find_worst(cache)] = NULL;
+ /* put row into cache */
+ cache->d_cache_area[i] = G_allocate_raster_buf(DCELL_TYPE);
+ error = G_get_d_raster_row (cache->fd,cache->d_cache_area[i],i);
+ if ( error == -1 ) {
+ G_get_window (®ion);
+ G_fatal_error ("Cache failure: could not read DCELL raster row at %.2f.\n",
+ G_row_to_northing((float)i,®ion));
+ }
+ cache->allocated_lookup[GT_RC_lookup_slot(cache, GT_RC_find_worst (cache))] = i;
+ cache->misses[i] = 0;
+ /* increase cache miss count on all other rows */
+ GT_RC_update_worst (cache, i);
+ return (DCELL*) (cache->d_cache_area[i]);
+ }
+ } else {
+ /* case two: row in cache */
+ /* that's good: we have to do nothing but return a pointer to the row */
+ cache->misses[i] = 0;
+ /* increase cache miss count on all other rows */
+ GT_RC_update_worst (cache, i);
+ return (DCELL*) (cache->d_cache_area[i]);
+ }
+ }
+
+ if (cache->data_type == FCELL_TYPE) {
+ if (cache->f_cache_area[i] == NULL) {
+ /* case one: cache miss */
+ if (cache->allocated < (cache->max+1)) { /* still got spare slots in cache */
+ cache->f_cache_area[i] = G_allocate_raster_buf(FCELL_TYPE);
+ /* put row into cache */
+ error = G_get_f_raster_row (cache->fd,cache->f_cache_area[i],i);
+ if ( error == -1 ) {
+ G_get_window (®ion);
+ G_fatal_error ("Cache failure: could not read FCELL raster row at %.2f.\n",
+ G_row_to_northing((float)i,®ion));
+ }
+ cache->allocated_lookup[cache->allocated] = i;
+ cache->allocated ++;
+ cache->misses[i] = 0;
+ /* increase cache miss count on all other rows */
+ GT_RC_update_worst (cache, i);
+ return (FCELL*) (cache->f_cache_area[i]);
+ } else {
+ /* if max cache allocated, we have to throw out one row */
+ /* find row with most misses and de-allocate it*/
+ G_free (cache->f_cache_area[GT_RC_find_worst(cache)]);
+ cache->f_cache_area[GT_RC_find_worst(cache)] = NULL;
+ /* put row into cache */
+ cache->f_cache_area[i] = G_allocate_raster_buf(FCELL_TYPE);
+ error = G_get_f_raster_row (cache->fd,cache->f_cache_area[i],i);
+ if ( error == -1 ) {
+ G_get_window (®ion);
+ G_fatal_error ("Cache failure: could not read FCELL raster row at %.2f.\n",
+ G_row_to_northing((float)i,®ion));
+ }
+ cache->allocated_lookup[GT_RC_lookup_slot(cache, GT_RC_find_worst (cache))] = i;
+ cache->misses[i] = 0;
+ /* increase cache miss count on all other rows */
+ GT_RC_update_worst (cache, i);
+ return (FCELL*) (cache->f_cache_area[i]);
+ }
+ } else {
+ /* case two: row in cache */
+ /* that's good: we have to do nothing but return a pointer to the row */
+ cache->misses[i] = 0;
+ /* increase cache miss count on all other rows */
+ GT_RC_update_worst (cache, i);
+ return (FCELL*) (cache->f_cache_area[i]);
+ }
+ }
+
+ return (NULL);
+};
+
+/* closes cache, frees allocated memory */
+void GT_RC_close (GT_Row_cache_t *cache) {
+ /* release all memory used to cache rows */
+ int i;
+
+ if (cache->off == 1) {
+ for (i = 0; i < cache->region_rows;i++) {
+ if (cache->data_type == CELL_TYPE) {
+ if (cache->c_cache_area[i] != NULL) {
+ G_free (cache->c_cache_area[i]);
+ cache->c_cache_area[i] = NULL;
+ }
+ }
+ if (cache->data_type == DCELL_TYPE) {
+ if (cache->d_cache_area[i] != NULL) {
+ G_free (cache->d_cache_area[i]);
+ cache->d_cache_area[i] = NULL;
+ }
+ }
+ if (cache->data_type == FCELL_TYPE) {
+ if (cache->f_cache_area[i] != NULL) {
+ G_free (cache->f_cache_area[i]);
+ cache->f_cache_area[i] = NULL;
+ }
+ }
+ }
+ if (cache->data_type == CELL_TYPE) {
+ G_free (cache->c_cache_area);
+ }
+ if (cache->data_type == DCELL_TYPE) {
+ G_free (cache->d_cache_area);
+ }
+ if (cache->data_type == FCELL_TYPE) {
+ G_free (cache->f_cache_area);
+ }
+ } else {
+ if (cache->data_type == CELL_TYPE) {
+ G_free (cache->c_cache_area[0]);
+ G_free (cache->c_cache_area);
+ }
+ if (cache->data_type == DCELL_TYPE) {
+ G_free (cache->d_cache_area[0]);
+ G_free (cache->d_cache_area);
+ }
+ if (cache->data_type == FCELL_TYPE) {
+ G_free (cache->f_cache_area[0]);
+ G_free (cache->f_cache_area);
+ }
+ }
+
+ G_free (cache->misses);
+ G_free (cache->allocated_lookup);
+ G_close_cell (cache->fd);
+};
Property changes on: grass-addons/grass6/dst/lib/gt_raster/rowcache.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/lib/gt_stats/Makefile
===================================================================
--- grass-addons/grass6/dst/lib/gt_stats/Makefile (rev 0)
+++ grass-addons/grass6/dst/lib/gt_stats/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,17 @@
+MODULE_TOPDIR = ../..
+
+GSL_LIB = `gsl-config --libs`
+GSL_INC = `gsl-config --cflags`
+LIB_NAME = gt_stats
+LIB_OBJS = gstats_tests.o gstats_gain.o gstats_error.o
+EXTRA_CFLAGS = -I../../include $(GSL_INC)
+EXTRA_LIBS=$(GISLIB) $(GSL_LIB)
+
+include $(MODULE_TOPDIR)/include/Make/Lib.make
+
+default: lib headers
+
+headers:
+ if [ ! -d $(GISBASE)/include ]; then $(MKDIR) $(GISBASE)/include; fi
+ if [ ! -d $(GISBASE)/include/gt ]; then $(MKDIR) $(GISBASE)/include/gt; fi
+ $(INSTALL) -m 644 ../../include/gt/*.h $(GISBASE)/include/gt/
Added: grass-addons/grass6/dst/lib/gt_stats/gstats_error.c
===================================================================
--- grass-addons/grass6/dst/lib/gt_stats/gstats_error.c (rev 0)
+++ grass-addons/grass6/dst/lib/gt_stats/gstats_error.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,20 @@
+#include <grass/gis.h>
+
+#include "gt/gstats_global.h"
+
+void gstats_error ( char *message ) {
+ if (GSTATS_FATAL) {
+ G_fatal_error ("GSTATS: %s", message);
+ } else {
+ G_warning ("GSTATS: %s", message);
+ }
+}
+
+void gstats_error_warning ( void ) {
+ GSTATS_FATAL = 0;
+}
+
+void gstats_error_fatal ( void ) {
+ GSTATS_FATAL = 1;
+}
+
Property changes on: grass-addons/grass6/dst/lib/gt_stats/gstats_error.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/lib/gt_stats/gstats_gain.c
===================================================================
--- grass-addons/grass6/dst/lib/gt_stats/gstats_gain.c (rev 0)
+++ grass-addons/grass6/dst/lib/gt_stats/gstats_gain.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,30 @@
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <grass/gis.h>
+
+/* Purpose: calculate Kvamme's gain index */
+
+double gstats_gain_K (double sample, double area) {
+
+ double kvamme_gain = 0;
+
+ if (sample > area) {
+ if ( area == 0 ) {
+ kvamme_gain = 1;
+ } else {
+ kvamme_gain = 1 - ( area / sample );
+ }
+ }
+
+ if (sample < area) {
+ if ( sample == 0 ) {
+ kvamme_gain = -1;
+ } else {
+ kvamme_gain = (-1) + ( sample / area );
+ }
+ }
+
+ return (kvamme_gain);
+};
Property changes on: grass-addons/grass6/dst/lib/gt_stats/gstats_gain.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/lib/gt_stats/gstats_tests.c
===================================================================
--- grass-addons/grass6/dst/lib/gt_stats/gstats_tests.c (rev 0)
+++ grass-addons/grass6/dst/lib/gt_stats/gstats_tests.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,302 @@
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <gsl/gsl_types.h>>
+#include <gsl/gsl_integration.h>
+#include <gsl/gsl_randist.h>
+#include <gsl/gsl_cdf.h>
+
+#include <grass/gis.h>
+
+#include "gt/gstats_error.h"
+
+
+
+/* Purpose: chi square test for differences in frequencies between sample and
+ population
+ Parameters: *observed = array of ints with event counts for each category
+ in the sample
+ *expected = array of ints with event counts for each category
+ as expected from the known population
+ k = number of categories
+ df = degrees of freedom (e.g. k-1)
+ Returns: Probability of making an error when rejecting the NULL hypothesis
+ -1 if data does not support Chi^2 test
+*/
+double gstats_test_XF (int *observed, int *expected, int k, int df) {
+ double chi;
+ int i;
+ long sum, sum2;
+ double checksum;
+ int lessThanFive;
+
+ if ( df < 1 ) {
+ gstats_error ("Chi^2 test: need at least one category with expected frequency > 0.");
+ return (-1);
+ }
+
+ if ( k < 2 ) {
+ gstats_error ("Chi^2 test: number of categories must be > 1.");
+ return (-1);
+ }
+
+ lessThanFive = 0; /* keeps count of categories with < 1 expected frequency */
+
+ /* check if parameters given make sense */
+ sum = 0;
+ sum2 = 0;
+ for (i = 0; i < k; i++) {
+ sum = sum + observed [i];
+ sum2 = sum2 + expected [i];
+ }
+
+ if ( sum < 2 ) {
+ gstats_error ("Chi^2 test: sum of observed frequencies over all categories must be > 2.");
+ return (-1);
+ }
+
+ if ( sum2 < 2 ) {
+ gstats_error ("Chi^2 test: sum of expected frequencies over all categories must be > 2.");
+ return (-1);
+ }
+
+ /* finally, calculate Chi! */
+ chi = 0;
+ for (i = 0; i < k; i++) {
+ if (expected[i] > 0) {
+ chi = chi + ( ((float) ((observed[i]-expected[i])*(observed[i]-expected[i])) / expected[i]) );
+ if (expected[i] < 5) {
+ lessThanFive ++;
+ }
+ }
+ else {
+ gstats_error ("Chi^2 test: expected frequency for category < 1.");
+ return (-1);
+ }
+ }
+
+ /* check if more than 20% of categories have less than 5 observations */
+ checksum = lessThanFive / ((double) (k)/100.0);
+ if (checksum > 20) {
+ gstats_error ("Chi^2 test: more than 20% of categories have an expected frequency < 5.");
+ return (-1);
+ }
+
+ return (gsl_ran_chisq_pdf (chi, (double) df));
+}
+
+
+
+/* Purpose: Relaxed chi square test for differences in frequencies between observed and
+ expected frequencies. This version keeps going, even if expected frequencies (E) are < 5 in
+ more than 20% of the categories. This also excludes skips categories that
+ have E = 0, reducing degrees of freedom accordingly.
+ Parameters: *observed = array of ints with event counts for each category
+ in the sample
+ *expected = array of ints with event counts for each category
+ as expected from the known population
+ k = number of categories
+ df = degrees of freedom (e.g. k-1)
+ Returns: Probability of making an error when rejecting the NULL hypothesis
+ -1 if data does not support Chi^2 test
+*/
+double gstats_rtest_XF (int *observed, int *expected, int k, int df) {
+ double chi;
+ int i;
+ long sum, sum2;
+
+ if ( df < 1 ) {
+ gstats_error ("Chi^2 test: need at least one category with expected frequency > 0.");
+ return (-1);
+ }
+
+ if ( k < 2 ) {
+ gstats_error ("Chi^2 test: number of categories must be > 1.");
+ return (-1);
+ }
+
+ /* check if parameters given make sense */
+ sum = 0;
+ sum2 = 0;
+ for (i = 0; i < k; i++) {
+ sum = sum + observed [i];
+ sum2 = sum2 + expected [i];
+ }
+
+ if ( sum < 2 ) {
+ gstats_error ("Chi^2 test: sum of observed frequencies over all categories must be > 2.");
+ return (-1);
+ }
+
+ if ( sum2 < 2 ) {
+ gstats_error ("Chi^2 test: sum of expected frequencies over all categories must be > 2.");
+ return (-1);
+ }
+
+ /* finally, calculate Chi! */
+ chi = 0;
+ for (i = 0; i < k; i++) {
+ if (expected[i] > 0) {
+ chi = chi + ( ((float) ((observed[i]-expected[i])*(observed[i]-expected[i])) / expected[i]) );
+ }
+ else {
+ df --;
+ if ( df < 1 ) {
+ gstats_error ("Chi^2 test: need at least one category with expected frequency > 0.");
+ return (-1);
+ }
+ }
+ }
+
+ return (gsl_ran_chisq_pdf (chi, (double) df));
+}
+
+
+/* Purpose: calculate z test for proportions, two-tailed for two-sided hypothesis H1 != H0
+ Parameters: p_sample = proportion of events in sample [0..1]
+ p_population = proportion of events in population [0..1]
+ n = sample size
+ Returns: Probability of making an error when rejecting the NULL hypothesis
+*/
+double gstats_test_ZP2 (double p_sample, double p_population, int n) {
+ double z;
+ double result = 0.0;
+
+
+ if ((p_sample < 0.0) || (p_sample > 1.0)) {
+ gstats_error ("z-stat: sample proportion must be given as 0.0 - 1.0.");
+ }
+
+ if ((p_population < 0.0) || (p_population > 1.0)) {
+ gstats_error ("z-stat: population proportion must be given as 0.0 - 1.0.");
+ }
+
+ if (n < 2) {
+ gstats_error ("z-stat: size of population must be a positive integer > 0.");
+ }
+
+ z = (p_sample - p_population) /
+ (sqrt ( (p_population * (1-p_population)) / n) );
+
+ /* determine direction of numeric integration */
+ if ( p_sample > p_population ) {
+ /* we use a normal distribution, if n is at least 30, */
+ /* t-distribution with n - 1 degress of freedom, otherwise */
+ if (n >= 30) {
+ result = gsl_cdf_ugaussian_Q (z);
+ } else {
+ result = gsl_cdf_tdist_Q (z, (double) n-1);
+ }
+ }
+ if ( p_sample < p_population ) {
+ /* we use a normal distribution, if n is at least 30, */
+ /* t-distribution with n - 1 degress of freedom, otherwise */
+ if (n >= 30) {
+ result = gsl_cdf_ugaussian_P (z);
+ } else {
+ result = gsl_cdf_tdist_P (z, (double) n-1);
+ }
+ }
+ if ( p_sample == p_population ) {
+ result = 0.5;
+ }
+
+ return (result * 2);
+}
+
+
+/* Purpose: calculate z test for proportions, lower tail for one-sided hypothesis H1 < H0
+ Parameters: p_sample = proportion of events in sample [0..1]
+ p_population = proportion of events in population [0..1]
+ n = sample size
+ Returns: Probability of making an error when rejecting the NULL hypothesis
+*/
+double gstats_test_ZPL (double p_sample, double p_population, int n) {
+ double z;
+ double result = 0.0;
+
+
+ if ((p_sample < 0.0) || (p_sample > 1.0)) {
+ gstats_error ("z-stat: sample proportion must be given as 0.0 - 1.0.");
+ }
+
+ if ((p_population < 0.0) || (p_population > 1.0)) {
+ gstats_error ("z-stat: population proportion must be given as 0.0 - 1.0.");
+ }
+
+ if (n < 2) {
+ gstats_error ("z-stat: size of population must be a positive integer > 0.");
+ }
+
+ if (p_sample > p_population) {
+ gstats_error ("z-stat: sample prop. > population prop., cannot calculate lower tail of distribution.");
+ }
+
+ z = (p_sample - p_population) /
+ (sqrt ( (p_population * (1-p_population)) / n) );
+
+ /* determine direction of numeric integration */
+ if ( p_sample < p_population ) {
+ /* we use a normal distribution, if n is at least 30, */
+ /* t-distribution with n - 1 degress of freedom, otherwise */
+ if (n >= 30) {
+ result = gsl_cdf_ugaussian_P (z);
+ } else {
+ result = gsl_cdf_tdist_P (z, (double) n-1);
+ }
+ }
+ if ( p_sample == p_population ) {
+ result = 0.5;
+ }
+
+ return (result);
+}
+
+
+/* Purpose: calculate z test for proportions, upper tail for one-sided hypothesis H1 > H0
+ Parameters: p_sample = proportion of events in sample [0..1]
+ p_population = proportion of events in population [0..1]
+ n = sample size
+ Returns: Probability of making an error when rejecting the NULL hypothesis
+*/
+double gstats_test_ZPU (double p_sample, double p_population, int n) {
+ double z;
+ double result = 0.0;
+
+
+ if ((p_sample < 0.0) || (p_sample > 1.0)) {
+ gstats_error ("z-stat: sample proportion must be given as 0.0 - 1.0.");
+ }
+
+ if ((p_population < 0.0) || (p_population > 1.0)) {
+ gstats_error ("z-stat: population proportion must be given as 0.0 - 1.0.");
+ }
+
+ if (n < 2) {
+ gstats_error ("z-stat: size of population must be a positive integer > 0.");
+ }
+
+ if (p_sample < p_population) {
+ gstats_error ("z-stat: sample prop. < population prop., cannot calculate upper tail of distribution.");
+ }
+
+ z = (p_sample - p_population) /
+ (sqrt ( (p_population * (1-p_population)) / n) );
+
+ /* determine direction of numeric integration */
+ if ( p_sample > p_population ) {
+ /* we use a normal distribution, if n is at least 30, */
+ /* t-distribution with n - 1 degress of freedom, otherwise */
+ if (n >= 30) {
+ result = gsl_cdf_ugaussian_Q (z);
+ } else {
+ result = gsl_cdf_tdist_Q (z, (double) n-1);
+ }
+ }
+ if ( p_sample == p_population ) {
+ result = 0.5;
+ }
+
+ return (result);
+}
Property changes on: grass-addons/grass6/dst/lib/gt_stats/gstats_tests.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/lib/gt_vector/Makefile
===================================================================
--- grass-addons/grass6/dst/lib/gt_vector/Makefile (rev 0)
+++ grass-addons/grass6/dst/lib/gt_vector/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,15 @@
+MODULE_TOPDIR = ../..
+
+LIB_NAME = gt_vector
+LIB_OBJS = gt_vector.o
+EXTRA_CFLAGS = -I../../include
+EXTRA_LIBS = $(GISLIB)
+
+include $(MODULE_TOPDIR)/include/Make/Lib.make
+
+default: lib headers
+
+headers:
+ if [ ! -d $(GISBASE)/include ]; then $(MKDIR) $(GISBASE)/include; fi
+ if [ ! -d $(GISBASE)/include/gt ]; then $(MKDIR) $(GISBASE)/include/gt; fi
+ $(INSTALL) -m 644 ../../include/gt/*.h $(GISBASE)/include/gt/
Added: grass-addons/grass6/dst/lib/gt_vector/gt_vector.c
===================================================================
--- grass-addons/grass6/dst/lib/gt_vector/gt_vector.c (rev 0)
+++ grass-addons/grass6/dst/lib/gt_vector/gt_vector.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,939 @@
+/*
+
+TODO:
+
+eliminate DEBUG statements
+
+Catch all calls to alloc() and free () in a custom function that keeps track of
+memory allocation in map->mem_size
+
+NULL data handling: NULL attributes can be handled by managing an array of short ints
+that can be set to 1 to signify a NULL attribute at that record.
+But: how do NULL atts appear in the original data? As missing values? As special codes?
+
+from d.what.vect:
+
+fprintf( stdout, _("Layer: %d\ncategory: %d\n"), Cats->field[j], Cats->cat[j] );
+
+currently, map->field seems to point to the currently layer's db connection, after:
+map->field = Vect_get_field (&map->in_vect_map, map->vect_cats->field[ map->current_layer - 1 ]);
+
+For advanced analytical operations, we need to able to open a map in level 2!
+Any analytical function requiring this should check if that has already been done,
+ if not attempt to open level 2, if that fails: warn or abort.
+
+Speed up attribute operations: copy all attribute values into an internal array, upon first
+query for that attribute (cache status=dirty). Serve all queries from that cache in the future.
+Set cache status back to dirty, if sth. has changed in the attribute table or another record
+has been added, so that the cache will be rebuilt on next access.
+
+Use Vect_get_num_updated_lines() and Vect_get_updated_line() to determine if cache needs to
+be set to dirty.
+
+A function that will return the numerical value of an attribute as type double, as long as
+that attribute is any number format (integer, double, ...)
+
+A function that checks, if an attribute of any numerical type exists (GVT_num_exists()).
+
+*/
+
+/* split into low and high level functions (e.g. export new vector map from SQL selection */
+
+/* if layer number = -1, parse all layers (see Martin Landa's recent posting; do other GRASS
+ modules handle it this way, too? Should this be default when opening a map? */
+
+/* in addition to the global
+
+ int GVT_NO_REGION_CONSTRAINTS;
+ int GVT_NO_TYPE_CONSTRAINTS;
+ int GVT_NO_SQL_CONSTRAINTS;
+
+ we need to be able to set these for each map, individually, too!
+
+ */
+
+
+#define GVT_DEBUG 1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <grass/gis.h>
+#include <grass/dbmi.h>
+#include <grass/Vect.h>
+
+#include "gt/gt_vector.h"
+
+
+/*
+ Check if GVT has been initialized and abort, if not.
+*/
+int GVT_check_init ( void ) {
+ return (0);
+}
+
+
+/*
+ Check if a vector map has been opened and signal a file error, if not.
+ The error will be fatal and program execution aborted, GVT_FATAL_FILE_ERRORS = TRUE.
+ Otherwise, the function will return FALSE.
+ It will return TRUE, if the map has been opened in the specified level:
+ 1 = geometries and attributes
+ 2 = same as 1 plus full topological information
+*/
+int GVT_check_opened ( GVT_map_s *map, int open_level ) {
+
+ if ( map->open_level >= open_level ) {
+ return ( TRUE );
+ }
+
+ if ( GVT_FATAL_FILE_ERRORS ) {
+ G_fatal_error ("GVT: attempted to access a map that had not been opened.\n");
+ }
+
+ return ( FALSE );
+}
+
+
+/* Allocates memory for a vector map, keeping track of the amount
+ of mem allocated in a counter in the struct.
+*/
+void * GVT_malloc ( size_t size, GVT_map_s *map ) {
+ void *p;
+ char tmp [2048];
+
+ p = G_malloc ( size );
+ if ( p == NULL ) {
+ /* TODO: %i is not the right type */
+ sprintf ( tmp, "GVT: failed to allocate %i bytes of memory.\n", size );
+ if ( GVT_FATAL_MEM_ERRORS )
+ G_fatal_error ( "%s", tmp );
+ G_warning ( "%s", tmp );
+ return (p);
+ }
+ map->mem_size = map->mem_size + size;
+ return (p);
+}
+
+
+/*
+
+ PUBLIC FUNCTIONS
+
+*/
+
+
+/*
+ Initializes a bunch of global variables to default values.
+ Always call this function once in your program before using
+ any other GVT functions!
+*/
+void GVT_init ( void ) {
+ GVT_NO_REGION_CONSTRAINTS = FALSE;
+ GVT_NO_TYPE_CONSTRAINTS = FALSE;
+ GVT_NO_SQL_CONSTRAINTS = FALSE;
+
+ GVT_NO_ATTRIBUTE_CACHING = FALSE;
+ GVT_MAX_CACHE_SIZE = 100000;
+
+ GVT_FATAL_FILE_ERRORS = TRUE;
+ GVT_FATAL_TYPE_ERRORS = TRUE;
+ GVT_FATAL_MEM_ERRORS = TRUE;
+
+ GVT_INIT_DONE = TRUE;
+}
+
+
+
+/* returns a pointer to a new GVT_map_s structure */
+/* caller must not pre-allocate that pointer! */
+GVT_map_s *GVT_new_map ( void ) {
+ GVT_map_s *map;
+ char tmp [2048];
+
+ struct Cell_head window;
+
+ map = G_malloc ( sizeof (GVT_map_s));
+ if ( map == NULL ) {
+ sprintf ( tmp, "GVT: failed to allocate %i bytes of memory for new map.\n",
+ sizeof (GVT_map_s) );
+ if ( GVT_FATAL_MEM_ERRORS )
+ G_fatal_error ( "%s", tmp );
+ G_warning ( "%s", tmp );
+ return (map);
+ }
+ map->mem_size = map->mem_size + sizeof (GVT_map_s);
+ map->open_level = -1;
+
+ /* TODO: keep track of number of bytes alloc'd */
+ map->vect_points = Vect_new_line_struct ();
+ map->vect_cats = Vect_new_cats_struct ();
+
+ /* -2 indicates, that no records exist in this map, yet */
+ map->current_record = -2;
+
+ /* DEFAULT CONSTRAINTS */
+ /* filter vector objects to current region and point types only */
+ G_get_window (&window);
+ Vect_set_constraint_region (&map->in_vect_map, window.north, window.south,
+ window.east, window.west, window.top, window.bottom);
+ map->north = window.north;
+ map->south = window.south;
+ map->east = window.east;
+ map->west = window.west;
+ map->top = window.top;
+ map->bottom = window.bottom;
+
+ /* set SQL string to NULL */
+ db_init_string ( &map->sql );
+ db_set_string ( &map->sql, GVT_EMPTY_SQL );
+
+ /*lat-long location? */
+ if ( G_projection () == 3 ) {
+ map->isLatLong = TRUE;
+ } else {
+ map->isLatLong = FALSE;
+ }
+
+ /* distance calculations will be needed for lots of analytical applications, so might as
+ well initialize it right now ...
+ */
+ G_begin_distance_calculations ();
+
+ map->hasData = FALSE;
+ map->num_layers = 0;
+ map->num_attributes = 0;
+ map->current_layer = 0;
+ map->current_record = 0;
+
+ return ( map );
+}
+
+
+/* returns number of free'd bytes */
+int GVT_free_map (GVT_map_s *map) {
+
+ int freed = 0;
+
+ /* TODO: keep track of number of bytes dealloc'd */
+
+ if ( map == NULL ) {
+ return (0);
+ }
+
+ /* TODO: free:
+ Vect_new_line_struct ();
+ Vect_new_cats_struct ();
+ */
+
+ free ( map );
+
+ /* TODO: compare amount free'd with map->mem_size */
+
+ return ( freed );
+};
+
+
+/* constraints can only be set or unset when openening a new map! */
+/* returns the open level of the map */
+/* TODO: open in level2 ? */
+/* TODO: let user choose open level and abort/warn if it cannot be reached */
+int GVT_open_map ( char *mapname, int type, GVT_map_s *map ) {
+ char *mapset;
+ char tmp [2048];
+ int i, j, dbcol;
+
+ dbColumn *column;
+ dbValue *dbvalue;
+ int ctype, sqltype, more;
+ char *colname;
+
+ if ( map->hasData ) {
+ G_fatal_error ("GVT: attempted to load data into an already opened map.\n");
+ }
+
+ /* DO NOT ALLOCATE ANYTHING IN THE *MAP STRUCT BETWEEN HERE ... */
+
+ if ( map->open_level > -1 ) {
+ sprintf (tmp, "GVT: Attempted to re-open vector map already opened in level %i.\n", map->open_level );
+ if ( GVT_FATAL_FILE_ERRORS )
+ G_fatal_error ( "%s", tmp);
+ G_warning ( "%s", tmp );
+ return (-1);
+ }
+
+ /* TODO: check if a valid type has been specified */
+ /* and exit, if GVT_FATAL_TYPE_ERRORS is set */
+
+ /* check if map exists and if there are > 0 vector points in
+ the specified layer */
+ if ((mapset = G_find_vector2 (mapname, "")) == NULL) {
+ free (mapset);
+ sprintf (tmp, "GVT: could not open vector map: %s.\n", mapname );
+ if ( GVT_FATAL_FILE_ERRORS )
+ G_fatal_error ( "%s", tmp);
+ G_warning ( "%s", tmp );
+ return (-1);
+ }
+
+ /* if success opening the vector map: */
+ map->open_level = 0;
+
+ /* attempt to open input map at level 1 */
+ Vect_set_open_level (1);
+ if (1 > Vect_open_old (&map->in_vect_map, mapname, mapset)) {
+ Vect_close (&map->in_vect_map);
+ free (mapset);
+ map->open_level = -1; /* reset open level */
+ sprintf (tmp, "GVT: could not open vector map for level 1 access: %s.\n", mapname );
+ if ( GVT_FATAL_FILE_ERRORS )
+ G_fatal_error ( "%s", tmp);
+ G_warning ( "%s", tmp );
+ return (-1);
+ }
+ map->open_level = 1;
+
+
+ /* ... AND HERE ! */
+
+ /* TODO: override constraints, if appropriate global vars have been set */
+
+ /* DEFAULT CONSTRAINTS */
+ /* filter vector objects to current region and point types only */
+ Vect_set_constraint_region (&map->in_vect_map, map->north, map->south,
+ map->east, map->west, map->top, map->bottom);
+ Vect_set_constraint_type (&map->in_vect_map, type);
+ map->type_constraints = type;
+
+ map->type = type;
+
+ if ( Vect_is_3d ( &map->in_vect_map ) ) {
+ map->is3d = TRUE;
+ } else {
+ map->is3d = FALSE;
+ }
+
+ sprintf ( map->name, "%s", mapname );
+
+ /* calculate number of vector points in map and current region */
+ map->num_records = 0;
+ /* TODO: map->type = : this should not be necessary if type constraints are in effect! */
+ while ((map->type = Vect_read_next_line (&map->in_vect_map, map->vect_points, map->vect_cats)) > 0) {
+ map->num_records ++;
+ }
+ /* TODO: determine number of layers and repeat the object counting for all layers */
+ /* exit, if no layer has the type requested and GVT_FATAL_TYPE_ERRORS is set */
+ /* save number of layers with valid type and associated layer numbers */
+
+ /* check for attributes */
+ /* TODO: this needs to be done for all layers, as given by n_cats (?)
+ so make sure there are no mem leaks in this loop
+ */
+ map->num_layers = 0;
+ map->current_layer = 0;
+ for ( i = 0; i < map->vect_cats->n_cats; i++ ) {
+ map->field = Vect_get_field (&map->in_vect_map, map->vect_cats->field[i]);
+ /* TODO: in which cases could field == NULL? what to do then? */
+ if ( map->field == NULL ) {
+
+ }
+ /* TODO: catch cases without a DB connection */
+ if ( map->field != NULL ) {
+ map->num_attributes = 0;
+ map->driver = db_start_driver ( map->field->driver );
+ db_init_handle ( &map->handle );
+ db_set_handle ( &map->handle, map->field->database, NULL);
+ if (db_open_database(map->driver, &map->handle) != DB_OK){
+ /* TODO: DB access failed */
+ db_shutdown_driver( map->driver );
+ } else {
+ sprintf ( map->sql_buf, "select * from %s where %s = %d ",
+ map->field->table,
+ map->field->key,
+ map->vect_cats->cat[i]);
+ db_set_string ( &map->sql, map->sql_buf );
+ db_open_select_cursor(map->driver, &map->sql, &map->cursor, DB_SEQUENTIAL);
+ map->table = db_get_cursor_table (&map->cursor);
+ db_fetch ( &map->cursor, DB_NEXT, &more );
+ map->dbncols = db_get_table_number_of_columns (map->table);
+ /* TODO: lots of the vars in here should not be part of GVT_map_s struct
+ many of them need to be tracked for each layer separately
+ */
+
+ map->num_attributes = map->dbncols; /* TODO: this is actually redundant but more readable */
+ map->att_names = G_calloc ( (unsigned) map->num_attributes, sizeof (char*));
+ map->att_types = G_calloc ( (unsigned) map->num_attributes, sizeof (short int));
+
+ for ( dbcol = 0; dbcol < map->dbncols; dbcol ++ ) {
+ map->num_attributes ++; /* count number of attributes */
+ column = db_get_table_column(map->table, dbcol);
+ sqltype = db_get_column_sqltype (column);
+ ctype = db_sqltype_to_Ctype(sqltype);
+ map->att_types[dbcol] = ctype;
+ dbvalue = db_get_column_value(column);
+ db_convert_value_to_string( dbvalue, sqltype, &map->str);
+ colname = (char*) db_get_column_name (column);
+ map->att_names[dbcol] = strdup ( colname ); /* save this attribute name */
+ if ( (ctype!=GVT_DOUBLE) && (GVT_INT) && (GVT_STRING) && (GVT_DATETIME) ) {
+ G_warning ("GVT: attribute %s is of unknown type.\n", colname);
+ }
+ }
+
+ /* create cache pointers and set all caches to dirty but don't read in attributes yet!*/
+ /* to keep cache addressing simple, we will allocate num_attributes caches for each type */
+ /* but later only allocate mem at the positions where it is really needed. */
+ map->cache_status = G_calloc ((unsigned) map->num_attributes, sizeof (short int));
+ map->cache_double = G_calloc ((unsigned) map->num_attributes, sizeof (double*));
+ map->cache_int = G_calloc ((unsigned) map->num_attributes, sizeof (long int*));
+ map->cache_char = G_calloc ((unsigned) map->num_attributes, sizeof (char*));
+ map->cache_datetime = G_calloc ((unsigned) map->num_attributes, sizeof (char*));
+ /* by setting all caches to dirty, we make sure that memory will be allocated and all attributes read */
+ /* into them the first time they are needed. */
+ for ( j = 0; j < map->num_attributes; j ++ ) {
+ map->cache_status[j] = GVT_CACHE_INIT;
+ }
+
+ /* TODO: keep these open for calls of GVT_get_double () etc. */
+ db_close_cursor(&map->cursor);
+ db_close_database( map->driver);
+ db_shutdown_driver( map->driver);
+ }
+ }
+ map->num_layers ++;
+ }
+
+ /* TODO: activate first layer of given type */
+ map->current_layer = 1;
+
+ /* TODO: */
+ /* init attribute caches for current layer (?) */
+
+
+ Vect_rewind (&map->in_vect_map);
+ map->current_record = -1;
+ free (mapset);
+
+ return ( map->open_level );
+}
+
+
+int GVT_open_map_points ( char *mapname, int type, GVT_map_s *map ) {
+ return ( GVT_open_map ( mapname, GV_POINT, map ) );
+}
+
+
+void GVT_close_map ( GVT_map_s *map ) {
+ Vect_close (&map->in_vect_map);
+ map->current_record = -2;
+ map->hasData = FALSE;
+ /* TODO: what else needs to be done? */
+}
+
+
+/* jump to first record */
+void GVT_first ( GVT_map_s *map ) {
+ Vect_rewind ( &map->in_vect_map );
+ Vect_read_next_line (&map->in_vect_map, map->vect_points, map->vect_cats);
+ map->current_record = 0;
+}
+
+
+/* jump to next record */
+/* returns:
+ 1 (TRUE) SUCCESS
+ 0 (FALSE) NO MORE RECORDS (EOF)
+*/
+int GVT_next ( GVT_map_s *map ) {
+ /* TODO: does this honor current type constraints? */
+ if ( Vect_read_next_line (&map->in_vect_map, map->vect_points, map->vect_cats) > 0 ) {
+ map->current_record ++;
+ return ( TRUE );
+ } else {
+ return ( FALSE );
+ }
+}
+
+
+/* jump to last record */
+void GVT_last ( GVT_map_s *map ) {
+ GVT_seek ( map->num_records-1, map );
+ map->current_record = map->num_records-1;
+}
+
+
+/* rewind database: jump to position before first record! */
+void GVT_rewind ( GVT_map_s *map ) {
+ Vect_rewind ( &map->in_vect_map );
+ map->current_record = -1;
+}
+
+
+/* rewind and refilter data using SQL string */
+/* first record has position 0 ! */
+/* last record has position map->num_records-1 ! */
+/* returns:
+ 1 (TRUE) SUCCESS
+ 0 (FALSE attempting to seek to illegal position
+*/
+int GVT_seek ( long int pos, GVT_map_s *map ) {
+ long int i;
+
+ /* TODO: check, if this work also with layers of mixed types! */
+ if ( pos < 0 ) {
+ return ( FALSE );
+ }
+ if ( pos > map->num_records-1 ) {
+ return ( FALSE );
+ }
+
+ Vect_rewind ( &map->in_vect_map );
+ for ( i = 0; i <= pos; i ++ ) {
+ Vect_read_next_line (&map->in_vect_map, map->vect_points, map->vect_cats);
+ }
+ map->current_record = i;
+ return ( TRUE );
+}
+
+
+/* returns ID (cat - 1) of currently active record */
+/* TODO: maybe return cat (current_record + 1)
+ is ID always = cat-1?
+*/
+long int GVT_get_current ( GVT_map_s *map ) {
+ return ( map->current_record );
+}
+
+
+void GVT_query () {
+}
+
+/*
+ check, if an attribute of a specified name and type exists
+*/
+
+int GVT_double_exists ( char *name, GVT_map_s *map ) {
+ return ( GVT_attr_exists (name, GVT_DOUBLE, map));
+}
+
+int GVT_int_exists ( char *name, GVT_map_s *map ) {
+ return ( GVT_attr_exists (name, GVT_INT, map));
+}
+
+
+int GVT_attr_exists ( char *name, int type, GVT_map_s *map ) {
+ int i;
+
+ GVT_check_opened (map, 1); /* map needs to be open at least in level 1 */
+
+ for ( i=0; i < map->num_attributes; i++ ) {
+ if ( !strcmp (map->att_names[i], name) ) {
+ if ( map->att_types[i] == type ) {
+ return (TRUE);
+ }
+ }
+ }
+
+ return ( FALSE );
+}
+
+
+/* checks if an attribute of any type exists in map */
+int GVT_any_exists ( char *name, GVT_map_s *map ) {
+ int i;
+
+ GVT_check_opened (map, 1); /* map needs to be open at least in level 1 */
+
+ for ( i=0; i < map->num_attributes; i++ ) {
+ if ( !strcmp (map->att_names[i], name) ) {
+ return (TRUE);
+ }
+ }
+
+ return ( FALSE );
+}
+
+
+/* Returns the contents of an attribute field of type 'type' in the map's attribute table */
+/* Memory will be allocated for the return value and must be free'd by the caller */
+/* if no longer needed. */
+/* TODO: this is far too much overhead for reading a single attribute! */
+/* fill attribute cache on first access, serve queries from cache until dirty */
+/* implement this in a function *GVT_get_attribute (). But keep this version as */
+/* an internal function that can be used if caching is turned off */
+/* check for attribute exist is already done by user-visible function, so at
+ this point we can have confidence that it exists! */
+char *GVT_get_attribute_no_cache ( char *name, int type, GVT_map_s *map ) {
+ int dbcol;
+ int found;
+
+ dbColumn *column;
+ dbValue *dbvalue;
+ int ctype, sqltype, more;
+ char *colname;
+
+ map->field = Vect_get_field (&map->in_vect_map, map->vect_cats->field[ map->current_layer - 1 ]);
+ /* TODO: in which cases could field == NULL? what to do then? */
+ /* TODO: catch cases without a DB connection */
+ if ( map->field != NULL ) {
+ /* TODO: we should not need to re-open everything, if GVT_open_map () does not close it */
+ map->driver = db_start_driver ( map->field->driver );
+ db_init_handle ( &map->handle );
+ db_set_handle ( &map->handle, map->field->database, NULL);
+ if (db_open_database(map->driver, &map->handle) != DB_OK){
+ /* TODO: DB access failed */
+ db_shutdown_driver( map->driver );
+ } else {
+ sprintf ( map->sql_buf, "select * from %s where %s = %d ",
+ map->field->table,
+ map->field->key,
+ map->vect_cats->cat[ map->current_layer - 1 ]);
+ db_set_string ( &map->sql, map->sql_buf );
+ db_open_select_cursor(map->driver, &map->sql, &map->cursor, DB_SEQUENTIAL);
+ map->table = db_get_cursor_table (&map->cursor);
+ db_fetch ( &map->cursor, DB_NEXT, &more );
+ map->dbncols = db_get_table_number_of_columns (map->table);
+ /* TODO: lots of the vars in here should not be part of GVT_map_s struct
+ many of them need to be tracked for each layer separately
+ */
+ found = FALSE;
+ /* TODO: too much overhead: better to keep a list of attributes in GVT_map_s and search that! */
+ /* use internal function GVT_attr_exists () for that. */
+ for ( dbcol = 0; dbcol < map->dbncols; dbcol ++ ) {
+ column = db_get_table_column(map->table, dbcol);
+ sqltype = db_get_column_sqltype (column);
+ ctype = db_sqltype_to_Ctype(sqltype);
+ colname = (char*) db_get_column_name (column);
+ if (!strcmp (colname,name)){
+ if (ctype == type) {
+ found = TRUE;
+ dbvalue = db_get_column_value(column);
+ db_convert_value_to_string( dbvalue, sqltype, &map->str); /* TODO: now we could actually skip the other runs of this loop: */
+ /* return (val) */
+ /* BUT CLEAN UP FIRST! */
+ } else {
+ /* TODO: abort if not double attribute or return something strange to signify this */
+ return ( NULL );
+ }
+ }
+ }
+ db_close_cursor(&map->cursor);
+ db_close_database( map->driver);
+ db_shutdown_driver( map->driver);
+ if ( found == FALSE ) {
+ return ( NULL );
+ }
+ }
+ }
+
+ return ( strdup (db_get_string ( &map->str )) );
+}
+
+
+/*
+ This function is user-visible
+*/
+char *GVT_get_attribute ( char *name, int type, GVT_map_s *map ) {
+ /* TODO: implement attribute caching */
+ return (GVT_get_attribute_no_cache ( name, type, map ));
+}
+
+
+/*
+ read a double attribute from a map
+
+ Returns:
+ NULL, if reading failed
+ double value of attribute, otherwise
+*/
+double GVT_get_double ( char *name, GVT_map_s *map) {
+
+ char *aval;
+ double dval;
+
+ /* todo: check, if attribute exists and has right type */
+
+ aval = GVT_get_attribute ( name, GVT_DOUBLE, map );
+ if ( aval == NULL ) {
+ /* TODO: implement NULL value handling */
+ G_fatal_error ("GVT: error reading double attribute '%s'.\n", name);
+ }
+
+ dval = atof ( db_get_string ( &map->str ) );
+ return ( dval );
+}
+
+
+/* TODO: this is far too much overhead for reading a single attribute! */
+/* fill attribute cache on first access, serve queries from cache until dirty */
+long int GVT_get_int ( char *name, GVT_map_s *map) {
+
+ char *aval;
+ long int ival;
+
+ /* todo: check, if attribute exists and has right type */
+
+ aval = GVT_get_attribute ( name, GVT_DOUBLE, map );
+ if ( aval == NULL ) {
+ /* TODO: implement NULL value handling */
+ G_fatal_error ("GVT: error reading double attribute '%s'.\n", name);
+ }
+
+ ival = atol ( db_get_string ( &map->str ) );
+ return ( ival );
+}
+
+
+/* TODO: implement C API attribute writes in GVT_set_double2 and delete this version ! */
+/* this writes a new value into a double type attribute of the current record */
+int GVT_set_double ( char *name, double dvalue, GVT_map_s *map ) {
+
+ char tmp [GVT_MAX_STRING_SIZE];
+ int error;
+
+ map->field = Vect_get_field (&map->in_vect_map, map->vect_cats->field[ map->current_layer - 1 ]);
+ /* TODO: in which cases could field == NULL? what to do then? */
+ /* TODO: catch cases without a DB connection */
+ if ( map->field != NULL ) {
+ sprintf ( tmp, "echo \"UPDATE %s SET %s=%f WHERE cat=%d\" | db.execute", map->name, name, dvalue, map->vect_cats->cat[map->current_layer - 1]);
+ error = system ( tmp );
+ }
+
+ return ( TRUE );
+}
+
+
+
+/* TODO: this is far too much overhead for reading a single attribute! */
+/* (same as GVT_get_double) */
+/* write a value into a double attribute */
+/* returns:
+ 1 (TRUE) SUCCESS: VALUE SET
+ 0 (FALSE) FAILURE
+*/
+int GVT_set_double2 ( char *name, double dvalue, GVT_map_s *map ) {
+ int dbcol;
+ int found;
+
+ dbColumn *column;
+ dbValue *dbvalue;
+ int ctype, sqltype, more;
+ char *colname;
+
+ map->field = Vect_get_field (&map->in_vect_map, map->vect_cats->field[ map->current_layer - 1 ]);
+ /* TODO: in which cases could field == NULL? what to do then? */
+ /* TODO: catch cases without a DB connection */
+ if ( map->field != NULL ) {
+ /* TODO: we should not need to re-open everything, if GVT_open_map () does not close it */
+ map->driver = db_start_driver ( map->field->driver );
+ db_init_handle ( &map->handle );
+ db_set_handle ( &map->handle, map->field->database, NULL);
+ if (db_open_database(map->driver, &map->handle) != DB_OK){
+ /* TODO: DB access failed */
+ db_shutdown_driver( map->driver );
+ } else {
+ sprintf ( map->sql_buf, "select * from %s where %s = %d ",
+ map->field->table,
+ map->field->key,
+ map->vect_cats->cat[ map->current_layer - 1 ]);
+ db_set_string ( &map->sql, map->sql_buf );
+ db_open_select_cursor(map->driver, &map->sql, &map->cursor, DB_SEQUENTIAL);
+
+ map->table = db_get_cursor_table (&map->cursor);
+ db_fetch ( &map->cursor, DB_NEXT, &more );
+ map->dbncols = db_get_table_number_of_columns (map->table);
+ /* TODO: lots of the vars in here should not be part of GVT_map_s struct
+ many of them need to be tracked for each layer separately
+ */
+ found = FALSE;
+ /* TODO: too much overhead: better to keep a list of attributes in GVT_map_s and search that! */
+ for ( dbcol = 0; dbcol < map->dbncols; dbcol ++ ) {
+ column = db_get_table_column(map->table, dbcol);
+ sqltype = db_get_column_sqltype (column);
+ ctype = db_sqltype_to_Ctype(sqltype);
+ colname = (char*) db_get_column_name (column);
+ if (!strcmp (colname,name)){
+ if (ctype == DB_C_TYPE_DOUBLE) {
+ found = TRUE;
+ dbvalue = db_get_column_value(column); /* dbvalue now points to attribute */
+ db_convert_value_to_string( dbvalue, sqltype, &map->str);
+ if ( db_test_value_isnull ( dbvalue ) ) {
+ fprintf ( stderr, " NULL\n" );
+ }
+ db_set_value_double (dbvalue, dvalue);
+ db_convert_value_to_string( dbvalue, sqltype, &map->str);
+ fprintf ( stderr, "SETTING %s TO: %f\n", db_get_string ( &map->str ), dvalue );
+
+ /* TODO: now we could actually skip the other runs of this loop! */
+ } else {
+ /* TODO: abort if not double attribute or return something strange to signify this */
+ return (FALSE);
+ }
+ }
+ }
+ db_close_cursor(&map->cursor);
+ db_close_database( map->driver);
+ db_shutdown_driver( map->driver);
+ if ( found == FALSE ) {
+ /* TODO: check if attribute exists */
+ return (FALSE);
+ }
+ }
+ }
+
+ return ( TRUE );
+}
+
+
+/* check if an attribute is NULL */
+int GVT_is_null () {
+ /* look at functions in lib/db/dbmi_base:
+ column.c: db_test_column_null_allowed ();
+ value.c: db_test_value_isnull (dbValue *value)
+ */
+ return ( FALSE );
+}
+
+
+int GVT_set_null () {
+ return ( TRUE );
+}
+
+
+/* append new record
+*/
+int GVT_append ( ) {
+ return ( TRUE );
+}
+
+
+/* delete record
+*/
+int GVT_delete ( ) {
+ return ( TRUE );
+}
+
+
+/* seek to first record that matches
+ a search string
+*/
+int GVT_find () {
+ return ( TRUE );
+}
+
+
+int GVT_find_next () {
+ return ( TRUE );
+}
+
+
+/* create a new double attribute
+ returns:
+ 1 (TRUE) SUCCESS
+ 0 (FALSE) FAILURE
+*/
+int GVT_add_double ( char *name, GVT_map_s *map ) {
+ char buf [GVT_MAX_STRING_SIZE];
+ int error;
+
+ /* TODO: replace system call with appropriate C API calls */
+ /* TODO: check if column with same name (but different type) exists */
+
+ sprintf ( buf, "echo \"ALTER TABLE %s ADD COLUMN %s double precision\" | db.execute", map->name, name );
+ fprintf ( stderr, "%s\n", buf );
+ error = system ( buf );
+
+ return ( TRUE );
+}
+
+
+/* delete an attribute from a table
+*/
+int GVT_drop_double ( char *name, GVT_map_s *map ) {
+ /* TODO: replace system call with appropriate C API calls */
+ /* NOTE: db.execute seems to not support DROP COLUMN statements! */
+ return ( TRUE );
+}
+
+
+long int GVT_get_num_records ( GVT_map_s *map ) {
+ return ( map->num_records );
+}
+
+
+int GVT_is_lat_long ( GVT_map_s *map ) {
+ return ( map->isLatLong );
+}
+
+
+/* pass NULL for constraints that you don't want to touch */
+int GVT_set_constraints ( struct Cell_head *window, char *SQL, GVT_map_s *map ) {
+
+ if ( window != NULL ) {
+ map->north = window->north;
+ map->south = window->south;
+ map->east = window->east;
+ map->west = window->west;
+ map->top = window->top;
+ map->bottom = window->bottom;
+ }
+
+ if ( SQL != NULL ) {
+ }
+ return (0);
+}
+
+
+
+int GVT_get_constraints ( void ) {
+ return (0);
+}
+
+
+int GVT_constraints ( int type, int SQL, int region ) {
+ return (0);
+}
+
+
+/* returns the file name of the map */
+char *GVT_get_mapname ( GVT_map_s *map ) {
+ /* first check, if opened */
+ return (NULL);
+}
+
+
+/* returns the mapset of the map */
+char *GVT_get_mapset ( GVT_map_s *map ) {
+ /* first check, if opened */
+ return (NULL);
+}
+
+
+/* ANALYTICAL FUNCTIONS */
+
+/* gets the 2D distance from the point in the map's current record
+ to the point defined by x and y
+ This also works for lat long locations
+*/
+double GVT_get_2D_point_distance ( double x, double y, GVT_map_s *map ) {
+ double d = 0.0;
+ double px, py;
+
+ /* TODO: check if it's a points map! */
+
+ if ( map->isLatLong ) {
+ px = *map->vect_points->x;
+ py = *map->vect_points->y;
+ d = G_geodesic_distance ( x, y, px, py );
+ } else {
+ /* TODO: implement distance for simple cartesian space */
+ }
+
+ return (d);
+}
+
+
+
+
+
+
Property changes on: grass-addons/grass6/dst/lib/gt_vector/gt_vector.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/misc/Makefile
===================================================================
--- grass-addons/grass6/dst/misc/Makefile (rev 0)
+++ grass-addons/grass6/dst/misc/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,16 @@
+MODULE_TOPDIR = ..
+
+SUBDIRS = \
+ m.dst.create \
+ m.dst.source \
+ m.dst.update \
+ m.dst.view \
+ m.filter.gen
+
+include $(MODULE_TOPDIR)/include/Make/Dir.make
+
+default: htmldir
+
+htmldir: subdirs
+
+clean: cleansubdirs
Added: grass-addons/grass6/dst/misc/m.dst.create/Makefile
===================================================================
--- grass-addons/grass6/dst/misc/m.dst.create/Makefile (rev 0)
+++ grass-addons/grass6/dst/misc/m.dst.create/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,11 @@
+MODULE_TOPDIR = ../..
+
+PGM = m.dst.create
+
+XMLLIB = `xml2-config --libs`
+LIBES = $(GISLIB) $(DATETIMELIB) $(XMLLIB)
+EXTRA_CFLAGS+=`xml2-config --cflags`
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
Added: grass-addons/grass6/dst/misc/m.dst.create/description.html
===================================================================
--- grass-addons/grass6/dst/misc/m.dst.create/description.html (rev 0)
+++ grass-addons/grass6/dst/misc/m.dst.create/description.html 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<TITLE>dst.create</TITLE>
+
+<body bgcolor="white">
+
+<H2>NAME</H2>
+
+<EM><b>dst.list</b></EM>, <EM><b>dst.create</b></EM>,
+<EM><b>dst.remove</b></EM>, <EM><b>dst.rename</b></EM> - Manage Dempster-Shafer knowledge base files in the current mapset.
+<BR>
+<EM>(GRASS Dempster-Shafer Knowledge Base File Management Programs)</EM>
+
+<p></p>
+Please refer to manual page of <EM><A HREF="dst.list.html">dst.list</A></EM>.
+
+</body>
+</html>
Property changes on: grass-addons/grass6/dst/misc/m.dst.create/description.html
___________________________________________________________________
Added: svn:mime-type
+ text/html
Added: svn:keywords
+ Author Date Id
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/misc/m.dst.create/main.c
===================================================================
--- grass-addons/grass6/dst/misc/m.dst.create/main.c (rev 0)
+++ grass-addons/grass6/dst/misc/m.dst.create/main.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,88 @@
+/*
+ Creates a new XML file on disk with the basic structure
+ of a Dempster Shafer knowledge base.
+
+ Any existing file of the same name will be overwritten!
+
+*/
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#include <grass/gis.h>
+
+int
+main (int argc, char *argv[])
+{
+ struct GModule *module;
+ struct
+ {
+ struct Option *file;
+ }
+ parm;
+
+ FILE *kb; /* knowledge base */
+
+ xmlDocPtr doc;
+ xmlNodePtr cur;
+ xmlNodePtr root;
+
+
+ /* setup some basic GIS stuff */
+ G_gisinit (argv[0]);
+ module = G_define_module ();
+ module->description = "Creates a new Dempster-Shafer knowledge base file.";
+
+ /* do not pause after a warning message was displayes */
+ G_sleep_on_error (0);
+
+ /* Parameters */
+ parm.file = G_define_option ();
+ parm.file->key = "file";
+ parm.file->type = TYPE_STRING;
+ parm.file->required = YES;
+ parm.file->description = "Filename for the new knowledge base";
+
+ /* parse command line */
+ if (G_parser (argc, argv))
+ {
+ exit (-1);
+ }
+
+ /* existing files will be overwritten! */
+ errno = 0;
+ kb = fopen (parm.file->answer,"w+");
+ if ( kb == NULL ) {
+ G_fatal_error ("Cannot open knowledge base file for writing.\nReason: %s.", strerror (errno));
+ } else {
+ fclose(kb);
+ }
+
+ /* create basic XML structure */
+ root = xmlNewNode(NULL, (xmlChar *) "dst-kb");
+ xmlSetProp(root,(xmlChar*) "N_SINGLETONS", (xmlChar*) "0");
+ /* the NULL hypotheses (empty set) is implicit */
+ xmlSetProp(root,(xmlChar*) "N_HYPOTHESES", (xmlChar*) "1");
+ /* initial number of groups in the knowledge base */
+ xmlSetProp(root,(xmlChar*) "N_GROUPS", (xmlChar*) "0");
+
+ xmlNewTextChild (root, NULL, "hyp", "NULL");
+
+ doc = xmlNewDoc("1.0");
+ xmlDocSetRootElement(doc, root);
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ xmlSetProp(cur,(xmlChar*) "TYPE", (xmlChar*) "NULL");
+
+ if (xmlSaveFormatFile (parm.file->answer, doc, 1) == -1) {
+ G_fatal_error ("Error creating XML file.\n");
+ }
+
+ exit (EXIT_SUCCESS));
+}
Property changes on: grass-addons/grass6/dst/misc/m.dst.create/main.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/misc/m.dst.source/Makefile
===================================================================
--- grass-addons/grass6/dst/misc/m.dst.source/Makefile (rev 0)
+++ grass-addons/grass6/dst/misc/m.dst.source/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,11 @@
+MODULE_TOPDIR = ../..
+
+PGM = m.dst.source
+
+XMLLIB = `xml2-config --libs`
+LIBES = $(GISLIB) $(DATETIMELIB) $(XMLLIB)
+EXTRA_CFLAGS = `xml2-config --cflags` -I../../include
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
Added: grass-addons/grass6/dst/misc/m.dst.source/description.html
===================================================================
--- grass-addons/grass6/dst/misc/m.dst.source/description.html (rev 0)
+++ grass-addons/grass6/dst/misc/m.dst.source/description.html 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,112 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<TITLE>dst.source</TITLE>
+
+<body bgcolor="white">
+
+
+<h2>DESCRIPTION</h2>
+
+This program is used to define sources of evidence in a Dempster-Shafer knowledge
+base file. The knowledge base file is an XML format ASCII file which resides in its
+own 'DST' element inside the user's current mapset.
+Such a file is necessary to perform Dempster-Shafer Theory (DST) calculations using
+<EM><A HREF="dst.combine.html">dst.combine </A></EM>.
+If you do not know what DST is or why you would need this program, please refer to the
+<EM><A HREF="dst.combine.html">dst.combine </A></EM> command's manpage for an introduction.<p>
+Although the knowlegde base file can theoretically be edited with
+any ASCII editor, it is highly recommended to always use <em>dst.source</em> to make changes
+regarding sources of evidence. This ensures that the mathematical structure of the model layout
+will remain intact.<p>
+
+The <em>dst.source</em> command allows the user to define sources of evidence in a knowledge base file.
+This is the last step in preparing data for a DST analysis.
+To get an overview of the DST model structure and the defined sources of evidence at any time,
+use the <EM><A HREF="dst.view.html">dst.view </A></EM> command.
+Knowledge base files themselves can be listed, created, deleted and renamed using a special
+<A HREF="dst.list.html">set of commands</A>.<p></p>
+
+Since hypotheses can be defined and evidences attached to them using
+<EM><A HREF="dst.update.html">dst.update </A></EM>, it may seem unnecessary to
+define these relations again as 'sources of evidence'. However, the information
+structure created by <EM><A HREF="dst.update.html">dst.update </A></EM> is not
+necessarily unambiguous. There are no restrictions on the order in which evidences
+are attached and some hypotheses may be associated with more evidences than others.
+This means that it is not always clear which evidences have to be combined in one run
+of <EM><A HREF="dst.combine.html">dst.combine </A></EM> and therefore another
+step is necessary.
+Defining sources of evidence ensures that one input to <EM><A HREF="dst.combine.html">
+dst.combine </A></EM> will always consist of exactly one evidence for each hypothesis
+in the frame of reference and that BPA values relating to that hypothesis will not be
+accidentally combined with hypotheses from another source.<p></p>
+
+
+<h3>Parameters</h3>
+<dl>
+<dt><B>file=</B><EM>name</EM></dt>
+ <dd>Name of DST knowledge base file to modify. You can get a listing of DST
+ knowledge base files in your current mapset by invoking
+ <EM><A HREF="dst.list.html">dst.list </A></EM>. </dd>
+<dt><B>add=</B><EM>name</EM></dt>
+ <dd>Adds a source of evidence 'name' to the knowledge base. Naming conventions follow
+ the same rules as filenames.</dd>
+<dt><B>del=</B><EM>name</EM></dt>
+ <dd>Deletes the evidence source 'name' from the knowledge base file.
+ </dd>
+<dt><B>ren=</B><EM>name</EM></dt>
+ <dd>Renames evidence source 'name'. New name must be specified using the <em>new=[name]</em>
+ parameter (see below).
+ </dd>
+<dt><B>new=</B><EM>name</EM></dt>
+ <dd>Specifies a new name for renaming a source of evidence.
+ </dd>
+<dt><B>const=</B><EM>value</EM></dt>
+ <dd>Assigns constant evidence to a source of evidence.
+ The hypothesis (or set of hypotheses) to which this evidence relates must be
+ specified using the <em>hypothesis=[name]</em> parameter.
+ The target source must be specified using the <em>source=[name]</em> parameter.
+ </dd>
+<dt><B>rast=</B><EM>name</EM></dt>
+ <dd>Assigns raster map evidence to a source of evidence.</dd>
+<dt><B>vect=</B><EM>name</EM></dt>
+ <dd>Assigns vector map evidence to a source of evidence.</dd>
+<dt><B>clean=</B><EM>name</EM></dt>
+ <dd>Removes all assignments to a source of evidence from a hypothesis (specified using <em>hypothesis=[name]</em>).</dd>
+<dt><B>prune=</B><EM>name</EM></dt>
+ <dd>Removes assignments to a source of evidence from one or all hypotheses. The type(s) of
+ evidence (const,rast,vect) to un-assign can be specified using <em>type=[name]</em>.
+ </dd>
+<dt><B>source=</B><EM>name</EM></dt>
+ <dd>Specifies source of evidence to operate on. Case matters!
+ </dd>
+<dt><B>hypothesis=</B><EM>name</EM></dt>
+ <dd>Specifies hypothesis to operate on. Note that order matters when refering to
+ hypotheses sets: 'a,c' may exist, but 'c,a' not!
+ </dd>
+<dt><B>type=</B><EM>name</EM></dt>
+ <dd>Type of evidence to un-assign (use in conjunction with <em>prune=[hyp]</em>).
+ Possible options are <em>const,rast,vect,*</em>.
+ </dd>
+
+<h2>USAGE</h2>
+
+Refer to the section on 'Predictive Modelling' in the
+manpage of the <EM><A HREF="dst.combine.html">dst.combine </A></EM> command
+for an example of how to define sources of evidence using <em>dst.source</em>.
+
+
+<h3>Notes</h3>
+This program was developed as part of the GRASS 5 DST Predictive Modelling Toolkit.<br>
+The term 'knowledge base file' was first used in the manual of the
+<A HREF="www.clarklabs.org" target="_blank"> IDRISI GIS </A> software which also offers some DST functionality.<br>
+<h3>SEE ALSO</h3>
+<EM><A HREF="dst.combine.html">dst.combine</A></EM><br>
+<EM><A HREF="dst.list.html">dst.list, dst.create, dst.remove, dst.rename</A></EM><br>
+<EM><A HREF="dst.update.html">dst.update</A></EM><br>
+<EM><A HREF="dst.view.html">dst.view</A></EM><br>
+<h3>AUTHOR</h3>
+Benjamin Ducke,<br>
+University of Kiel, Germany<br>
+<i>Last changed: 2005/07/21</i>
+</body>
+</html>
Property changes on: grass-addons/grass6/dst/misc/m.dst.source/description.html
___________________________________________________________________
Added: svn:mime-type
+ text/html
Added: svn:keywords
+ Author Date Id
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/misc/m.dst.source/main.c
===================================================================
--- grass-addons/grass6/dst/misc/m.dst.source/main.c (rev 0)
+++ grass-addons/grass6/dst/misc/m.dst.source/main.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,979 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#include <grass/gis.h>
+
+#define MAX_GROUP_CHARS 32
+
+/* TODO:
+ - update number of groups after deletion!
+*/
+
+int N_SINGLETONS = 0; /* number of singletons in knowledge base */
+int N_HYPOTHESES = 0; /* number of hypotheses in knowledge base */
+int N_GROUPS = 0; /* number of groups in knowledge base */
+char *xmlfile; /* file name of knowledge base */
+xmlDocPtr doc;
+FILE *lp;
+
+
+/* returns the amount of memory needed to hold the argument string */
+/* to improve readability */
+long int to_alloc (xmlChar *string) {
+ return (sizeof (xmlChar) * (xmlStrlen (string) + 1 ) );
+}
+
+
+/* return number of singletons in a hypothesis subset */
+int get_no_singletons (xmlChar *set) {
+ xmlChar *tmp;
+ xmlChar *copy;
+ int i;
+
+ /* must copy the argument, because it is going to get crippled */
+ /* by strtok ... */
+ copy = (xmlChar*) G_malloc ((signed) (sizeof(xmlChar) * strlen (set) * 2));
+ strcpy (copy,set);
+
+ /* extract first singleton */
+ tmp = strtok (copy,",");
+ /* don't count the empty set */
+ if ( strcmp (copy,"NULL") == 0) {
+ return (0);
+ }
+ i = 1;
+ /* look for further singletons */
+ while ( (tmp = strtok (NULL,",")) != NULL ) {
+ i ++;
+ }
+
+ G_free (copy);
+
+ return (i);
+}
+
+/* returns 1, if name is rast,vect or const */
+/* 0 otherwise */
+int is_evidence (xmlChar *name) {
+ if ( name == NULL ) {
+ return (0);
+ }
+ if ( !strcmp (name,"const") ) {
+ return (1);
+ }
+ if ( !strcmp (name,"rast") ) {
+ return (1);
+ }
+ if ( !strcmp (name,"vect") ) {
+ return (1);
+ }
+ return (0);
+}
+
+void open_xml_file ( char* filename ) {
+
+ xmlNodePtr cur;
+
+ /* get a fully qualified, absolute path and filename for */
+ /* reading/writing the XML database file. */
+ /* What to do on a DOS system? Let's hope that libxml handles it!*/
+ xmlfile=G_strdup(filename );
+
+ /* parse the XML structure; check that we have a valid file */
+ doc = xmlParseFile (xmlfile);
+ if ( doc == NULL ) {
+ xmlFreeDoc(doc);
+ G_fatal_error ("Could not parse XML structure of knowledge base.\n");
+ }
+
+ cur = xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ xmlFreeDoc(doc);
+ G_fatal_error ("Knowledge base is an empty file.\n");
+ }
+
+ if (xmlStrcmp(cur->name, (const xmlChar *) "dst-kb")) {
+ xmlFreeDoc(doc);
+ G_fatal_error ("File is not a DST knowledge base.\n");
+ }
+
+ N_SINGLETONS = atoi (xmlGetProp(cur, "N_SINGLETONS"));
+ N_HYPOTHESES = atoi (xmlGetProp(cur, "N_HYPOTHESES"));
+ N_GROUPS = atoi (xmlGetProp(cur, "N_GROUPS"));
+}
+
+
+void add_group (char *name) {
+
+ xmlNodePtr cur;
+ xmlChar *tmp;
+
+ /* parse all group nodes */
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ while (cur != NULL) {
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "grp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) name, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ /* there already is a group with this name! */
+ G_fatal_error ("Group '%s' already exists in the knowledge base.\n",
+ (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+ }
+ }
+ cur = cur->next;
+ }
+
+ /* add new group to root of XML doc */
+ cur = xmlDocGetRootElement(doc);
+ xmlNewTextChild (cur, NULL, (xmlChar*) "grp", (xmlChar*) name);
+ /* increase number of stored groups by one */
+ N_GROUPS ++;
+ tmp = G_malloc (sizeof (xmlChar) * 100);
+ sprintf (tmp,"%i",N_GROUPS);
+ xmlSetProp(cur,(xmlChar*) "N_GROUPS", (xmlChar*) tmp);
+ G_free (tmp);
+
+ /* save changes to XML file */
+ xmlSaveFormatFile (xmlfile, doc, 1);
+
+ xmlFree (cur);
+}
+
+
+void del_group ( char *name ) {
+ int i = 0;
+ xmlNodePtr cur;
+ xmlNodePtr prev;
+ xmlNodePtr hypNode;
+ xmlNodePtr evidenceNode;
+
+ prev = NULL;
+ hypNode = NULL;
+ evidenceNode = NULL;
+
+ /* PASS 1: delete the group itself */
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ while ((cur != NULL) && ( i ==0 ) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "grp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) name, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ i = 1; /* this exits the while loop */
+
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+
+ if ( i != 1 ) {
+ G_fatal_error ("Group '%s' does not exist in the knowledge base.\n",name);
+ }
+
+ xmlUnlinkNode (prev);
+ xmlFreeNode (prev);
+
+
+ /* PASS 2: delete all references to the group */
+ i = 0;
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ while ( (cur != NULL) ) {
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ hypNode = cur->xmlChildrenNode;
+ /* check all evidence entries */
+ while ( hypNode != NULL ) {
+ if ( is_evidence ( (xmlChar*) hypNode->name) ) {
+ /* check all evidence childs */
+ evidenceNode = hypNode->xmlChildrenNode;
+ while ( evidenceNode != NULL ) {
+ /* check all assigns */
+ if ( !xmlStrcmp (evidenceNode->name, "assign") ) {
+ /* check if assignment is to current group */
+ if ( !xmlStrcmp ( (xmlChar*) name, (const xmlChar *)
+ xmlNodeListGetString(doc, evidenceNode->xmlChildrenNode, 1)) ) {
+ i = 1;
+ }
+ }
+ prev = evidenceNode;
+ evidenceNode = evidenceNode->next;
+ if ( i == 1 ) { /* delayed deletion */
+ xmlUnlinkNode (prev);
+ xmlFreeNode (prev);
+ i = 0;
+ }
+ }
+ }
+ hypNode = hypNode->next;
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+
+
+
+ /* save changes to XML file */
+ xmlSaveFormatFile (xmlfile, doc, 1);
+
+ xmlFree (cur);
+}
+
+
+void ren_group ( char *name, char *newname ) {
+
+ int i = 0;
+ xmlNodePtr cur;
+ xmlNodePtr prev;
+ xmlNodePtr hypNode;
+ xmlNodePtr evidenceNode;
+
+ prev = NULL;
+ hypNode = NULL;
+ evidenceNode = NULL;
+
+ /* PASS 1: rename the group itself */
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ while ((cur != NULL) && ( i ==0 ) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "grp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) name, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ i = 1; /* this exits the while loop */
+
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+
+ if ( i != 1 ) {
+ G_fatal_error ("Group '%s' does not exist in the knowledge base.\n",name);
+ }
+
+ xmlNodeSetContent(prev->xmlChildrenNode, newname);
+
+ /* PASS 2: rename all references to the group */
+ i = 0;
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ while ( (cur != NULL) ) {
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ hypNode = cur->xmlChildrenNode;
+ /* check all evidence entries */
+ while ( hypNode != NULL ) {
+ if ( is_evidence ( (xmlChar*) hypNode->name) ) {
+ /* check all evidence childs */
+ evidenceNode = hypNode->xmlChildrenNode;
+ while ( evidenceNode != NULL ) {
+ /* check all assigns */
+ if ( !xmlStrcmp (evidenceNode->name, "assign") ) {
+ /* check if assignment is to current group */
+ if ( !xmlStrcmp ( (xmlChar*) name, (const xmlChar *)
+ xmlNodeListGetString(doc, evidenceNode->xmlChildrenNode, 1)) ) {
+ i = 1;
+ }
+ }
+ prev = evidenceNode;
+ evidenceNode = evidenceNode->next;
+ if ( i == 1 ) { /* delayed renaming */
+ xmlNodeSetContent(prev->xmlChildrenNode, newname);
+ i = 0;
+ }
+ }
+ }
+ hypNode = hypNode->next;
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+
+
+ /* save changes to XML file */
+ xmlSaveFormatFile (xmlfile, doc, 1);
+
+ xmlFree (cur);
+}
+
+/* assign CONST evidence *evidence from *hyp to *group */
+void assign_const ( char *evidence, char *hyp, char *group ) {
+
+ int i = 0;
+ xmlNodePtr cur;
+ xmlNodePtr prev;
+ xmlNodePtr parent;
+ xmlNodePtr hypParent;
+ xmlNodePtr cur2;
+ xmlNodePtr delete;
+
+ prev = NULL;
+ cur2 = NULL;
+ delete = NULL;
+
+ /* 1. check, if the group exists */
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ while ((cur != NULL) && ( i ==0 ) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "grp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) group, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ i = 1; /* this exits the while loop */
+
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if ( i != 1 ) {
+ G_fatal_error ("Group '%s' does not exist in the knowledge base.\n",group);
+ }
+
+ /* 2. check, if the hypothesis exists */
+ i = 0;
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ while ((cur != NULL) && ( i ==0 ) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) hyp, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ i = 1; /* this exits the while loop */
+
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if ( i != 1 ) {
+ G_fatal_error ("Hypothesis '%s' does not exist in the knowledge base.\n",hyp);
+ }
+
+ /* 3. check, if the evidence exists in that hypothesis */
+ i = 0;
+ hypParent = prev;
+ cur = prev->xmlChildrenNode;
+ while ((cur != NULL) && ( i ==0 ) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "const"))) {
+ if ( (!xmlStrcmp((const xmlChar *) evidence, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ i = 1; /* this exits the while loop */
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if ( i != 1 ) {
+ G_fatal_error ("Hypothesis has no CONST evidence with value '%s'.\n",evidence);
+ }
+ parent = prev;
+ /* 4. check, if CONST evidence in this hyp has already been assigned to the group */
+ /* if so, delete all old references. */
+ i = 0;
+ cur = hypParent->xmlChildrenNode;
+ while ( (cur != NULL) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "const"))) {
+ cur2 = cur->xmlChildrenNode;
+ while ( cur2 != NULL ) {
+ if ( (!xmlStrcmp((const xmlChar *) "assign", (const xmlChar *) cur2->name ))) {
+ if ((!xmlStrcmp((const xmlChar *) group, (const xmlChar *)
+ xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1) ))) {
+ /* found an assignment for this group! */
+ /* mark for delayed deletion */
+ i = 1;
+ }
+ }
+ delete = cur2;
+ cur2 = cur2->next;
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ if ( i == 1 ) {
+ G_warning ("Removing old CONST value of '%s' for hyp. '%s', group '%s'.\n",evidence,hyp,group);
+ /* remove old assignment */
+ xmlUnlinkNode ( delete );
+ xmlFreeNode ( delete );
+ i = 0;
+ }
+ }
+
+ /* 5. add a new child to the evidence node that refers to the group */
+ cur = xmlNewTextChild (parent, NULL, (xmlChar*) "assign", (xmlChar*) group);
+
+ /* save changes to XML file */
+ xmlSaveFormatFile (xmlfile, doc, 1);
+
+ xmlFree (cur);
+ xmlFree (parent);
+ xmlFree (hypParent);
+}
+
+void assign_rast ( char *evidence, char *hyp, char *group ) {
+
+ int i = 0;
+ xmlNodePtr cur;
+ xmlNodePtr prev;
+ xmlNodePtr parent;
+ xmlNodePtr hypParent;
+ xmlNodePtr cur2;
+ xmlNodePtr delete;
+
+ prev = NULL;
+ cur2 = NULL;
+ delete = NULL;
+
+ /* 1. check, if the group exists */
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ while ((cur != NULL) && ( i ==0 ) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "grp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) group, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ i = 1; /* this exits the while loop */
+
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if ( i != 1 ) {
+ G_fatal_error ("Group '%s' does not exist in the knowledge base.\n",group);
+ }
+
+ /* 2. check, if the hypothesis exists */
+ i = 0;
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ while ((cur != NULL) && ( i ==0 ) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) hyp, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ i = 1; /* this exits the while loop */
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if ( i != 1 ) {
+ G_fatal_error ("Hypothesis '%s' does not exist in the knowledge base.\n",hyp);
+ }
+
+ /* 3. check, if the evidence exists in that hypothesis */
+ i = 0;
+ hypParent = prev;
+ cur = prev->xmlChildrenNode;
+ while ((cur != NULL) && ( i ==0 ) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "rast"))) {
+ if ( (!xmlStrcmp((const xmlChar *) evidence, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ i = 1; /* this exits the while loop */
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if ( i != 1 ) {
+ G_fatal_error ("Hypothesis has no RAST evidence '%s'.\n",evidence);
+ }
+ parent = prev;
+ /* 4. check, if RAST evidence in this hyp has already been assigned to the group */
+ /* if so, delete all old references. */
+ i = 0;
+ cur = hypParent->xmlChildrenNode;
+ while ( (cur != NULL) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "rast"))) {
+ cur2 = cur->xmlChildrenNode;
+ while ( cur2 != NULL ) {
+ if ( (!xmlStrcmp((const xmlChar *) "assign", (const xmlChar *) cur2->name ))) {
+ if ((!xmlStrcmp((const xmlChar *) group, (const xmlChar *)
+ xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1) ))) {
+ /* found an assignment for this group! */
+ /* mark for delayed deletion */
+ i = 1;
+ }
+ }
+ delete = cur2;
+ cur2 = cur2->next;
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ if ( i == 1 ) {
+ G_warning ("Removing RAST link '%s' for hyp. '%s', group '%s'.\n",evidence,hyp,group);
+ /* remove old assignment */
+ xmlUnlinkNode ( delete );
+ xmlFreeNode ( delete );
+ i = 0;
+ }
+ }
+
+ /* 5. add a new child to the evidence node that refers to the group */
+ cur = xmlNewTextChild (parent, NULL, (xmlChar*) "assign", (xmlChar*) group);
+
+ /* save changes to XML file */
+ xmlSaveFormatFile (xmlfile, doc, 1);
+
+ xmlFree (cur);
+ xmlFree (parent);
+ xmlFree (hypParent);
+}
+
+void assign_vect ( char *evidence, char *hyp, char *group ) {
+
+ int i = 0;
+ xmlNodePtr cur;
+ xmlNodePtr prev;
+ xmlNodePtr parent;
+ xmlNodePtr hypParent;
+ xmlNodePtr cur2;
+ xmlNodePtr delete;
+
+ prev = NULL;
+ cur2 = NULL;
+ delete = NULL;
+
+ /* 1. check, if the group exists */
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ while ((cur != NULL) && ( i ==0 ) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "grp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) group, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ i = 1; /* this exits the while loop */
+
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if ( i != 1 ) {
+ G_fatal_error ("Group '%s' does not exist in the knowledge base.\n",group);
+ }
+
+ /* 2. check, if the hypothesis exists */
+ i = 0;
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ while ((cur != NULL) && ( i ==0 ) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) hyp, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ i = 1; /* this exits the while loop */
+
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if ( i != 1 ) {
+ G_fatal_error ("Hypothesis '%s' does not exist in the knowledge base.\n",hyp);
+ }
+
+ /* 3. check, if the evidence exists in that hypothesis */
+ i = 0;
+ hypParent = prev;
+ cur = prev->xmlChildrenNode;
+ while ((cur != NULL) && ( i ==0 ) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "vect"))) {
+ if ( (!xmlStrcmp((const xmlChar *) evidence, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ i = 1; /* this exits the while loop */
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if ( i != 1 ) {
+ G_fatal_error ("Hypothesis has no VECT evidence '%s'.\n",evidence);
+ }
+ parent = prev;
+ /* 4. check, if VECT evidence in this hyp has already been assigned to the group */
+ /* if so, delete all old references. */
+ i = 0;
+ cur = hypParent->xmlChildrenNode;
+ while ( (cur != NULL) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "vect"))) {
+ cur2 = cur->xmlChildrenNode;
+ while ( cur2 != NULL ) {
+ if ( (!xmlStrcmp((const xmlChar *) "assign", (const xmlChar *) cur2->name ))) {
+ if ((!xmlStrcmp((const xmlChar *) group, (const xmlChar *)
+ xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1) ))) {
+ /* found an assignment for this group! */
+ /* mark for delayed deletion */
+ i = 1;
+ }
+ }
+ delete = cur2;
+ cur2 = cur2->next;
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ if ( i == 1 ) {
+ G_warning ("Removing VECT link '%s' for hyp. '%s', group '%s'.\n",evidence,hyp,group);
+ /* remove old assignment */
+ xmlUnlinkNode ( delete );
+ xmlFreeNode ( delete );
+ i = 0;
+ }
+ }
+
+ /* 5. add a new child to the evidence node that refers to the group */
+ cur = xmlNewTextChild (parent, NULL, (xmlChar*) "assign", (xmlChar*) group);
+
+ /* save changes to XML file */
+ xmlSaveFormatFile (xmlfile, doc, 1);
+
+ xmlFree (cur);
+ xmlFree (parent);
+ xmlFree (hypParent);
+}
+
+
+void prune ( char* group, char* hyp, char* type ) {
+
+ xmlNodePtr cur;
+ xmlNodePtr prev;
+ xmlNodePtr hypNode;
+ xmlNodePtr typeNode;
+ int i = 0;
+
+ prev = NULL;
+ hypNode = NULL;
+ typeNode = NULL;
+
+ /* 1. check, if the group exists */
+ if ( strcmp ("*",group) != 0 ) {
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ while ((cur != NULL) && ( i ==0 ) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "grp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) group, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ i = 1; /* this exits the while loop */
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if ( i != 1 ) {
+ G_fatal_error ("Group '%s' does not exist in the knowledge base.\n",group);
+ }
+ }
+
+ if ( strcmp ("*",hyp) != 0 ) {
+ /* 2. check, if the hypothesis exists */
+ i = 0;
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ while ((cur != NULL) && ( i ==0 ) ){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) hyp, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ i = 1; /* this exits the while loop */
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if ( i != 1 ) {
+ G_fatal_error ("Hypothesis '%s' does not exist in the knowledge base.\n",hyp);
+ }
+ }
+
+ /* walk thru whole XML tree and delete all references if necessary */
+ i = 0;
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ while ( (cur != NULL) ) {
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ hypNode = cur->xmlChildrenNode;
+ fprintf (lp,"HYP\n");
+ /* check all evidence entries */
+ while ( hypNode != NULL ) {
+ if ( is_evidence ( (xmlChar*) hypNode->name) ) {
+ fprintf (lp,"\tEVIDENCE\n");
+ /* check all evidence childs */
+ typeNode = hypNode->xmlChildrenNode;
+ while ( typeNode != NULL ) {
+ /* check all assigns */
+ if ( !xmlStrcmp (typeNode->name, "assign") ) {
+ fprintf (lp,"\t\tEVIDENCE\n");
+ i = 1;
+ }
+ prev = typeNode;
+ typeNode = typeNode->next;
+ if ( i == 1 ) { /* delayed deletion */
+ fprintf (lp,"\t\tCHECK:\n");
+ /* check if assignment is to current group */
+ fprintf (lp,"\t\t\t1. GROUP (%s) ?\n",xmlNodeListGetString(doc, prev->xmlChildrenNode, 1));
+ if ( (!xmlStrcmp ( (xmlChar*) group, (const xmlChar *)
+ xmlNodeListGetString(doc, prev->xmlChildrenNode, 1))) ||
+ (strcmp (group,"*") ) ) {
+ fprintf (lp,"\t\t\t1. GROUP=YES\n");
+ fprintf (lp,"\t\t\t2. TYPE (%s) ?\n",hypNode->name);
+ if ( (!strcmp (hypNode->name,type)) || (!strcmp (type,"*")) ) {
+ fprintf (lp,"\t\t\t2. TYPE = YES\n");
+ fprintf (lp,"\t\t\t3. HYP (%s) ?\n",xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+ if ( (!xmlStrcmp ( (xmlChar*) hyp, (const xmlChar *)
+ xmlNodeListGetString(doc, cur->xmlChildrenNode, 1))) ||
+ (strcmp (group,"*") ) ) {
+ fprintf (lp,"\t\t\t3. HYP = YES\n");
+ fprintf (lp,"\t\t\t->PURGE\n");
+ }
+ }
+ }
+ i = 0;
+ }
+ }
+ }
+ hypNode = hypNode->next;
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+
+
+ /* save changes to XML file */
+ xmlSaveFormatFile (xmlfile, doc, 1);
+
+ xmlFree (cur);
+}
+
+int
+main (int argc, char *argv[])
+{
+ FILE *kb;
+
+ struct GModule *module;
+ struct
+ {
+ struct Option *file;
+ struct Option *add;
+ struct Option *del;
+ struct Option *ren;
+ struct Option *newname;
+ struct Option *cnst;
+ struct Option *rast;
+ struct Option *vect;
+ struct Option *null; /* delete all references to a group from a hyp */
+ struct Option *prune; /* group, hyp, type */
+ struct Option *group;
+ struct Option *hyp;
+ struct Option *type;
+ }
+ parm;
+
+ /* setup some basic GIS stuff */
+ G_gisinit (argv[0]);
+ module = G_define_module ();
+ module->description = "Manages sources of evidence in a DST knowledge base file.";
+
+ /* do not pause after a warning message was displayed */
+ G_sleep_on_error (0);
+
+ /* Parameters */
+ parm.file = G_define_option ();
+ parm.file->key = "file";
+ parm.file->type = TYPE_STRING;
+ parm.file->required = YES;
+ parm.file->description = "Name of the knowledge base file";
+
+ parm.add = G_define_option ();
+ parm.add->key = "add";
+ parm.add->type = TYPE_STRING;
+ parm.add->required = NO;
+ parm.add->description = "Source of evidence to add to the knowledge base";
+
+ parm.del = G_define_option ();
+ parm.del->key = "delete";
+ parm.del->type = TYPE_STRING;
+ parm.del->required = NO;
+ parm.del->description = "Source of evidence to delete from the knowledge base";
+
+ parm.ren = G_define_option ();
+ parm.ren->key = "rename";
+ parm.ren->type = TYPE_STRING;
+ parm.ren->required = NO;
+ parm.ren->description = "Source of evidence to rename in the knowledge base";
+
+ parm.newname = G_define_option ();
+ parm.newname->key = "new";
+ parm.newname->type = TYPE_STRING;
+ parm.newname->required = NO;
+ parm.newname->description = "New name for source of evidence (use with 'ren=')";
+
+ parm.cnst = G_define_option ();
+ parm.cnst->key = "const";
+ parm.cnst->type = TYPE_DOUBLE;
+ parm.cnst->required = NO;
+ parm.cnst->description = "Attach constant value evidence to a source of evidence";
+
+ parm.rast = G_define_standard_option (G_OPT_R_INPUT);
+ parm.rast->key = "rast";
+ parm.rast->type = TYPE_STRING;
+ parm.rast->required = NO;
+ parm.rast->description = "Attach a GRASS raster map to a source of evidence";
+ parm.rast->gisprompt = "old,fcell,raster";
+
+ parm.vect = G_define_standard_option (G_OPT_V_INPUT);
+ parm.vect->key = "vect";
+ parm.vect->type = TYPE_STRING;
+ parm.vect->required = NO;
+ parm.vect->description = "Attach a GRASS vector map to a source of evidence";
+
+ parm.null = G_define_option ();
+ parm.null->key = "clean";
+ parm.null->type = TYPE_STRING;
+ parm.null->required = NO;
+ parm.null->description = "Remove all sources of evidence from a hypothesis";
+
+ parm.prune = G_define_option ();
+ parm.prune->key = "prune";
+ parm.prune->type = TYPE_STRING;
+ parm.prune->required = NO;
+ parm.prune->description = "Remove multiple sources of evidence from one or more hypotheses";
+
+ parm.group = G_define_option ();
+ parm.group->key = "source";
+ parm.group->type = TYPE_STRING;
+ parm.group->required = NO;
+ parm.group->description = "Source of evidence to operate on";
+
+ parm.hyp = G_define_option ();
+ parm.hyp->key = "hypothesis";
+ parm.hyp->type = TYPE_STRING;
+ parm.hyp->required = NO;
+ parm.hyp->description = "Hypothesis to operate on";
+
+ parm.type = G_define_option ();
+ parm.type->key = "type";
+ parm.type->type = TYPE_STRING;
+ parm.type->required = NO;
+ parm.type->options = "const,rast,vect,*";
+ parm.type->description = "Type of evidence to remove (use with 'prune=')";
+
+ G_disable_interactive ();
+
+ /* parse command line */
+ if (G_parser (argc, argv))
+ {
+ exit (-1);
+ }
+
+ /* check if we have read/write access to knowledge base file */
+ errno = 0;
+ kb = fopen (parm.file->answer,"r+");
+ if ( kb == NULL ) {
+ G_fatal_error ("Cannot open knowledge base file for reading and writing.\nReason: %s.", strerror (errno));
+
+ } else {
+ fclose(kb);
+ }
+
+ /* this is necessary to produce nicely formatted output */
+ xmlKeepBlanksDefault (0);
+ open_xml_file ( parm.file->answer );
+
+ /* send output to terminal */
+ lp = stderr;
+
+ /* get action from command line */
+ /* add a group */
+ if ( parm.add->answer != NULL) {
+ /* the NULL has a special meaning! */
+ if ( strcmp (parm.add->answer,"NULL") == 0 ) {
+ G_fatal_error ("'NULL' cannot be used as group name.\n");
+ }
+ if ( is_evidence (parm.add->answer) ) {
+ G_fatal_error ("The keyword '%s' cannot be used as a group name.\n",parm.add->answer);
+ }
+ /* hypothesis names must conform to same restrictions as filenames */
+ if ( G_legal_filename (parm.add->answer) != 1 ) {
+ G_fatal_error ("Group name invalid (contains special chars, whitespace or other).\n");
+ }
+ /* hypothesis names cannot have more than 32 chars */
+ if ( strlen (parm.add->answer) > (MAX_GROUP_CHARS) ) {
+ G_fatal_error ("Group names cannot be longer than %i characters.\n",
+ MAX_GROUP_CHARS);
+ }
+ /* cannot use TMP as hypothesis name */
+ if ( !strcmp (parm.add->answer,"TMP") ) {
+ G_fatal_error ("Group name 'TMP' is a reserved name. Please choose another one.\n");
+ }
+ add_group (parm.add->answer);
+ }
+ /* delete a group */
+ if ( parm.del->answer != NULL ) {
+ del_group (parm.del->answer);
+ }
+ /* rename a group */
+ if ( parm.ren->answer != NULL) {
+ if ( parm.newname->answer == NULL ) {
+ G_fatal_error ("Please provide a new group name using 'newname='.\n");
+ }
+ /* the NULL has a special meaning! */
+ if ( strcmp (parm.newname->answer,"NULL") == 0 ) {
+ G_fatal_error ("'NULL' cannot be used as group name.\n");
+ }
+ if ( is_evidence (parm.newname->answer) ) {
+ G_fatal_error ("The keyword '%s' cannot be used as a group name.\n",parm.add->answer);
+ }
+ /* hypothesis names must conform to same restrictions as filenames */
+ if ( G_legal_filename (parm.newname->answer) != 1 ) {
+ G_fatal_error ("Group name invalid (contains special chars, whitespace or other).\n");
+ }
+ /* hypothesis names cannot have more than 32 chars */
+ if ( strlen (parm.newname->answer) > (MAX_GROUP_CHARS) ) {
+ G_fatal_error ("Group names cannot be longer than %i characters.\n",
+ MAX_GROUP_CHARS);
+ }
+ /* cannot use TMP as hypothesis name */
+ if ( !strcmp (parm.newname->answer,"TMP") ) {
+ G_fatal_error ("Group name 'TMP' is a reserved name. Please choose another one.\n");
+ }
+ ren_group (parm.ren->answer, parm.newname->answer);
+ }
+ /* define CONST evidence for group */
+ if ( parm.cnst->answer != NULL ) {
+ if ( parm.group->answer == NULL ) {
+ G_fatal_error ("Please provide a group name using 'group='.\n");
+ }
+ if ( parm.hyp->answer == NULL ) {
+ G_fatal_error ("Please provide a hypothesis name using 'hyp='.\n");
+ }
+ assign_const ( parm.cnst->answer, parm.hyp->answer, parm.group->answer);
+ }
+
+ /* define RAST evidence for group */
+ if ( parm.rast->answer != NULL ) {
+ if ( parm.group->answer == NULL ) {
+ G_fatal_error ("Please provide a group name using 'group='.\n");
+ }
+ if ( parm.hyp->answer == NULL ) {
+ G_fatal_error ("Please provide a hypothesis name using 'hyp='.\n");
+ }
+ assign_rast ( parm.rast->answer, parm.hyp->answer, parm.group->answer);
+ }
+
+ /* define VECT evidence for group */
+ if ( parm.vect->answer != NULL ) {
+ if ( parm.group->answer == NULL ) {
+ G_fatal_error ("Please provide a group name using 'group='.\n");
+ }
+ if ( parm.hyp->answer == NULL ) {
+ G_fatal_error ("Please provide a hypothesis name 'hyp='.\n");
+ }
+ assign_vect ( parm.vect->answer, parm.hyp->answer, parm.group->answer );
+ }
+
+ /* prune group assignment(s) */
+ if ( parm.prune->answer != NULL ) {
+ if ( parm.hyp->answer == NULL ) {
+ G_fatal_error ("Please provide a hypothesis name (or '*' for all hypotheses) using 'hyp='.\n");
+ }
+ if ( parm.type->answer == NULL ) {
+ G_fatal_error ("Please provide a type name (or '*' for all types) using 'type='.\n");
+ }
+ prune ( parm.prune->answer, parm.hyp->answer, parm.type->answer);
+ }
+
+ xmlFree(doc);
+
+ G_free (xmlfile);
+
+ exit (EXIT_SUCCESS);
+}
Property changes on: grass-addons/grass6/dst/misc/m.dst.source/main.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/misc/m.dst.update/Makefile
===================================================================
--- grass-addons/grass6/dst/misc/m.dst.update/Makefile (rev 0)
+++ grass-addons/grass6/dst/misc/m.dst.update/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,11 @@
+MODULE_TOPDIR = ../..
+
+PGM = m.dst.update
+
+XMLLIB = `xml2-config --libs`
+LIBES = $(GISLIB) $(DATETIMELIB) $(XMLLIB)
+EXTRA_CFLAGS = `xml2-config --cflags` -I../../include
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
Added: grass-addons/grass6/dst/misc/m.dst.update/description.html
===================================================================
--- grass-addons/grass6/dst/misc/m.dst.update/description.html (rev 0)
+++ grass-addons/grass6/dst/misc/m.dst.update/description.html 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,163 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<TITLE>dst.update</TITLE>
+
+<body bgcolor="white">
+
+
+<h2>DESCRIPTION</h2>
+
+This program is used to manage user-supplied hypotheses and evidences in a Dempster-Shafer knowledge
+base file. The knowledge base file is an XML format ASCII file which resides in its own 'DST' element
+inside the user's current mapset.
+Such a file is necessary to perform Dempster-Shafer Theory (DST) calculations using
+<EM><A HREF="dst.combine.html">dst.combine </A></EM>.
+Although the knowledge base file can theoretically be edited with
+any ASCII editor, it is highly recommended to always use <em>dst.update</em> to make any changes
+to it. This ensures that the mathematical structure of the model layout will always remain intact.<p>
+If you do not know what DST is or why you would need this program, please refer to the
+<EM><A HREF="dst.combine.html">dst.combine </A></EM> command's manpage for an introduction.<p>
+The <em>dst.update</em> command allows the user to register hypotheses in a knowledge base file
+and attach evidences which support these hypotheses.
+To get an overview of the DST model structure at any time,
+use the <EM><A HREF="dst.view.html">dst.view </A></EM> command.
+Knowledge base files themselves can be listed, created, deleted and renamed using a specialised
+<A HREF="dst.list.html">set of commands</A>.
+
+
+<h3>Registering Hypotheses</h3>
+
+As described in the <EM><A HREF="dst.combine.html">dst.combine </A></EM> command's manpage,
+the user-suppplied hypotheses (type 'USER') form the backbone of any DST analysis. The Frame of Reference (FOD)
+is the set of hypotheses that cover all possible outcomes of the analysis. In the DST, this also
+includes two types of hypotheses, which the user does not have to supply.
+<ul>
+<li>The NULL hypotheses, which always exists.</li>
+<li>Sets of all possible combinations of user-supplied singleton hypotheses, which exist if more than one
+hypothesis is supplied.</li>
+</ul>
+
+It is vital that the FOD is always complete and that the hypotheses are stored in the correct
+hierachical order. E.g., if three hypotheses {a},{b} and {c} were supplied, one after another,
+the correct and complete FOD would look like:
+<pre>
+{NULL}
+{a}
+{b}
+{a,b}
+{c}
+{a,c}
+{b,c}
+{a,b,c}
+</pre>
+The order in which {a},{b} and {c} are given has no influence on the correctness of the DST
+calculations. Nevertheless, keeping the correct structure intact can be challenging if the
+FOD is subject to changes. With <em>dst.update</em>, the user can add, rename and remove
+hypotheses in the FOD, without having to worry about its structure.
+In fact, the user only adds, renames are removes <em>singleton hypotheses</em> (except {NULL})
+, sets are always managed automatically and stored as type 'AUTO' in the knowledge base file.<p></p>
+According to the laws of combinatorics, the number of hypotheses sets in the FOD grows rapidly
+if more hypotheses are supplied by the user. Currently, up two 12 user-supplied hypotheses
+are supported, but it seems unlikely that DST calculations with more than 4-6 user hypotheses
+will finish within reasonable time, as processing time also grows exponentially.<p>
+You can manage user-supplied hypotheses by using the <em>add=[hyp]</em>, <em>del=[hyp]</em>,
+<em>ren=[hyp]</em> (plus <em>new=[hyp]</em>) parameters.
+All other hypotheses will automatically be updated in the correct way. Note that names of
+hypotheses, like filenames, must not contain spaces or special characters. They will also
+be treated case-sensitive so 'HYP' is a different hypothesis than 'Hyp'.
+
+<h3>Attaching Evidences</h3>
+
+Once all hypotheses have been specified (it is vital for correct results that no possible
+hypothesis be left out!), it is up to the user to specify which evidences support a given
+hypothesis (or set of hypotheses).
+Any evidence must be the result of a correct BPA calculation (see
+<EM><A HREF="r.dst.bpa.html">r.dst.bpa </A></EM>for more details on this).<p></p>
+Different GRASS map formats can be attached using the <em>const=[name]</em>, <em>rast=[name}</em>,
+<em>vect=[name]</em> and <em>site=[name]</em> parameters.
+<em>However</em>, currently only GRASS raster maps or constant values can be used to
+supply evidence. Handling of other vector evidence is not yet implemented in the DST combination
+routines themselves.
+Thus, only evidence attached using the <em>rast=[name]</em> parameter will produce output
+if you call the
+<EM><A HREF="dst.combine.html">dst.combine </A></EM> command. Evidence of type 'const'
+consists of a single floating point number. It can be useful for testing purposes and to
+get a feeling for what the DST functions do with your data.<p></p>
+If you need to remove erraneous or outdated evidence from a knowledge base file, you can use
+the <em>clean=[hypothesis]</em> and <em>prune=[evidence]</em> parameters (see description
+of parameters below).<p></p>
+If all hypotheses and evidences are present in the data base, they have to be grouped
+to define sources of evidence. This can be done using the
+<EM><A HREF="dst.source.html">dst.source </A></EM> command.
+
+<h3>Parameters</h3>
+<dl>
+<dt><B>file=</B><EM>name</EM></dt>
+ <dd>Name of DST knowledge base file to modify. You can get a listing of DST
+ knowledge base files in your current mapset by using
+ <EM><A HREF="dst.list.html">dst.list </A></EM>. </dd>
+<dt><B>add=</B><EM>name</EM></dt>
+ <dd>Adds a hypothesis 'name' to the knowledge base. Naming conventions follow
+ the same rules as filenames.</dd>
+<dt><B>del=</B><EM>name</EM></dt>
+ <dd>Deletes hypothesis 'name' (and all references in hypotheses sets) from the
+ knowledge base file.
+ </dd>
+<dt><B>ren=</B><EM>name</EM></dt>
+ <dd>Renames hypothesis 'name' (and all references in hypotheses sets) from the
+ knowledge base file. New name must be specified using the <em>new=[name]</em>
+ parameter (see below).
+ </dd>
+<dt><B>new=</B><EM>name</EM></dt>
+ <dd>Specifies a new name for renaming a hypothesis.
+ </dd>
+<dt><B>const=</B><EM>value</EM></dt>
+ <dd>Attaches a constant value as evidence to a hypothesis. As with all evidences,
+ the target hypothesis must be specified using the <em>hypothesis=[name]</em>
+ parameter.
+ </dd>
+<dt><B>rast=</B><EM>name</EM></dt>
+ <dd>Attaches a GRASS raster map as evidence to a hypothesis.</dd>
+<dt><B>vect=</B><EM>name</EM></dt>
+ <dd>Attaches a GRASS vector map as evidence to a hypothesis (useless for now).</dd>
+<dt><B>clean=</B><EM>name</EM></dt>
+ <dd>Removes all attached evidence from a hypothesis (specified using <em>hypothesis=[name]</em>).</dd>
+<dt><B>prune=</B><EM>name</EM></dt>
+ <dd>Removes all references to an evidence from one or all hypotheses. The type(s) of
+ evidence to detach can be specified using <em>type=[name]</em>.
+ </dd>
+<dt><B>hypothesis=</B><EM>name</EM></dt>
+ <dd>Specifies hypothesis to operate on. Note that order matters when refering to
+ hypotheses sets: 'a,c' may exist, but 'c,a' not!
+ </dd>
+<dt><B>type=</B><EM>name</EM></dt>
+ <dd>Type of evidence to detach (use in conjunction with <em>prune=[hyp]</em>).
+ Possible options are <em>const,rast,vect,*</em>.
+ </dd>
+<dt><B>precision=</B><EM>value</EM></dt>
+ <dd>Number of decimal places for storing evidence of type <em>const</em>. The default is '2'.
+ </dd>
+
+<h2>USAGE</h2>
+
+Refer to the section on 'Predictive Modelling' in the
+manpage of the <EM><A HREF="dst.combine.html">dst.combine </A></EM> command
+for an example of how to register hypotheses and evidences using <em>dst.update</em>.
+
+
+<h3>Notes</h3>
+This program was developed as part of the GRASS 5 DST Predictive Modelling Toolkit.<br>
+The term 'knowledge base file' was first used in the manual of the
+<A HREF="www.clarklabs.org" target="_blank"> IDRISI GIS </A> software which also offers some DST functionality.<br>
+<h3>SEE ALSO</h3>
+<EM><A HREF="dst.combine.html">dst.combine</A></EM><br>
+<EM><A HREF="dst.list.html">dst.list, dst.create, dst.remove, dst.rename</A></EM><br>
+<EM><A HREF="dst.source.html">dst.source</A></EM><br>
+<EM><A HREF="dst.view.html">dst.view</A></EM><br>
+<EM><A HREF="r.dst.bpa.html">r.dst.bpa</A></EM><br>
+<h3>AUTHOR</h3>
+Benjamin Ducke,<br>
+University of Kiel, Germany<br>
+<i>Last changed: 2004/07/21</i>
+</body>
+</html>
Property changes on: grass-addons/grass6/dst/misc/m.dst.update/description.html
___________________________________________________________________
Added: svn:mime-type
+ text/html
Added: svn:keywords
+ Author Date Id
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/misc/m.dst.update/main.c
===================================================================
--- grass-addons/grass6/dst/misc/m.dst.update/main.c (rev 0)
+++ grass-addons/grass6/dst/misc/m.dst.update/main.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,1417 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <errno.h>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/globals.h>
+
+#include <grass/gis.h>
+
+#define MAX_HYPOTHESES 12 /* hard-coded limit for the number of hypotheses
+ anything more than this will overflow the
+ LONG variable needed to caluclate combinatorics
+ (facultary function) */
+
+#define MAX_HYP_CHARS 32 /* hard-coded limit for hypothesis name strings */
+#define TMP_SIZE 4096
+
+/* TODO:
+
+ - interface redesign
+ - the interface needs to be redesigned, because it must be possible to achieve the following:
+ 1. Allow the user to attach external files as evidence
+ 2. Force the user to assign every evidence to a source of evidence when attaching
+ 3. Clean up the current mess of options, especially the many cleaning tools
+ - it must not be allowed to perform any operation on the "NULL" (not case-sensitive) hypothesis!
+ -> currently, it's allowed to attach evidence to it!
+ - we must allow for external files to be attached/detached
+ - it would be better to have simple names as evidence and the data source names as an XML property
+ (long file names!)
+ Evidence names should be unique across all types of evidence. That way, we can greatly simplify
+ m.dst.source, too.
+ - WHY can we attach more than one evidence to a hypothesis?
+ - introduce new actions "attach/detach"
+ - introduce new action "check" to validate the contents of knowledge base file
+ - remove actions "const,rast,vect,att", they are types
+ - add ACTIONS "file-rast","file-vect" to attach external file data sources
+ - rename type=* to type=all
+ - type=all is an error for all actions except prune
+ - rework the prune= logics. All we need is the name of a hypothesis, and a type.
+ for single evidences, we have "detach"
+ - there is also a "clean=" option ("parm.null"). That's one too much!
+ - delete anything to do with const type evidence: we do not need this
+ - support voxel type evidence
+ - Improve checking in attach_vect():
+ vector evidence: needs to consist of a map and attribute name.
+ vector evidence: can only be a double type attribute.
+ vector evidence: attribute values must be in range (0;1)
+ - Improve checking in attach_rast():
+ raster evidence: must be floating point
+ raster evidence: must be in range (0;1)
+ - Clean-ups:
+ - replace strcpy, strcmp, strcat with XML functions
+ - call xmlFree(cur,...) at the end of functions
+ - user should be able to specify hyp=b,a AS WELL as hyp=a,b - it's the same!
+ - Other improvements:
+ - tighter checking for correct command line
+ - differentiate between BPNs and BPAs a BPA consists of several BPNs!
+ - Testing:
+ - rigorous testing of all ops (especially prune)
+ - Documentation:
+ - hypothesis names are case sensitive (also in m.dst.source)!
+
+*/
+
+char *xmlfile; /* store absolute pathname of XML file */
+xmlDocPtr doc;
+xmlNodePtr cur;
+int N_SINGLETONS = 0; /* number of singletons in knowledge base */
+int N_HYPOTHESES = 0;
+
+/* calculate facultary function for n */
+long fac (long n) {
+ long i,result=1;
+
+ for (i=1;i<=n;i++)
+ result=result*i;
+ return result;
+}
+
+
+/* returns the amount of memory needed to hold the argument string */
+/* (to improve readability) of source code */
+long int to_alloc (char *string) {
+ return (sizeof (xmlChar) * (strlen (string) + 1 ) );
+}
+
+
+/* return number of singletons in a hypothesis subset */
+int get_no_singletons (xmlChar *set) {
+ xmlChar *tmp;
+ xmlChar *copy;
+ int i;
+
+ /* must copy the argument, because it is going to get crippled */
+ /* by strtok ... */
+ copy = (xmlChar*) G_malloc ((signed) (sizeof(xmlChar) * strlen (set) * 2));
+ strcpy (copy,set);
+
+ /* extract first singleton */
+ tmp = strtok (copy,",");
+ /* don't count the empty set */
+ if ( strcmp (copy,"NULL") == 0) {
+ return (0);
+ }
+ i = 1;
+ /* look for further singletons */
+ while ( (tmp = strtok (NULL,",")) != NULL ) {
+ i ++;
+ }
+
+ G_free (copy);
+ return (i);
+}
+
+
+/* returns 1, if a singleton is part of a subset, 0 otherwise */
+int is_in_subset (char *set, char *singleton) {
+ char *tmp;
+ char *copy;
+
+ /* must copy the argument, because it is going to get crippled */
+ /* by strtok ... */
+ copy = (char*) G_malloc ((signed) (sizeof(char) * (strlen (set) * 2)));
+ strcpy (copy,set);
+
+ /* extract first singleton */
+ tmp = strtok (copy,",");
+ if (strcmp (tmp,singleton) == 0) {
+ G_free (copy);
+ return (1);
+ }
+
+ /* look for further singletons */
+ while ( (tmp = strtok (NULL,",")) != NULL ) {
+ if (strcmp (tmp,singleton) == 0) {
+ G_free (copy);
+ return (1);
+ }
+ }
+
+ G_free (copy);
+ return (0);
+}
+
+/* returns the singleton at position pos */
+/* pos starts at 0 */
+/* returns NULL if unsucessfull */
+
+/* caller must free the returned allocated char buffer! */
+/* OTHERWISE, THIS LEAKS MEMORY */
+char *get_singleton (xmlChar *set, int pos) {
+ char *tmp;
+ char *tmp2;
+ char *copy;
+ int i;
+
+ tmp2 = NULL;
+
+ /* trying to access a set out of bounds */
+ if ( ( pos < 0 ) || ( pos >= get_no_singletons (set) ) ) {
+ G_fatal_error ("Set index ouf of range\n.");
+ }
+
+ /* must copy the argument, because it is going to get crippled */
+ /* by strtok ... */
+ copy = (char*) G_malloc ((signed) (sizeof(char) * (strlen (set) + 1)));
+ strcpy (copy,set);
+
+ i = 0;
+ /* extract first singleton */
+ tmp = strtok (copy,",");
+ if ( i == pos ) {
+ tmp2 = G_malloc ((signed) (sizeof(char) * (strlen (tmp) + 1)));
+ strcpy (tmp2,tmp);
+ G_free (copy);
+ return (tmp2);
+ }
+
+ /* look for further singletons */
+ while ( (tmp = strtok (NULL,",")) != NULL ) {
+ i ++;
+ if ( pos == i ) {
+ tmp2 = G_malloc ((signed) (sizeof(char) * (strlen (tmp) + 1)));
+ strcpy (tmp2,tmp);
+ G_free (copy);
+ return (tmp2);
+ }
+ }
+
+ /* should never get here, but who knows ... */
+ G_free (tmp2);
+ G_free (copy);
+ return (NULL);
+}
+
+/* returns 1, if set is in the lookup list, 0 otherwise */
+int is_in_list (xmlChar *set, xmlChar **lookup, int len) {
+ long i;
+
+ for ( i = 0; i < len; i ++ ) {
+ if ( !strcmp (set,lookup[i]) ) {
+ return (1);
+ }
+ }
+ return (0);
+}
+
+
+
+/* returns 1, if name is rast,vect or const */
+/* 0 otherwise */
+int is_evidence (xmlChar *name) {
+ if ( name == NULL ) {
+ return (0);
+ }
+ if ( !strcasecmp (name,"const") ) {
+ return (1);
+ }
+ if ( !strcasecmp (name,"rast") ) {
+ return (1);
+ }
+ if ( !strcasecmp (name,"vect") ) {
+ return (1);
+ }
+ if ( !strcasecmp (name,"NULL") ) {
+ return (1);
+ }
+ return (0);
+}
+
+/*
+
+ USER-INVOKED ACTIONS
+
+*/
+
+/* user may supply only a singleton hypothesis */
+void add_hypothesis (char *name) {
+
+ int built_new = 0;
+ long hyps_needed;
+ long no_unique_sets, no_fac;
+ long no_lookups;
+ long h, i, j, k, overflow;
+ long counter [MAX_HYPOTHESES]; /* could actually be much smaller, but who cares) */
+ xmlChar **singleton;
+ xmlChar **lookup;
+ xmlChar *new_hyp;
+ xmlChar tmp [TMP_SIZE] ;
+ xmlNodePtr new_node;
+
+ lookup = NULL;
+ new_hyp = NULL;
+
+ /* hypothesis names must conform to same restrictions as filenames */
+ if ( G_legal_filename (name) != 1 ) {
+ G_fatal_error ("Hypothesis name invalid (contains special chars, whitespace or other).\n");
+ }
+ /* hypothesis names cannot have more than 32 chars */
+ if ( strlen (name) > (MAX_HYP_CHARS) ) {
+ sprintf (tmp,"Hypothesis names cannot be longer than %i characters.\n",
+ MAX_HYP_CHARS);
+ G_fatal_error ("%s",tmp);
+ }
+
+ /* cannot use TMP as hypothesis name */
+ if ( !strcmp (name,"TMP") ) {
+ G_fatal_error ("Hypothesis name 'TMP' is a reserved name.\n");
+ }
+
+ /* start at the root of the XML file */
+ cur = xmlDocGetRootElement(doc);
+ /* get the first child node of the root */
+ /* the child nodes contain the hypotheses */
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ while (cur != NULL) {
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) name, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ /* there already is a hypothesis with this name! */
+ sprintf (tmp,"Hypothesis '%s' already exists in the knowledge base.\n",
+ (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+ G_fatal_error ("%s",tmp);
+ }
+ }
+ cur = cur->next;
+ }
+
+ /* insert Hypothesis as a new child of the XML root */
+ cur = xmlDocGetRootElement(doc);
+ new_node = xmlNewTextChild (cur, NULL, (xmlChar*) "hyp", (xmlChar*) name);
+ /* increase number of stored singletons by one */
+ N_SINGLETONS ++;
+ /* ouch! cannot have that many hypotheses! */
+ if (N_SINGLETONS > MAX_HYPOTHESES) {
+ sprintf (tmp,"The maximum number of combinable user hypotheses is %i.\n",
+ MAX_HYPOTHESES);
+ G_fatal_error ("%s",tmp);
+ }
+ sprintf (tmp,"%i",N_SINGLETONS);
+ xmlSetProp(cur,(xmlChar*) "N_SINGLETONS", (xmlChar*) tmp);
+ /* increase number of hypotheses */
+ N_HYPOTHESES ++;
+ sprintf (tmp,"%i",N_HYPOTHESES);
+ xmlSetProp(cur,(xmlChar*) "N_HYPOTHESES", (xmlChar*) tmp);
+ /* set type of the newly created hyp-node to SINGLETON */
+ xmlSetProp(new_node,(xmlChar*) "TYPE", (xmlChar*) "USER");
+
+ /* check if a new subset has to be generated */
+ hyps_needed = (int) pow((float) 2, (float) N_SINGLETONS);
+ /* build a singleton-list of all singleton hypotheses */
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ singleton = (xmlChar**) G_malloc ((signed) (N_SINGLETONS * sizeof (xmlChar*)));
+
+ /* fill singleton list with hypothesis names */
+ i = 0;
+ while (cur != NULL) {
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ /* is it a singleton ? */
+ if (get_no_singletons ((xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) == 1) {
+ singleton[i] = (xmlChar*) G_malloc ((signed) ((strlen ((xmlChar*) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) + 1 ) * sizeof(xmlChar)));
+ singleton[i] = (xmlChar*) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+ /* jump over empty set */
+ if (strcmp ((char*) singleton[i],"NULL") != 0) {
+ i ++;
+ }
+ }
+ }
+ cur = cur->next;
+ }
+
+ if (N_HYPOTHESES < hyps_needed) {
+ /* need to generate new subsets! */
+ /* for each of the possible different subset-sizes ... */
+ for ( k = 2; k <= N_SINGLETONS; k ++ ) {
+ /* j stores the current subset size */
+ /* generate all unique subsets with j members */
+ no_unique_sets = fac(N_SINGLETONS) / ( fac(k) * fac(N_SINGLETONS-k) );
+ no_fac = no_unique_sets;
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+
+ /* CHANGE THIS TO SAVE SOME MEM */
+ /* LOOKUP LIST IS ACTUALLY SMALLER */
+ no_lookups = no_unique_sets;
+ /* DOESN'T REALLY MATTER, THOUGH */
+
+ /* determine number of sets size k that need to be generated */
+ while (cur != NULL) {
+ /* found a Hypothesis node? */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ if (get_no_singletons (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) == k) {
+ /* it is of the size we are currently trying to generate */
+ /* that counts as one done! */
+ no_unique_sets --;
+ }
+ }
+ cur = cur->next;
+ }
+
+ /* DEBUG */
+ /* fprintf (stderr,"%s: NEED %i (%i) sets of size %i\n", name, no_unique_sets, no_fac, k); */
+
+ /*
+ PASS 1: generate needed sets with TMP dummies
+ This time through, we will only put k TMP entries
+ into the XML tree. In PASS 2, we will fill them
+ with hierarchically ordered hypotheses nodes
+ */
+
+ for ( i = 0; i < no_unique_sets; i ++ ) {
+ /* new hypothesis set has to have at least 2 elements */
+ /* if set size > 2, attach more dummies */
+ sprintf (tmp,"TMP,TMP");
+ for (j = 0; j < (k-2); j++ ) {
+ strcat (tmp,",TMP");
+ }
+ /* attach new hypothesis sets to end of list */
+ cur = xmlDocGetRootElement(doc);
+ new_node = xmlNewTextChild (cur, NULL, (xmlChar*) "hyp", (xmlChar*) tmp);
+ xmlSetProp(new_node,(xmlChar*) "TYPE", (xmlChar*) "AUTO");
+ N_HYPOTHESES ++;
+ }
+
+ /* PASS 2: fill in the TMP entries with hypothesis sets */
+ i = 0;
+ new_hyp= G_malloc ((signed) ( (((sizeof (xmlChar) ) * MAX_HYP_CHARS ) * k) + ( sizeof (xmlChar) * (k + 1))) );
+ while ( i < no_unique_sets ) {
+ /* initialise counters */
+ for ( j = 0; j < N_SINGLETONS; j ++ ) {
+ counter [ j ] = j;
+ }
+ if (no_lookups > 0) {
+ /* build list of all hypotheses for quick lookup */
+ lookup = (xmlChar**) G_malloc ((signed) (no_lookups * sizeof (xmlChar*)));
+ /* get names of k-size hypotheses and store in lookup list */
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+
+ /* generate lookup list */
+ j = 0;
+ while (cur != NULL) {
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ if (get_no_singletons (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) == k) {
+ lookup[j] = (xmlChar*) G_malloc ((signed) ((strlen ((xmlChar*) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) + 1) * sizeof(xmlChar)));
+ lookup[j] = (xmlChar*) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+ j ++;
+ }
+ }
+ cur = cur->next;
+ }
+ }
+
+ /* construct initial set */
+ strcpy ( new_hyp, singleton [counter[0]] );
+ for ( j = 1; j < k; j ++) {
+ strcat ( new_hyp, "," );
+ strcat ( new_hyp, singleton [counter[j]] );
+ }
+
+ while ( is_in_list ( new_hyp, lookup, no_lookups ) ) {
+
+ overflow = 1;
+ built_new = 1;
+
+ for ( j = k-1; j > -1; j -- ) {
+ if ( overflow ) {
+ overflow = 0;
+ counter [ j ] ++ ;
+ if ( counter [ j ] > (j+(N_SINGLETONS-k)) ) {
+ overflow = 1;
+ counter [j] = 0;
+ }
+ }
+ }
+
+ /* update all counters, so that each counter */
+ /* is higher than its left neighbour */
+ for (h = 1; h < k; h ++) {
+ if (counter [h] <= counter [h-1] ) {
+ counter [h] = counter [h-1] + 1;
+ }
+ }
+
+ /* try to insert this hypothesis */
+ strcpy ( new_hyp, singleton [counter[0]] );
+ for ( j = 1; j < k; j ++) {
+ strcat ( new_hyp, "," );
+ strcat ( new_hyp, singleton [counter[j]] );
+ }
+ }
+ /* find right node to insert and do so! */
+ /* right node is the first TMP node with size = k */
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ j = 0;
+ while ((cur != NULL) && (j == 0)) {
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ if (get_no_singletons (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) == k) {
+ if ( strstr ( xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)
+ ,"TMP") != NULL ) {
+ //fprintf (stderr,"\tInserted %s\n",new_hyp);
+ xmlNodeSetContent (cur, new_hyp);
+ j = 1; /* this exits the while loop */
+ }
+ }
+ }
+ cur = cur->next;
+ }
+
+ for (j = 0; j < no_lookups; j ++) {
+ G_free (lookup[j]);
+ }
+ G_free (lookup);
+ i ++;
+ /* update status display only if needed */
+ if (built_new == 1) {
+ G_percent (N_HYPOTHESES, hyps_needed, 5);
+ fflush (stdout);
+ }
+ }
+ }
+
+ G_free (new_hyp);
+ }
+ /* update status display only if needed */
+ if (built_new == 1) {
+ G_percent (100, 100, 100);
+ printf ("\n");
+ fflush (stdout);
+ }
+
+ /* update number of hypotheses */
+ sprintf (tmp,"%i",N_HYPOTHESES);
+ cur = xmlDocGetRootElement(doc);
+ xmlSetProp(cur,(xmlChar*) "N_HYPOTHESES", (xmlChar*) tmp);
+
+ /* save changes to XML file */
+ xmlSaveFormatFile (xmlfile, doc, 1);
+
+ /* free memory */
+ for (i = 0; i < N_SINGLETONS; i ++) {
+ G_free (singleton[i]);
+ }
+ G_free (singleton);
+}
+
+/* delete a hypothesis (singletons only) */
+void del_hypothesis ( char *hyp ) {
+ int i = 0;
+ xmlNodePtr prevNode;
+
+ /* check if Hypothesis exists in knowledge base */
+ /* start at the root of the XML file */
+ cur = xmlDocGetRootElement(doc);
+ /* get the first child node of the root */
+ /* the child nodes contain the hypotheses */
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ while ((cur != NULL) && ( i ==0 ) ){
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) hyp, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ /* Found Hypothesis */
+ i = 1; /* this exits the while loop */
+ }
+ }
+ prevNode = cur;
+ cur = cur->next;
+ }
+
+ if ( i != 1 ) {
+ G_fatal_error ("Hypothesis '%s' does not exist in the knowledge base.\n",hyp);
+ }
+
+ /* delete every node in the XML tree that has the wanted singleton */
+ /* start at the root of the XML file */
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ i = 0;
+ while ( cur != NULL ) {
+ /* found a Hypothesis node! */
+ if ( !xmlStrcmp (cur->name, (const xmlChar *) "hyp" ) ) {
+ if ( is_in_subset ( xmlNodeListGetString(doc, cur->xmlChildrenNode, 1), hyp) ) {
+ /* Found Hypothesis */
+ i = 1; /* signal delayed deletion */
+ }
+ }
+ prevNode = cur;
+ cur = cur->next;
+ /* delayed deletion */
+ if (i == 1) {
+ xmlUnlinkNode (prevNode);
+ xmlFreeNode (prevNode);
+ i = 0;
+ }
+ }
+
+ /* save changes to XML file */
+ xmlSaveFormatFile (xmlfile, doc, 1);
+}
+
+/* rename a SINGLETON hypothesis */
+void ren_hypothesis ( char *hyp, char *newname ) {
+ int i = 0;
+ int j;
+ char *tmp;
+ char *tmp2;
+ char *result;
+ xmlNodePtr prevNode;
+
+ tmp2 = NULL;
+
+ /* check if Hypothesis exists in knowledge base */
+ /* start at the root of the XML file */
+ cur = xmlDocGetRootElement(doc);
+ /* get the first child node of the root */
+ /* the child nodes contain the hypotheses */
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ while ((cur != NULL) && ( i ==0 ) ){
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) hyp, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ /* Found Hypothesis */
+ i = 1; /* this exits the while loop */
+ }
+ }
+ prevNode = cur;
+ cur = cur->next;
+ }
+
+ if ( i != 1 ) {
+ G_fatal_error ("Hypothesis '%s' does not exist in the knowledge base.\n",hyp);
+ }
+
+ /* check for legal hypothesis name */
+ if (G_legal_filename (newname) == -1 ) {
+ G_fatal_error ("Please provide a well-formed hypothesis name (no special chars or whitespace).\n");
+ }
+
+ /* check for legal length of new name */
+ if ( strlen (newname) > MAX_HYP_CHARS ) {
+ G_fatal_error ("Hypothesis names my have at most %i characters.\n\tPlease choose a shorter name.\n",MAX_HYP_CHARS);
+ }
+
+ /* change name(s) of hypoheses */
+ /* rename every node in the XML tree that has the wanted name */
+ /* start at the root of the XML file */
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ /* parse all hypothesis nodes */
+ i = 0;
+ while ( cur != NULL ) {
+ /* found a Hypothesis node! */
+ if ( !xmlStrcmp (cur->name, (const xmlChar *) "hyp" ) ) {
+ if ( strstr ( xmlNodeListGetString(doc, cur->xmlChildrenNode, 1), hyp) != NULL ) {
+ /* Found Hypothesis */
+ i = 1; /* signal delayed renaming */
+ }
+ }
+ prevNode = cur;
+ cur = cur->next;
+ /* delayed renaming */
+ if (i == 1) {
+ /* rename */
+ tmp = G_malloc ((signed) (sizeof (xmlChar) * (strlen (xmlNodeListGetString(doc, prevNode->xmlChildrenNode, 1)) + 1)));
+ tmp = xmlNodeListGetString(doc, prevNode->xmlChildrenNode, 1);
+ /* make a buffer large enough to hold new set name */
+ result = G_malloc ((sizeof (xmlChar) * (MAX_HYP_CHARS*2)) + 1);
+ strcpy (result,"");
+ /* call tokenizer */
+ for (j = 0; j < get_no_singletons (tmp); j ++) {
+ tmp2 = get_singleton (tmp,j);
+ //fprintf (stderr,"\tTOKEN %i of %i: %s\n",j,get_no_singletons (tmp), tmp2);
+ if ( !strcmp (tmp2, hyp) ) {
+ /* replace this token */
+ if ( j > 0 ) strcat (result,",");
+ strcat (result,newname);
+ } else {
+ /* append unmodified token */
+ if ( j > 0 ) strcat (result,",");
+ strcat (result,tmp2);
+ }
+ G_free (tmp2);
+ }
+ strcpy (tmp,result);
+ xmlNodeSetContent(prevNode->xmlChildrenNode, result);
+ i = 0;
+ G_free (tmp);
+ G_free (result);
+ }
+ }
+
+ /* save changes */
+ xmlSaveFormatFile (xmlfile, doc, 1);
+}
+
+/* attach a constant bpn value to a hypothesis */
+void attach_const ( double bpa, char* hyp, int precision ) {
+ char *tmp;
+ int i = 0;
+ float result;
+ xmlNodePtr parentNode;
+ xmlNodePtr prevNode;
+
+ prevNode = NULL;
+
+ /* check if Hypothesis exists in knowledge base */
+ /* start at the root of the XML file */
+ cur = xmlDocGetRootElement(doc);
+ /* get the first child node of the root */
+ /* the child nodes contain the hypotheses */
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ while ((cur != NULL) && ( i ==0 ) ){
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) hyp, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ /* Found Hypothesis */
+ i = 1; /* this exits the while loop */
+ }
+ }
+ prevNode = cur;
+ cur = cur->next;
+ }
+
+ if ( i != 1 ) {
+ G_fatal_error ("Hypothesis '%s' does not exist in the knowledge base.\n",hyp);
+ }
+
+ /* convert back to str and store with user-defined precision */
+ i = 0;
+ result = bpa;
+ while ( result > 1 ) {
+ result = result / 10;
+ i ++;
+ }
+ /* get enough memory to store the number */
+ tmp = G_malloc ((signed) (sizeof (xmlChar) * i * (precision + 2)));
+ sprintf (tmp,"%2$.*1$f",precision,bpa);
+
+ /* check, if a CONST property already exists. If so, add this one. */
+ i = 0;
+ parentNode = prevNode;
+ cur = prevNode->xmlChildrenNode; /* go to first child */
+ while ((cur != NULL)){
+ /* found an attached const bpa */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "const"))) {
+ i = 1;
+ /* read attribute value */
+ if ( (!xmlStrcmp((const xmlChar *)
+ xmlNodeListGetString(doc, cur->xmlChildrenNode, 1), tmp))) {
+ /* Has same value: issue warning */
+ G_fatal_error ("Const bpn value '%s' already attached to hypothesis '%s'.\n", tmp,hyp);
+ }
+ }
+ cur = cur->next;
+ }
+
+ /* add another child node and store CONST bpa */
+ xmlNewTextChild (parentNode,NULL,"const",tmp);
+
+ /* save changes to XML file */
+ xmlSaveFormatFile (xmlfile, doc, 1);
+
+ G_free (tmp);
+}
+
+/* attach a raster map to a hypothesis */
+void attach_rast ( char *rastmap, char* hyp ) {
+ int i = 0;
+ xmlNodePtr parentNode;
+ xmlNodePtr prevNode;
+
+ prevNode = NULL;
+
+ /* check if Hypothesis exists in knowledge base */
+ /* start at the root of the XML file */
+ cur = xmlDocGetRootElement(doc);
+ /* get the first child node of the root */
+ /* the child nodes contain the hypotheses */
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ while ((cur != NULL) && ( i ==0 ) ){
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) hyp, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ /* Found Hypothesis */
+ i = 1; /* this exits the while loop */
+ }
+ }
+ prevNode = cur;
+ cur = cur->next;
+ }
+
+ if ( i != 1 ) {
+ G_fatal_error ("Hypothesis '%s' does not exist in the knowledge base.\n",hyp);
+ }
+
+ /* check, if raster map exists in mapset search path */
+ if ( G_find_cell (rastmap,"" ) == NULL ) {
+ G_fatal_error ("Raster map '%s' not found in current search path.\n",rastmap);
+ }
+
+ /* check, if a rast sibling already exists. */
+ i = 0;
+ parentNode = prevNode;
+ cur = prevNode->xmlChildrenNode; /* go to first child */
+ while ((cur != NULL)){
+ /* found an attached raster map */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "rast"))) {
+ i = 1;
+ /* read text of sibling */
+ if ( (!xmlStrcmp((const xmlChar *)
+ xmlNodeListGetString(doc, cur->xmlChildrenNode, 1), rastmap))) {
+ /* Has same value: issue warning */
+ G_fatal_error ("Raster map '%s' already attached to hypothesis '%s'.\n", rastmap,hyp);
+ }
+ }
+ cur = cur->next;
+ }
+
+ /* add another child node and store rast map */
+ xmlNewTextChild (parentNode,NULL,"rast",rastmap);
+
+ /* save changes to XML file */
+ xmlSaveFormatFile (xmlfile, doc, 1);
+}
+
+/* attach a vector map to a hypothesis */
+void attach_vect ( char *vectmap, char *attname, char* hyp ) {
+ int i = 0;
+ xmlNodePtr parentNode;
+ xmlNodePtr prevNode;
+
+ prevNode = NULL;
+
+ /* check if Hypothesis exists in knowledge base */
+ /* start at the root of the XML file */
+ cur = xmlDocGetRootElement(doc);
+ /* get the first child node of the root */
+ /* the child nodes contain the hypotheses */
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ while ((cur != NULL) && ( i ==0 ) ){
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) hyp, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ /* Found Hypothesis */
+ i = 1; /* this exits the while loop */
+ }
+ }
+ prevNode = cur;
+ cur = cur->next;
+ }
+
+ if ( i != 1 ) {
+ G_fatal_error ("Hypothesis '%s' does not exist in the knowledge base.\n",hyp);
+ }
+
+ /* check, if vector map exists in mapset search path */
+ if ( G_find_vector (vectmap,"" ) == NULL ) {
+ G_fatal_error ("Vector map '%s' not found in current search path.\n",vectmap);
+ }
+
+ /* check, if a vect sibling already exists. */
+ i = 0;
+ parentNode = prevNode;
+ cur = prevNode->xmlChildrenNode; /* go to first child */
+ while ((cur != NULL)){
+ /* found an attached vector map */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "vect"))) {
+ i = 1;
+ /* read text of sibling */
+ if ( (!xmlStrcmp((const xmlChar *)
+ xmlNodeListGetString(doc, cur->xmlChildrenNode, 1), vectmap))) {
+ /* Has same value: issue warning */
+ G_fatal_error ("Vector map '%s' already attached to hypothesis '%s'.\n", vectmap,hyp);
+ }
+ }
+ cur = cur->next;
+ }
+
+ /* add another child node and store vect map */
+ prevNode = xmlNewTextChild (parentNode,NULL,"vect",vectmap);
+
+ i = 0;
+ /*
+ result = fuzzyness;
+ while ( result > 1 ) {
+ result = result / 10;
+ i ++;
+ }
+ tmp = G_malloc (sizeof (xmlChar) * i * (precision + 2));
+ sprintf (tmp,"%2$.*1$f",precision,fuzzyness);
+ */
+
+ /* save changes to XML file */
+ xmlSaveFormatFile (xmlfile, doc, 1);
+}
+
+
+/* remove all evidence from a hypothesis */
+void attach_null ( char *hyp ) {
+ int i = 0;
+ xmlNodePtr prevNode;
+
+ prevNode = NULL;
+
+ /* check if Hypothesis exists in knowledge base */
+ /* start at the root of the XML file */
+ cur = xmlDocGetRootElement(doc);
+ /* get the first child node of the root */
+ /* the child nodes contain the hypotheses */
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ while ((cur != NULL) && ( i ==0 ) ){
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) hyp, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ /* Found Hypothesis */
+ i = 1; /* this exits the while loop */
+ prevNode = cur;
+ }
+ }
+ cur = cur->next;
+ }
+
+ if ( i != 1 ) {
+ G_fatal_error ("Hypothesis '%s' does not exist in the knowledge base.\n",hyp);
+ }
+
+ i = 0;
+ cur = prevNode->xmlChildrenNode; /* go to first child */
+ /* walk through all siblings and delete if necessary */
+ while ((cur != NULL)){
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "const"))) {
+ i = 1; /* this signals delayed deletion */
+ }
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "rast"))) {
+ i = 1;
+ }
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "vect"))) {
+ i = 1;
+ }
+ prevNode = cur;
+ cur = cur->next;
+ if ( i == 1 ) {
+ /* remove evidence from hyp */
+ xmlUnlinkNode (prevNode);
+ xmlFreeNode (prevNode);
+ i = 0;
+ }
+ }
+
+ /* save changes to XML file */
+ xmlSaveFormatFile (xmlfile, doc, 1);
+}
+
+
+/* detaches an evidence from ALL hypotheses
+ detaches an evidence from ONE selected hypothesis, if *hyp != NULL, i.e.
+ if the user has specified a hypothesis name on the command line
+ type may be: const,rast,vect,*
+ use prune=* to prune all evidence of a specified type
+ use hyp=* to prune evidence from all Hyps
+ use type=* to prune evidence of all types
+ use any combination of the above (with care)!
+*/
+void prune ( char *evidence, char *hyp, char *type ) {
+
+ int i = 0;
+ xmlNodePtr parentNode;
+ xmlNodePtr prevNode;
+
+ //fprintf (stderr,"PRUNE: EVI=%s, HYP=%s, TYP=%s\n",evidence, hyp, type);
+
+ if ( strcmp (hyp,"*") != 0 ) {
+ /* user wants to prune only a single hypothesis: check if it exists */
+ /* check if Hypothesis exists in knowledge base */
+ /* start at the root of the XML file */
+ cur = xmlDocGetRootElement(doc);
+ /* get the first child node of the root */
+ /* the child nodes contain the hypotheses */
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ while ((cur != NULL) && ( i ==0 ) ){
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ if ( (!xmlStrcmp((const xmlChar *) hyp, (const xmlChar *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ /* Found Hypothesis */
+ i = 1; /* this exits the while loop */
+ }
+ }
+ prevNode = cur;
+ cur = cur->next;
+ }
+
+ if ( i != 1 ) {
+ G_fatal_error ("Hypothesis '%s' does not exist in the knowledge base.\n",hyp);
+ }
+ }
+
+ /* traverse the XML tree and delete all references to evidence */
+ /* start at the root of the XML file */
+ cur = xmlDocGetRootElement(doc);
+ /* get the first child node of the root */
+ /* the child nodes contain the hypotheses */
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ i = 0;
+ while ( cur != NULL ){
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ parentNode = cur->xmlChildrenNode; /* go to first child */
+ if ( strcmp (hyp,"*") != 0 ) { /* user has specified a hyp to prune */
+ fprintf (stderr,"HYP=%s\n",hyp);
+ if ( (!xmlStrcmp((const xmlChar *) hyp, (const xmlChar *)
+ xmlNodeListGetString(doc, cur->xmlChildrenNode, 1) ))) {
+ /* only delete from user-specified hypothesis */
+ while ((parentNode != NULL)){
+ /* walk through all siblings and delete if necessary */
+ if ((!xmlStrcmp(parentNode->name, (const xmlChar *) type))) {
+ fprintf (stderr,"\tTYPE=%s\n",type);
+ /* found evidence of the type to be deleted */
+ if ( strcmp (evidence,"*") != 0 ) { /* delete only specified evidence */
+ fprintf (stderr,"\t\tEVI=%s\n",evidence);
+ if ( (!xmlStrcmp((const xmlChar *) evidence, (const xmlChar *)
+ xmlNodeListGetString(doc, parentNode->xmlChildrenNode, 1) ))) {
+ i = 1;
+ }
+ }
+ else { /* delete all evidence */
+ fprintf (stderr,"\t\tEVI=ALL\n");
+ if ( is_evidence (xmlNodeListGetString(doc, parentNode->xmlChildrenNode, 1)) ) {
+ i = 1; /* this signals delayed deletion */
+ fprintf (stderr,"\t\t\tPRUNE\n");
+ }
+ }
+ }
+ if ( !strcmp (type,"*") ) { /* user wants to prune all types! */
+ fprintf (stderr,"\tTYPE=ALL\n");
+ if ( strcmp (evidence,"*") != 0 ) { /* delete only specified evidence */
+ if ( (!xmlStrcmp((const xmlChar *) evidence, (const xmlChar *)
+ xmlNodeListGetString(doc, parentNode->xmlChildrenNode, 1) ))) {
+ i = 1;
+ }
+ }
+ else { /* delete all evidence */
+ fprintf (stderr,"\t\tEVI=ALL\n");
+ if ( is_evidence (xmlNodeListGetString(doc, parentNode->xmlChildrenNode, 1)) ) {
+ i = 1; /* this signals delayed deletion */
+ }
+ }
+ }
+ prevNode = parentNode;
+ parentNode = parentNode->next;
+ if ( i == 1 ) {
+ /* remove evidence from hyp */
+ xmlUnlinkNode (prevNode);
+ xmlFreeNode (prevNode);
+ i = 0;
+ }
+ }
+ }
+ }
+ else { /* prune all hyps */
+ fprintf (stderr,"HYP=ALL\n");
+ while ((parentNode != NULL)){
+ /* walk through all siblings and delete if necessary */
+ if ((!xmlStrcmp(parentNode->name, (const xmlChar *) type))) {
+ /* found evidence of the type to be deleted */
+ if ( strcmp (evidence,"*") != 0 ) {
+ fprintf (stderr,"\tTYPE=%s\n",type);
+ if ( (!xmlStrcmp((const xmlChar *) evidence, (const xmlChar *)
+ xmlNodeListGetString(doc, parentNode->xmlChildrenNode, 1) ))) {
+ i = 1;
+ }
+ } else { /* user wants to delete all evidences */
+ fprintf (stderr,"\t\tEVI=ALL\n");
+ if ( is_evidence (xmlNodeListGetString(doc, parentNode->xmlChildrenNode, 1)) ) {
+ i = 1; /* this signals delayed deletion */
+ }
+ }
+ }
+ if ( !strcmp (type,"*") ) { /* user wants to prune all types! */
+ fprintf (stderr,"\tTYPE=ALL\n");
+ if ( strcmp (evidence,"*") != 0 ) { /* delete only specified evidence */
+ fprintf (stderr,"\t\tEVI=%s\n",evidence);
+ if ( (!xmlStrcmp((const xmlChar *) evidence, (const xmlChar *)
+ xmlNodeListGetString(doc, parentNode->xmlChildrenNode, 1) ))) {
+ i = 1;
+ }
+ }
+ else { /* delete all type of evidence */
+ fprintf (stderr,"\t\tEVI=ALL\n");
+ if ( is_evidence (xmlNodeListGetString(doc, parentNode->xmlChildrenNode, 1)) ) {
+ i = 1; /* this signals delayed deletion */
+ }
+ }
+ }
+ prevNode = parentNode;
+ parentNode = parentNode->next;
+ if ( i == 1 ) {
+ /* remove evidence from hyp */
+ xmlUnlinkNode (prevNode);
+ xmlFreeNode (prevNode);
+ i = 0;
+ }
+ }
+ }
+ }
+ cur = cur->next;
+ }
+
+ /* save changes to XML file */
+ xmlSaveFormatFile (xmlfile, doc, 1);
+
+}
+
+int
+main (int argc, char *argv[])
+{
+ struct GModule *module;
+ struct
+ {
+ struct Option *file;
+ struct Option *add;
+ struct Option *del;
+ struct Option *ren;
+ struct Option *newname;
+ struct Option *cnst;
+ struct Option *rast;
+ struct Option *vect;
+ struct Option *att;
+ struct Option *null;
+ struct Option *prune;
+ struct Option *hyp;
+ struct Option *type;
+ struct Option *precision;
+ }
+ parm;
+
+ FILE *kb; /* knowledge base */
+ char *tmp;
+
+ G_gisinit ( argv[0] );
+
+ tmp = (char*) G_malloc (255 * sizeof(char));
+
+ int num_actions;
+
+ /* setup some basic GIS stuff */
+ G_gisinit (argv[0]);
+ module = G_define_module ();
+ module->description = "Manages the contents of a Dempster-Shafer knowledge base.";
+ /* do not pause after a warning message was displayed */
+ G_sleep_on_error (0);
+
+ /* Parameters */
+ parm.file = G_define_option ();
+ parm.file->key = "file";
+ parm.file->type = TYPE_STRING;
+ parm.file->required = YES;
+ parm.file->description = "Filename of the knowledge base to modify";
+
+ parm.add = G_define_option ();
+ parm.add->key = "add";
+ parm.add->type = TYPE_STRING;
+ parm.add->required = NO;
+ parm.add->description = "Add a user (singleton) hypothesis to the knowledge base";
+
+ parm.del = G_define_option ();
+ parm.del->key = "delete";
+ parm.del->type = TYPE_STRING;
+ parm.del->required = NO;
+ parm.del->description = "Delete a hypothesis from the knowledge base";
+
+ parm.ren = G_define_option ();
+ parm.ren->key = "rename";
+ parm.ren->type = TYPE_STRING;
+ parm.ren->required = NO;
+ parm.ren->description = "Rename a hypothesis in the knowledge base";
+
+ parm.newname = G_define_option ();
+ parm.newname->key = "to";
+ parm.newname->type = TYPE_STRING;
+ parm.newname->required = NO;
+ parm.newname->description = "New name for hypothesis (use with 'rename=')";
+
+ parm.cnst = G_define_option ();
+ parm.cnst->key = "const";
+ parm.cnst->type = TYPE_DOUBLE;
+ parm.cnst->options = "0-1";
+ parm.cnst->required = NO;
+ parm.cnst->description = "Attach constant evidence to a hypothesis";
+
+ parm.rast = G_define_standard_option (G_OPT_R_INPUT);
+ parm.rast->key = "rast";
+ parm.rast->type = TYPE_STRING;
+ parm.rast->required = NO;
+ parm.rast->description = "Attach a GRASS raster map as evidence to a hypothesis";
+ parm.rast->gisprompt = "old,fcell,raster";
+
+ parm.vect = G_define_standard_option (G_OPT_V_INPUT);
+ parm.vect->key = "vect";
+ parm.vect->type = TYPE_STRING;
+ parm.vect->required = NO;
+ parm.vect->description = "Attach a GRASS vector map as evidence to a hypothesis (use with 'att=')";
+
+ parm.att = G_define_option ();
+ parm.att->key = "att";
+ parm.att->type = TYPE_STRING;
+ parm.att->required = NO;
+ parm.att->description = "Attach an attribute field as evidence to a hypothesis (use with 'vect=')";
+
+ parm.null = G_define_option ();
+ parm.null->key = "clean";
+ parm.null->type = TYPE_STRING;
+ parm.null->required = NO;
+ parm.null->description = "Remove all attached evidence from a hypothesis";
+
+ parm.prune = G_define_option ();
+ parm.prune->key = "prune";
+ parm.prune->type = TYPE_STRING;
+ parm.prune->required = NO;
+ parm.prune->description = "Remove multiple evidences from one or more hypotheses";
+
+ parm.hyp = G_define_option ();
+ parm.hyp->key = "hypothesis";
+ parm.hyp->type = TYPE_STRING;
+ parm.hyp->required = NO;
+ parm.hyp->description = "Name of hypothesis to operate on";
+
+ parm.type = G_define_option ();
+ parm.type->key = "type";
+ parm.type->type = TYPE_STRING;
+ parm.type->required = NO;
+ parm.type->options = "const,rast,vect,*";
+ parm.type->description = "Type of evidence to remove (use with 'prune=')";
+
+ parm.precision = G_define_option ();
+ parm.precision->key = "precision";
+ parm.precision->type = TYPE_INTEGER;
+ parm.precision->required = NO;
+ parm.precision->description = "Decimal places to store for constant evidence";
+ parm.precision->answer = "3";
+ parm.precision->options = "0-10";
+
+ /* disable interactive mode */
+ G_disable_interactive ();
+
+ /* parse command line */
+ if (G_parser (argc, argv))
+ {
+ exit (-1);
+ }
+
+ /* check if we have read/write access to knowledge base file */
+ errno = 0;
+ kb = fopen (parm.file->answer,"r+");
+ if ( kb == NULL ) {
+ G_fatal_error ("Cannot open knowledge base file for reading and writing.\nReason: %s.", strerror (errno));
+ } else {
+ fclose(kb);
+ }
+
+ /* this is necessary to produce nicely formatted output */
+ xmlKeepBlanksDefault (0);
+
+ xmlfile=G_strdup(parm.file->answer);
+
+ /* parse the XML structure; check that we have a valid file */
+ doc = xmlParseFile (xmlfile);
+ if ( doc == NULL ) {
+ xmlFreeDoc(doc);
+ G_fatal_error ("Could not parse XML structure of knowledge base.\n");
+ }
+
+ cur = xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ xmlFreeDoc(doc);
+ G_fatal_error ("Knowledge base is an empty file.\n");
+ }
+
+ if (xmlStrcmp(cur->name, (const xmlChar *) "dst-kb")) {
+ xmlFreeDoc(doc);
+ G_fatal_error ("File is not a DST knowledge base.\n");
+ }
+
+ N_SINGLETONS = atoi (xmlGetProp(cur, "N_SINGLETONS"));
+ N_HYPOTHESES = atoi (xmlGetProp(cur, "N_HYPOTHESES"));
+
+
+ /* check basic parameter logic */
+ num_actions = 0;
+
+ /* add a hypothesis */
+ if ( parm.add->answer != NULL) {
+ /* user may not supply more than a singleton hypothesis */
+ /* all combinations will be built automatically */
+ if ( strchr (parm.add->answer, (int) ',') != NULL ) {
+ G_fatal_error ("Only SINGLETON hypotheses can be created by the user.\n");
+ }
+ /* the NULL has a special meaning! */
+ if ( strcasecmp (parm.add->answer,"NULL") == 0 ) {
+ G_fatal_error ("User cannot supply a 'NULL' hypothesis; it is implicit.\n");
+ }
+ if ( is_evidence (parm.add->answer) ) {
+ G_fatal_error ("The keyword '%s' cannot be used as a hypothesis name.\n",parm.add->answer);
+ }
+ num_actions ++;
+ }
+
+ /* delete a hypothesis */
+ if ( parm.del->answer != NULL ) {
+ /* user may not supply more than a singleton hypothesis */
+ /* all combinations will be built automatically */
+ if ( strchr (parm.del->answer, (int) ',') != NULL ) {
+ G_fatal_error ("Only SINGLETON hypotheses can be deleted by the user.\n");
+ }
+ /* the NULL has a special meaning! */
+ if ( strcasecmp (parm.del->answer,"NULL") == 0 ) {
+ G_fatal_error ("User cannot delete the 'NULL' hypothesis; it is implicit.\n");
+ }
+ num_actions ++;
+ }
+
+ /* rename a hypothesis */
+ if ( parm.ren->answer != NULL ) {
+ /* user may not supply more than a singleton hypothesis */
+ /* all combinations will be built automatically */
+ if ( strchr (parm.ren->answer, (int) ',') != NULL ) {
+ G_fatal_error ("Only SINGLETON hypotheses can be renamed by the user.\n");
+ }
+ /* the NULL has a special meaning! */
+ if ( strcmp (parm.ren->answer,"NULL") == 0 ) {
+ G_fatal_error ("User cannot rename the 'NULL' hypothesis; it is implicit.\n");
+ }
+ /* a new filename must also be provided */
+ if ( parm.newname->answer == NULL ) {
+ G_fatal_error ("Please also provide a new name using 'new='.\n");
+ }
+ if ( is_evidence (parm.newname->answer) ) {
+ G_fatal_error ("The keyword '%s' cannot be used as a hypothesis name.\n",parm.newname->answer);
+ }
+ num_actions ++;
+ }
+
+ /* attach evidence of different types */
+ /* CONST value */
+ if ( parm.cnst->answer != NULL ) {
+ if ( parm.hyp->answer == NULL ) {
+ G_fatal_error ("Please provide a hypothesis using 'hyp='.\n");
+ }
+ num_actions ++;
+ }
+
+ /* RAST */
+ if ( parm.rast->answer != NULL ) {
+ if ( parm.hyp->answer == NULL ) {
+ G_fatal_error ("Please provide a hypothesis using 'hyp='.\n");
+ }
+ num_actions ++;
+ }
+
+ /* ATTRIBUTE NAME */
+ if ( parm.att->answer != NULL ) {
+ if ( parm.vect->answer == NULL ) {
+ G_fatal_error ("Please provide a vector map using 'vect='.\n");
+ }
+ num_actions ++;
+ }
+
+ /* VECT */
+ if ( parm.vect->answer != NULL ) {
+ if ( parm.att->answer == NULL ) {
+ G_fatal_error ("Please provide an attribute field using 'att='.\n");
+ }
+ if ( parm.hyp->answer == NULL ) {
+ G_fatal_error ("Please provide a hypothesis using 'hyp='.\n");
+ }
+ num_actions ++;
+ }
+
+ /* NULL = remove all evidence from a hypothesis */
+ if ( parm.null->answer != NULL ) {
+ /* user wants to remove evidence from a hypothesis */
+ num_actions ++;
+ }
+
+ /* prune evidence */
+ if ( parm.prune->answer != NULL ) {
+ if ( parm.hyp->answer == NULL ) {
+ G_fatal_error
+ ("Please provide name of hypothesis to prune (or '*' for all) using 'hyp='.\n");
+ }
+ if ( parm.type->answer == NULL ) {
+ G_fatal_error ("Provide type of evidence to prune (or '*' for all) using 'type='.\n");
+ }
+ /* NULL has a special meaning! */
+ if ( parm.hyp->answer != NULL ) {
+ if ( strcmp (parm.hyp->answer,"NULL") == 0 ) {
+ G_fatal_error ("Evidence cannot be pruned from the 'NULL' hypothesis.\n");
+ }
+ }
+ num_actions ++;
+ }
+
+ /* Exactly one action given? */
+ if ( num_actions != 1 ) {
+ G_fatal_error ("Please specify exactly one action to perform on the knowledge base.\n");
+ }
+
+ /* Run the chosen action */
+ if ( parm.add->answer != NULL) {
+ add_hypothesis (parm.add->answer);
+ }
+ if ( parm.del->answer != NULL ) {
+ del_hypothesis (parm.del->answer);
+ }
+ if ( parm.ren->answer != NULL ) {
+ ren_hypothesis (parm.ren->answer, parm.newname->answer);
+ }
+ if ( parm.cnst->answer != NULL ) {
+ /* user wants to attach a constant bpa value to a hypothesis */
+ attach_const (atof (parm.cnst->answer),parm.hyp->answer,atoi(parm.precision->answer));
+ }
+ if ( parm.rast->answer != NULL ) {
+ /* user wants to attach a raster map to a hypothesis */
+ attach_rast ( parm.rast->answer, parm.hyp->answer);
+ }
+ if ( parm.vect->answer != NULL ) {
+ attach_vect ( parm.vect->answer, parm.att->answer, parm.hyp->answer );
+ }
+ if ( parm.null->answer != NULL ) {
+ attach_null (parm.null->answer);
+ }
+ if ( parm.prune->answer != NULL ) {
+ prune ( parm.prune->answer, parm.hyp->answer, parm.type->answer );
+ }
+
+ G_free (tmp);
+ xmlFree(cur);
+ xmlFree(doc);
+ G_free (xmlfile);
+
+ exit (EXIT_SUCCESS);
+}
Property changes on: grass-addons/grass6/dst/misc/m.dst.update/main.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/misc/m.dst.view/Makefile
===================================================================
--- grass-addons/grass6/dst/misc/m.dst.view/Makefile (rev 0)
+++ grass-addons/grass6/dst/misc/m.dst.view/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,11 @@
+MODULE_TOPDIR = ../..
+
+PGM = m.dst.view
+
+XMLLIB = `xml2-config --libs`
+LIBES = $(GISLIB) $(DATETIMELIB) $(XMLLIB)
+EXTRA_CFLAGS = `xml2-config --cflags` -I../../include
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
Added: grass-addons/grass6/dst/misc/m.dst.view/description.html
===================================================================
--- grass-addons/grass6/dst/misc/m.dst.view/description.html (rev 0)
+++ grass-addons/grass6/dst/misc/m.dst.view/description.html 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<TITLE>dst.view</TITLE>
+
+<body bgcolor="white">
+
+<h2>DESCRIPTION</h2>
+
+With the <em>dst.view</em> command, the information in a Dempster-Shafer knowledge base file
+can be printed out in a formatted, easy-to-read fashion.
+The knowledge base file is an XML format ASCII file which resides in its own 'DST' element
+inside the user's current mapset.
+Such a file is necessary to perform Dempster-Shafer Theory (DST) calculations using
+<EM><A HREF="dst.combine.html">dst.combine </A></EM>.
+If you do not know what DST is or why you would need this program, please refer to the
+<EM><A HREF="dst.combine.html">dst.combine </A></EM> command's manpage for an introduction.<p>
+Knowledge base files themselves can be listed, created, deleted and renamed using a special
+<A HREF="dst.list.html">set of commands</A>.
+
+<h3>Flags</h3>
+<dl>
+<dt><strong>-a</strong></dt>
+ <dd>Show all hypotheses (including type 'AUTO'). Normally, only <em>singleton</em> hypotheses
+ supplied by the user (type 'USER') are shown. If this flag is set, then sets of hypotheses
+ that were generated automatically will also be shown, as well. See the manpage of
+ <EM><A HREF="dst.update.html">dst.update </A></EM> for an explanation of the different
+ types.
+ </dd>
+</dl>
+
+<h3>Parameters</h3>
+<dl>
+<dt><B>file=</B><EM>name</EM></dt>
+ <dd>Name of DST knowledge base file to view. You can get a listing of DST
+ knowledge base files in your current mapset by invoking
+ <EM><A HREF="dst.list.html">dst.list </A></EM>.
+ </dd>
+<dt><B>logfile=</B><EM>name</EM></dt>
+ <dd>Specfiy a valid file name if you want the output stored in a file instead
+ of printed on the screen.
+ </dd>
+</dl>
+
+<h3>Notes</h3>
+This program was developed as part of the GRASS 5 DST Predictive Modelling Toolkit.<br>
+The term "knowledge base file" was first used in the manual of the
+<A HREF="www.clarklabs.org" target="_blank"> IDRISI GIS </A> software which also offers some DST functionality.<br>
+<h3>SEE ALSO</h3>
+<EM><A HREF="dst.combine.html">dst.combine</A></EM><br>
+<EM><A HREF="dst.update.html">dst.update</EM></A><br>
+<EM><A HREF="dst.list.html">dst.create, dst.remove, dst.rename, dst.list</A></EM><br>
+<h3>AUTHOR</h3>
+Benjamin Ducke,<br>
+University of Kiel, Germany<br>
+<i>Last changed: 2005/07/21</i>
+</body>
+</html>
Property changes on: grass-addons/grass6/dst/misc/m.dst.view/description.html
___________________________________________________________________
Added: svn:mime-type
+ text/html
Added: svn:keywords
+ Author Date Id
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/misc/m.dst.view/main.c
===================================================================
--- grass-addons/grass6/dst/misc/m.dst.view/main.c (rev 0)
+++ grass-addons/grass6/dst/misc/m.dst.view/main.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,586 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#include <grass/gis.h>
+
+
+int N_SINGLETONS = 0; /* number of singletons in knowledge base */
+int N_HYPOTHESES = 0; /* number of hypotheses in knowledge base */
+xmlDocPtr doc;
+FILE *lp;
+
+
+/* returns the amount of memory needed to hold the argument string */
+/* to improve readability */
+long int to_alloc (xmlChar *string) {
+ return (sizeof (xmlChar) * (xmlStrlen (string) + 1 ) );
+}
+
+
+/* return number of singletons in a hypothesis subset */
+int get_no_singletons (xmlChar *set) {
+ xmlChar *tmp;
+ xmlChar *copy;
+ int i;
+
+ /* must copy the argument, because it is going to get crippled */
+ /* by strtok ... */
+ copy = (xmlChar*) G_malloc ((signed) (sizeof(xmlChar) * strlen (set) * 2));
+ strcpy (copy,set);
+
+ /* extract first singleton */
+ tmp = strtok (copy,",");
+ /* don't count the empty set */
+ if ( strcmp (copy,"NULL") == 0) {
+ return (0);
+ }
+ i = 1;
+ /* look for further singletons */
+ while ( (tmp = strtok (NULL,",")) != NULL ) {
+ i ++;
+ }
+
+ G_free (copy);
+ return (i);
+}
+
+int is_evidence (xmlChar *name) {
+ if ( name == NULL ) {
+ return (0);
+ }
+ if ( !strcmp (name,"const") ) {
+ return (1);
+ }
+ if ( !strcmp (name,"rast") ) {
+ return (1);
+ }
+ if ( !strcmp (name,"vect") ) {
+ return (1);
+ }
+ return (0);
+}
+
+void open_xml_file ( char* filename ) {
+
+ xmlNodePtr cur;
+ char *xmlfile; /* file name of knowledge base */
+
+ /* get a fully qualified, absolute path and filename for */
+ /* reading/writing the XML database file. */
+ /* What to do on a DOS system? Let's hope that libxml handles it!*/
+ xmlfile = G_strdup (filename);
+
+ /* parse the XML structure; check that we have a valid file */
+ doc = xmlParseFile (xmlfile);
+ if ( doc == NULL ) {
+ xmlFreeDoc(doc);
+ G_fatal_error ("Could not parse XML structure of knowledge base file.\n");
+ }
+
+ cur = xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ xmlFreeDoc(doc);
+ G_fatal_error ("Knowledge base is an empty file.\n");
+ }
+
+ if (xmlStrcmp(cur->name, (const xmlChar *) "dst-kb")) {
+ xmlFreeDoc(doc);
+ G_fatal_error ("File is not a DST knowledge base.\n");
+ }
+
+ N_SINGLETONS = atoi (xmlGetProp(cur, "N_SINGLETONS"));
+ N_HYPOTHESES = atoi (xmlGetProp(cur, "N_HYPOTHESES"));
+}
+
+
+void print_header ( char *filename ) {
+ fprintf (lp,"DEMPSTER-SHAFER KNOWLEDGE BASE INFORMATION\n");
+ fprintf (lp,"Filename: %s\n", filename );
+ fprintf (lp,"No. of user-supplied singletons:\t%i\n",N_SINGLETONS);
+ fprintf (lp,"No. of possible hypotheses overall:\t%i\n",N_HYPOTHESES);
+}
+
+void print_hypotheses ( int print_all ) {
+
+ int present = 0;
+ xmlNodePtr cur;
+
+ fprintf (lp,"\nHYPOTHESES");
+ if ( ! print_all == 1 ) {
+ fprintf (lp," (type USER only):\n");
+ } else {
+ fprintf (lp,":\n");
+ }
+ present = 0;
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ while ((cur != NULL) ) {
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ /* check if it user-supplied */
+ if ( xmlStrcmp ( "USER", xmlGetProp (cur, "TYPE")) == 0 ) {
+ present ++;
+ fprintf (lp," '%s'\n",xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+ } if ( print_all ) {
+ /* if print_all flag is active: also dump NULL and AUTO types */
+ if ( xmlStrcmp ( "AUTO", xmlGetProp (cur, "TYPE")) == 0 ) {
+ present ++;
+ fprintf (lp," '%s' [AUTO]\n",xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+ }
+ if ( xmlStrcmp ( "NULL", xmlGetProp (cur, "TYPE")) == 0 ) {
+ present ++;
+ fprintf (lp," '%s' [NULL]\n",xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+ }
+ }
+ }
+ cur = cur->next;
+ }
+ if ( present == 0 ) {
+ fprintf (lp," - NONE - \n" );
+ }
+}
+
+
+void print_const_evidence ( void ) {
+
+ int i = 0;
+ int j;
+ int present = 0;
+ xmlNodePtr cur;
+ xmlNodePtr parentNode;
+
+
+ fprintf (lp,"\nCONSTANT EVIDENCE:\n");
+ /* 1: print user-supplied stuff */
+ fprintf (lp,"A) USER Hypothesis SINGLETONS:\n");
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ while ((cur != NULL) ) {
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ /* check if there is a CONST evidence attached */
+ i = 0;
+ parentNode = cur->xmlChildrenNode;
+ while ((parentNode != NULL)){
+ if ((!xmlStrcmp(parentNode->name, "const"))) {
+ i ++;
+ }
+ parentNode = parentNode->next;
+ }
+ if ( i > 0 ) {
+ /* get name of Hypothesis */
+ if ( xmlStrcmp ( "USER", xmlGetProp (cur, "TYPE")) == 0 ) {
+ present = 1;
+ fprintf (lp," '%s'\n",xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+ /* now get all the CONST entries */
+ parentNode = cur->xmlChildrenNode;
+ j = 1;
+ while ((parentNode != NULL)){
+ if ((!xmlStrcmp(parentNode->name, "const"))) {
+ fprintf (lp,"\t%i. %s\n",j,xmlNodeListGetString(doc, parentNode->xmlChildrenNode, 1));
+ j ++;
+ }
+ parentNode = parentNode->next;
+ }
+ }
+ }
+ }
+ cur = cur->next;
+ }
+
+ if ( present == 0 ) {
+ fprintf (lp," - NONE - \n" );
+ }
+ present = 0;
+
+ /* 2: print auto-generated stuff */
+ fprintf (lp,"B) AUTO Hypothesis SETS:\n");
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ while ((cur != NULL) ) {
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ /* check if there is a CONST evidence attached */
+ i = 0;
+ parentNode = cur->xmlChildrenNode;
+ while ((parentNode != NULL)){
+ if ((!xmlStrcmp(parentNode->name, "const"))) {
+ i ++;
+ }
+ parentNode = parentNode->next;
+ }
+ if ( i > 0 ) {
+ /* get name of Hypothesis */
+ if ( xmlStrcmp ( "AUTO", xmlGetProp (cur, "TYPE")) == 0 ) {
+ present = 1;
+ fprintf (lp," '%s'\n",xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+ /* now get all the CONST entries */
+ parentNode = cur->xmlChildrenNode;
+ j = 1;
+ while ((parentNode != NULL)){
+ if ((!xmlStrcmp(parentNode->name, "const"))) {
+ fprintf (lp,"\t%i. %s\n",j,xmlNodeListGetString(doc, parentNode->xmlChildrenNode, 1));
+ j ++;
+ }
+ parentNode = parentNode->next;
+ }
+ }
+ }
+ }
+ cur = cur->next;
+ }
+
+ if ( present == 0 ) {
+ fprintf (lp," - NONE - \n" );
+ }
+}
+
+void print_rast_evidence ( void ) {
+
+ int i = 0;
+ int j;
+ int present = 0;
+ xmlNodePtr cur;
+ xmlNodePtr parentNode;
+
+
+ fprintf (lp,"\nRASTER EVIDENCE:\n");
+ /* 1: print user-supplied stuff */
+ fprintf (lp,"A) USER Hypothesis SINGLETONS:\n");
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ while ((cur != NULL) ) {
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ /* check if there is a RAST evidence attached */
+ i = 0;
+ parentNode = cur->xmlChildrenNode;
+ while ((parentNode != NULL)){
+ if ((!xmlStrcmp(parentNode->name, "rast"))) {
+ i ++;
+ }
+ parentNode = parentNode->next;
+ }
+ if ( i > 0 ) {
+ /* get name of Hypothesis */
+ if ( xmlStrcmp ( "USER", xmlGetProp (cur, "TYPE")) == 0 ) {
+ present = 1;
+ fprintf (lp," '%s'\n",xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+ /* now get all the RAST entries */
+ parentNode = cur->xmlChildrenNode;
+ j = 1;
+ while ((parentNode != NULL)){
+ if ((!xmlStrcmp(parentNode->name, "rast"))) {
+ fprintf (lp,"\t%i. %s\n",j,xmlNodeListGetString(doc, parentNode->xmlChildrenNode, 1));
+ j ++;
+ }
+ parentNode = parentNode->next;
+ }
+ }
+ }
+ }
+ cur = cur->next;
+ }
+
+ if ( present == 0 ) {
+ fprintf (lp," - NONE - \n" );
+ }
+ present = 0;
+
+ /* 2: print auto-generated stuff */
+ fprintf (lp,"B) AUTO Hypothesis SETS:\n");
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ while ((cur != NULL) ) {
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ /* check if there is a RAST evidence attached */
+ i = 0;
+ parentNode = cur->xmlChildrenNode;
+ while ((parentNode != NULL)){
+ if ((!xmlStrcmp(parentNode->name, "rast"))) {
+ i ++;
+ }
+ parentNode = parentNode->next;
+ }
+ if ( i > 0 ) {
+ /* get name of Hypothesis */
+ if ( xmlStrcmp ( "AUTO", xmlGetProp (cur, "TYPE")) == 0 ) {
+ present = 1;
+ fprintf (lp," '%s'\n",xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+ /* now get all the RAST entries */
+ parentNode = cur->xmlChildrenNode;
+ j = 1;
+ while ((parentNode != NULL)){
+ if ((!xmlStrcmp(parentNode->name, "rast"))) {
+ fprintf (lp,"\t%i. %s\n",j,xmlNodeListGetString(doc, parentNode->xmlChildrenNode, 1));
+ j ++;
+ }
+ parentNode = parentNode->next;
+ }
+ }
+ }
+ }
+ cur = cur->next;
+ }
+
+ if ( present == 0 ) {
+ fprintf (lp," - NONE - \n" );
+ }
+}
+
+
+void print_vect_evidence ( void ) {
+
+ int i = 0;
+ int j;
+ int present = 0;
+ xmlNodePtr cur;
+ xmlNodePtr parentNode;
+
+
+ fprintf (lp,"\nVECTOR EVIDENCE\n");
+ /* 1: print user-supplied stuff */
+ fprintf (lp,"A) USER Hypothesis SINGLETONS:\n");
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ while ((cur != NULL) ) {
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ /* check if there is a CONST evidence attached */
+ i = 0;
+ parentNode = cur->xmlChildrenNode;
+ while ((parentNode != NULL)){
+ if ((!xmlStrcmp(parentNode->name, "vect"))) {
+ i ++;
+ }
+ parentNode = parentNode->next;
+ }
+ if ( i > 0 ) {
+ /* get name of Hypothesis */
+ if ( xmlStrcmp ( "USER", xmlGetProp (cur, "TYPE")) == 0 ) {
+ present = 1;
+ fprintf (lp," '%s'\n",xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+ /* now get all the VECT entries */
+ parentNode = cur->xmlChildrenNode;
+ j = 1;
+ while ((parentNode != NULL)){
+ if ((!xmlStrcmp(parentNode->name, "vect"))) {
+ fprintf (lp,"\t%i. %s\n",j,xmlNodeListGetString(doc, parentNode->xmlChildrenNode, 1));
+ j ++;
+ }
+ parentNode = parentNode->next;
+ }
+ }
+ }
+ }
+ cur = cur->next;
+ }
+
+ if ( present == 0 ) {
+ fprintf (lp," - NONE - \n" );
+ }
+ present = 0;
+
+ /* 2: print auto-generated stuff */
+ fprintf (lp,"B) AUTO Hypothesis SETS:\n");
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ /* parse all hypotheses nodes */
+ while ((cur != NULL) ) {
+ /* found a Hypothesis node! */
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ /* check if there is a CONST evidence attached */
+ i = 0;
+ parentNode = cur->xmlChildrenNode;
+ while ((parentNode != NULL)){
+ if ((!xmlStrcmp(parentNode->name, "vect"))) {
+ i ++;
+ }
+ parentNode = parentNode->next;
+ }
+ if ( i > 0 ) {
+ /* get name of Hypothesis */
+ if ( xmlStrcmp ( "AUTO", xmlGetProp (cur, "TYPE")) == 0 ) {
+ present = 1;
+ fprintf (lp," '%s'\n",xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+ /* now get all the VECT entries */
+ parentNode = cur->xmlChildrenNode;
+ j = 1;
+ while ((parentNode != NULL)){
+ if ((!xmlStrcmp(parentNode->name, "vect"))) {
+ fprintf (lp,"\t%i. %s\n",j,xmlNodeListGetString(doc, parentNode->xmlChildrenNode, 1));
+ j ++;
+ }
+ parentNode = parentNode->next;
+ }
+ }
+ }
+ }
+ cur = cur->next;
+ }
+
+ if ( present == 0 ) {
+ fprintf (lp," - NONE - \n" );
+ }
+}
+
+
+
+void print_groups ( void ) {
+
+ int i = 0;
+ int j = 0;
+ xmlNodePtr top;
+ xmlNodePtr cur;
+ xmlNodePtr prev;
+ xmlNodePtr hypNode;
+ xmlNodePtr evidenceNode;
+
+ fprintf (lp,"\nUSER-DEFINED GROUPS:\n");
+
+ top = xmlDocGetRootElement(doc);
+ top = top->xmlChildrenNode;
+ while ((top != NULL) ){
+ if ((!xmlStrcmp(top->name, (const xmlChar *) "grp"))) {
+ i ++;
+ fprintf (lp," %i: '%s'\n",i,xmlNodeListGetString(doc, top->xmlChildrenNode, 1));
+ /* found a group: must process whole tree for this group! */
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ j = 0;
+ while ( (cur != NULL) ) {
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ hypNode = cur->xmlChildrenNode;
+ /* check all evidence entries */
+ while ( hypNode != NULL ) {
+ if ( is_evidence ( (xmlChar*) hypNode->name) ) {
+ /* check all evidence childs */
+ evidenceNode = hypNode->xmlChildrenNode;
+ while ( evidenceNode != NULL ) {
+ /* check all assigns */
+ if ( !xmlStrcmp (evidenceNode->name, "assign") ) {
+ /* check if assignment is to current group */
+ if ( !xmlStrcmp ( (xmlChar*) xmlNodeListGetString(doc, top->xmlChildrenNode, 1),
+ (const xmlChar *)
+ xmlNodeListGetString(doc, evidenceNode->xmlChildrenNode, 1)) ) {
+ fprintf (lp,"\t'%s' = '%s'\n",
+ xmlNodeListGetString(doc, cur->xmlChildrenNode, 1),
+ xmlNodeListGetString(doc, hypNode->xmlChildrenNode, 1));
+ j = 1;
+ }
+ }
+ evidenceNode = evidenceNode->next;
+ }
+ }
+ hypNode = hypNode->next;
+ }
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ if ( j == 0 ) {
+ fprintf (lp,"\t- NONE - \n");
+ }
+ }
+ top = top->next;
+ }
+ if ( i == 0 ) {
+ /* no groups defined */
+ fprintf (lp," - NONE - \n");
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ FILE *kb;
+
+ struct GModule *module;
+ struct
+ {
+ struct Option *file;
+ struct Option *log;
+ }
+ parm;
+ struct
+ {
+ struct Flag *all;
+ }
+ flag;
+
+ /* setup some basic GIS stuff */
+ G_gisinit (argv[0]);
+ module = G_define_module ();
+ module->description = "Displays structured contents of a Dempster-Shafer knowledge base";
+
+ /* do not pause after a warning message was displayed */
+ G_sleep_on_error (0);
+
+ /* Parameters */
+ parm.file = G_define_option ();
+ parm.file->key = "file";
+ parm.file->type = TYPE_STRING;
+ parm.file->required = YES;
+ parm.file->description = "Name of the knowledge base file to display";
+
+ parm.log = G_define_option ();
+ parm.log->key = "output";
+ parm.log->type = TYPE_STRING;
+ parm.log->required = NO;
+ parm.log->description = "File to write contents to (default: display on screen)";
+
+ /* Flags */
+ flag.all = G_define_flag ();
+ flag.all->key='a';
+ flag.all->description = "Show all hypotheses (including type AUTO)";
+
+ /* parse command line */
+ if (G_parser (argc, argv))
+ {
+ exit (-1);
+ }
+
+ /* check if we have read/write access to knowledge base */
+ errno = 0;
+ kb = fopen (parm.file->answer, "r");
+ if ( kb == NULL ) {
+ G_fatal_error ("Cannot open knowledge base file for reading.\nReason: %s.", strerror (errno));
+ } else {
+ fclose(kb);
+ }
+
+ open_xml_file ( parm.file->answer );
+
+ if ( parm.log->answer != NULL ) {
+ errno = 0;
+ lp = fopen (parm.log->answer,"w+");
+ if ( lp == NULL ) {
+ G_fatal_error ("Cannot create output file for writing.\nReason: %s.", strerror (errno));
+ }
+ } else {
+ /* send output to terminal */
+ lp = stdout;
+ }
+
+ /* now output information */
+ print_header ( parm.file->answer );
+ print_hypotheses ( flag.all->answer );
+ print_const_evidence ();
+ print_rast_evidence ();
+ print_vect_evidence ();
+ print_groups ();
+
+ exit (EXIT_SUCCESS);
+}
Property changes on: grass-addons/grass6/dst/misc/m.dst.view/main.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/misc/m.filter.gen/gaussgen
===================================================================
(Binary files differ)
Property changes on: grass-addons/grass6/dst/misc/m.filter.gen/gaussgen
___________________________________________________________________
Added: svn:executable
+ *
Added: svn:mime-type
+ application/octet-stream
Added: grass-addons/grass6/dst/misc/m.filter.gen/main.c
===================================================================
--- grass-addons/grass6/dst/misc/m.filter.gen/main.c (rev 0)
+++ grass-addons/grass6/dst/misc/m.filter.gen/main.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,219 @@
+/*
+
+ PROGRAM: m.filter.gen
+ AUTHOR(S): Benjamin Ducke <benjamin.ducke AT oadigital.net>
+ PURPOSE: Outputs different types of filters for use with r.mfilter(.fp).
+
+ USAGE: Run from within GRASS GIS.
+ Use --help flag for usage instructions.
+
+ COPYRIGHT: (C) 2011 by Benjamin Ducke
+
+ This program is free software under the GNU General Public
+ License (>=v2). Read the file COPYING that comes with GRASS
+ for details.
+*/
+
+/*
+
+NOTES
+
+Produce the following types of filters:
+
+- mean (square or round)
+- gaussian
+- laplacian
+- single line with any length and orientation (destriping)
+
+Geometric operations (rotate):
+http://homepages.inf.ed.ac.uk/rbf/HIPR2/geomops.htm
+
+
+
+*/
+
+#define TYPE_MEAN 0 /* simple mean, with different shapes */
+#define TYPE_GAUSS 1 /* gaussian, fixed shape */
+#define TYPE_LAPLACE 2 /* laplacian, fixed shape */
+#define TYPE_DIRECTM 3 /* directional mean filter, definable rotation and x/y dims */
+
+#define VERSION "1.00"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <grass/gis.h>
+
+# GLOBAL VARS
+int MODE = TYPE_MEAN; /* default filter type */
+
+/* module options and flags */
+struct GModule *module;
+struct Option *type; /* filter type */
+struct Option *divisor; /* filter divisor; default=0 */
+struct Option *radiusx; /* filter radius in */
+struct Option *sigma; /* Gaussian: sigma */
+struct Option *shape; /* Mean: geometric shape of filter */
+struct Option *opt_max_dist, *output, *opt_seed, *opt_sample;
+struct Option *sites;
+struct Option *fieldopt;
+struct Option *curvature_corr;
+struct Option *spot, *offseta, *offsetb, *azimuth1, *azimuth2, *vert1, *vert2, *radius1, *radius2;
+/* parallel filtering: always use unmodified input cells
+ neighborhood to calculate new cell value */
+struct Flag *parallel;
+
+/*
+ Generates a Gaussian shape filter description.
+*/
+int gen_gauss ( int cols, int rows ) {
+ /* gauss bell variables */
+ double w[cols][rows]; /* cell weights (exact) */
+ int n; /* approximation steps in each direction from center */
+ double s; /* sigma */
+ double s2;
+ double a;
+ double sum;
+
+ /* approximated gauss bell */
+ int wi[cols][rows]; /* cell weights (integer) */
+ double min;
+ double max;
+ double m_i;
+ int sum_i;
+
+ /* looping vars */
+ int i,j,x,y;
+ double checksum;
+
+}
+
+
+int main ( int argc, char *argv[] )
+{
+
+
+ /* program options
+ int option;
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "nsteps", 1, NULL, 'n' },
+ { "sigma", 1, NULL, 's' },
+ { "mfilter", 0, NULL, 'm' },
+ { "total", 0, NULL, 't' },
+ { "integer", 0, NULL, 'i' },
+ { "help", 0, NULL, 'h' },
+ { 0, 0, 0, 0 }
+ };
+ */
+
+ /* default settings */
+ n = 2;
+ s = 1.0;
+ format_mfilter = 0;
+ print_sum = 0;
+ integer = 0;
+
+
+ /* check options */
+ if ( n < 1 ) {
+ fprintf (stderr, "ERROR: 'n' must be larger or equal than '1'.\n");
+ exit (1);
+ }
+ if ( s <= 0.0 ) {
+ fprintf (stderr, "ERROR: 's' must be larger than '0.0'.\n");
+ exit (1);
+ }
+ if ( format_mfilter && print_sum ) {
+ fprintf (stderr, "WARNING: sum total will not be printed for mfilter output.\n");
+ }
+
+ /* compute "exact" gauss bell */
+ s2 = 2 * pow ( s,2 );
+ sum = 0;
+ for ( y = -n; y <= n; y ++ ) {
+ j = y + n;
+ for ( x = -n; x <= n; x ++ ) {
+ i = x + n;
+ a = ( pow((double)x,2) + pow((double)y,2) ) / s2;
+ w[i][j] = exp (-a);
+ sum = sum + w [i][j]; /* sum of weights */
+ }
+ }
+
+ /* check for sane kernel shape */
+ checksum = 0;
+ for ( x = -n; x <= n; x ++ ) {
+ i = x + n;
+ checksum = checksum + w[i][0];
+ }
+ if ( checksum < 0.001 ) {
+ fprintf (stderr, "WARNING: Kernel dimensions too large. Sigma should be increased.\n");
+ }
+
+ if ( integer ) {
+ /* compute integer version of bell */
+ max = w[n][n];
+ min = w[0][0];
+ if ( min < 0.001 ) {
+ /* avoid division by zero problem */
+ min = 0.001;
+ }
+ m_i = round ((max / min) * 2 ); /* integer multiplication factor */
+ sum_i = 0;
+ for ( y = -n; y <= n; y ++ ) {
+ j = y + n;
+ for ( x = -n; x <= n; x ++ ) {
+ i = x + n;
+ wi[i][j] = (int) round (m_i*w[i][j]);
+ /* guard against hitting integer size limit */
+ if ( wi[i][j] < 0 ) {
+ fprintf (stderr, "ERROR: Integer overflow.\n");
+ exit (1);
+ }
+ sum_i = sum_i + wi [i][j];
+ }
+ }
+ }
+
+ /* print filter matrix */
+ if ( format_mfilter ) {
+ /* print in mfilter format */
+ fprintf ( stdout, "TITLE %ix%i Gaussian\n", (2*n+1), (2*n+1) );
+ fprintf ( stdout, "MATRIX %i\n", (2*n+1) );
+ for ( j = 0; j < (2*n+1) ; j ++ ) {
+ for ( i = 0; i < (2*n+1) ; i ++ ) {
+ if ( integer )
+ fprintf ( stdout, "%i", wi[i][j] );
+ else
+ fprintf ( stdout, "%.3f", w[i][j] );
+ if ( i < (2*n) )
+ fprintf ( stdout, " " );
+ }
+ fprintf ( stdout, "\n" );
+ }
+ fprintf ( stdout, "DIVISOR 0\n" );
+ fprintf ( stdout, "TYPE P\n" );
+ } else {
+ /* print as raw data dump */
+ for ( j = 0; j < (2*n+1) ; j ++ ) {
+ for ( i = 0; i < (2*n+1) ; i ++ ) {
+ if ( integer )
+ fprintf ( stdout, "%i\t", wi[i][j] );
+ else
+ fprintf ( stdout, "%.3f\t", w[i][j] );
+ }
+ fprintf ( stdout, "\n" );
+ }
+ if ( print_sum ) {
+ if ( integer )
+ fprintf ( stdout, "sum=%i\n", sum_i );
+ else
+ fprintf ( stdout, "sum=%.3f\n", sum );
+ }
+ }
+
+ return (0);
+}
+
Property changes on: grass-addons/grass6/dst/misc/m.filter.gen/main.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/misc/m.filter.gen/main.org
===================================================================
--- grass-addons/grass6/dst/misc/m.filter.gen/main.org (rev 0)
+++ grass-addons/grass6/dst/misc/m.filter.gen/main.org 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,244 @@
+/*
+
+ PROGRAM: m.filter.gen
+ AUTHOR(S): Benjamin Ducke <benjamin.ducke AT oadigital.net>
+ PURPOSE: Outputs different types of filters for use with r.mfilter(.fp).
+
+ USAGE: Run from within GRASS GIS.
+ Use --help flag for usage instructions.
+
+ COPYRIGHT: (C) 2011 by Benjamin Ducke
+
+ This program is free software under the GNU General Public
+ License (>=v2). Read the file COPYING that comes with GRASS
+ for details.
+*/
+
+
+#define ROWS 100
+#define COLS 100
+
+#define VERSION "1.00"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <libgen.h>
+
+void show_help ( void ) {
+ fprintf (stdout, "Usage: gaussgen [OPTION]\n");
+ fprintf (stdout, "Computes a stepwise approximation of the 2D Gaussian.\n");
+ fprintf (stdout, "\nPossible OPTIONSs are:\n");
+ fprintf (stdout, " -n, --nsteps=\t\tnumber of approximation steps (int, default: 2)\n");
+ fprintf (stdout, " -s, --sigma=\t\tdistribution sigma (double, default: 1)\n");
+ fprintf (stdout, " -m, --mfilter\t\tformat output for GRASS GIS r.mfilter\n");
+ fprintf (stdout, " -t, --total\t\talso print sum of weights\n");
+ fprintf (stdout, " -i, --integer\t\tproduce rounded integer distribution\n");
+ fprintf (stdout, " -h, --help\t\tdisplay this help and exit\n");
+ fprintf (stdout, "\nThe number of approximation steps refers to the center of the distribution \n");
+ fprintf (stdout, "and works in both directions. The default setting (2) produces a 5x5 matrix.\n");
+ fprintf (stdout, "Larger sigma settings require more steps for an accurate approximation.\n");
+ fprintf (stdout, "On the other hand, very steep kernels (small sigma) make no sense with\n");
+ fprintf (stdout, "many approximation steps (edge values will all be '0.0').");
+ fprintf (stdout, "\nExample:\n");
+ fprintf (stdout, "\tgaussgen --nsteps=3 --sigma=2.0\n");
+ fprintf (stdout, "\nThis program is free software under the GNU General Public\n");
+ fprintf (stdout, "License (>=v2). Read http://www.gnu.org/licenses/gpl.html for details");
+ fprintf (stdout, "\nVersion %s\n", VERSION);
+ exit (0);
+}
+
+int main ( int argc, char *argv[] )
+{
+
+ /* operation modes */
+ int integer;
+ int print_sum;
+ int format_mfilter;
+
+
+ /* gauss bell variables */
+ double w[COLS][ROWS]; /* cell weights (exact) */
+ int n; /* approximation steps in each direction from center */
+ double s; /* sigma */
+ double s2;
+ double a;
+ double sum;
+
+ /* approximated gauss bell */
+ int wi[COLS][ROWS]; /* cell weights (integer) */
+ double min;
+ double max;
+ double m_i;
+ int sum_i;
+
+ /* looping vars */
+ int i,j,x,y;
+ double checksum;
+
+ /* program options */
+ int option;
+ int option_index = 0;
+ static struct option long_options[] = {
+ { "nsteps", 1, NULL, 'n' },
+ { "sigma", 1, NULL, 's' },
+ { "mfilter", 0, NULL, 'm' },
+ { "total", 0, NULL, 't' },
+ { "integer", 0, NULL, 'i' },
+ { "help", 0, NULL, 'h' },
+ { 0, 0, 0, 0 }
+ };
+
+ /* default settings */
+ n = 2;
+ s = 1.0;
+ format_mfilter = 0;
+ print_sum = 0;
+ integer = 0;
+
+ /* read command line settings */
+ option = getopt_long ( argc, argv, "n:smtih", long_options, &option_index );
+ while ( option != -1 ) {
+ if ( option == '?' ) {
+ fprintf (stderr, "ERROR: Unknown option specified.\n");
+ show_help();
+ }
+
+ if ( option == ':' ) {
+ if (optopt == 'n') {
+ fprintf (stderr, "ERROR: Must specify number of steps.\n");
+ exit (1);
+ }
+ if (optopt == 's') {
+ fprintf (stderr, "ERROR: Must specify distribution sigma.\n");
+ exit (1);
+ }
+ }
+
+ /* set options */
+ if ( option == 'n' ) {
+ n = atoi ( optarg );
+ }
+ if ( option == 's' ) {
+ s = strtod ( optarg, NULL );
+ }
+ if ( option == 'm' ) {
+ format_mfilter = 1;
+ }
+ if ( option == 't' ) {
+ print_sum = 1;
+ }
+ if ( option == 'i' ) {
+ integer = 1;
+ }
+ if ( option == 'h' ) {
+ show_help();
+ }
+
+ option = getopt_long ( argc, argv, "n:s:mtih", long_options, &option_index );
+ }
+
+
+ /* check options */
+ if ( n < 1 ) {
+ fprintf (stderr, "ERROR: 'n' must be larger or equal than '1'.\n");
+ exit (1);
+ }
+ if ( s <= 0.0 ) {
+ fprintf (stderr, "ERROR: 's' must be larger than '0.0'.\n");
+ exit (1);
+ }
+ if ( format_mfilter && print_sum ) {
+ fprintf (stderr, "WARNING: sum total will not be printed for mfilter output.\n");
+ }
+
+ /* compute "exact" gauss bell */
+ s2 = 2 * pow ( s,2 );
+ sum = 0;
+ for ( y = -n; y <= n; y ++ ) {
+ j = y + n;
+ for ( x = -n; x <= n; x ++ ) {
+ i = x + n;
+ a = ( pow((double)x,2) + pow((double)y,2) ) / s2;
+ w[i][j] = exp (-a);
+ sum = sum + w [i][j]; /* sum of weights */
+ }
+ }
+
+ /* check for sane kernel shape */
+ checksum = 0;
+ for ( x = -n; x <= n; x ++ ) {
+ i = x + n;
+ checksum = checksum + w[i][0];
+ }
+ if ( checksum < 0.001 ) {
+ fprintf (stderr, "WARNING: Kernel dimensions too large. Sigma should be increased.\n");
+ }
+
+ if ( integer ) {
+ /* compute integer version of bell */
+ max = w[n][n];
+ min = w[0][0];
+ if ( min < 0.001 ) {
+ /* avoid division by zero problem */
+ min = 0.001;
+ }
+ m_i = round ((max / min) * 2 ); /* integer multiplication factor */
+ sum_i = 0;
+ for ( y = -n; y <= n; y ++ ) {
+ j = y + n;
+ for ( x = -n; x <= n; x ++ ) {
+ i = x + n;
+ wi[i][j] = (int) round (m_i*w[i][j]);
+ /* guard against hitting integer size limit */
+ if ( wi[i][j] < 0 ) {
+ fprintf (stderr, "ERROR: Integer overflow.\n");
+ exit (1);
+ }
+ sum_i = sum_i + wi [i][j];
+ }
+ }
+ }
+
+ /* print filter matrix */
+ if ( format_mfilter ) {
+ /* print in mfilter format */
+ fprintf ( stdout, "TITLE %ix%i Gaussian\n", (2*n+1), (2*n+1) );
+ fprintf ( stdout, "MATRIX %i\n", (2*n+1) );
+ for ( j = 0; j < (2*n+1) ; j ++ ) {
+ for ( i = 0; i < (2*n+1) ; i ++ ) {
+ if ( integer )
+ fprintf ( stdout, "%i", wi[i][j] );
+ else
+ fprintf ( stdout, "%.3f", w[i][j] );
+ if ( i < (2*n) )
+ fprintf ( stdout, " " );
+ }
+ fprintf ( stdout, "\n" );
+ }
+ fprintf ( stdout, "DIVISOR 0\n" );
+ fprintf ( stdout, "TYPE P\n" );
+ } else {
+ /* print as raw data dump */
+ for ( j = 0; j < (2*n+1) ; j ++ ) {
+ for ( i = 0; i < (2*n+1) ; i ++ ) {
+ if ( integer )
+ fprintf ( stdout, "%i\t", wi[i][j] );
+ else
+ fprintf ( stdout, "%.3f\t", w[i][j] );
+ }
+ fprintf ( stdout, "\n" );
+ }
+ if ( print_sum ) {
+ if ( integer )
+ fprintf ( stdout, "sum=%i\n", sum_i );
+ else
+ fprintf ( stdout, "sum=%.3f\n", sum );
+ }
+ }
+
+ return (0);
+}
+
Property changes on: grass-addons/grass6/dst/misc/m.filter.gen/main.org
___________________________________________________________________
Added: svn:executable
+ *
Added: grass-addons/grass6/dst/raster/Makefile
===================================================================
--- grass-addons/grass6/dst/raster/Makefile (rev 0)
+++ grass-addons/grass6/dst/raster/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,15 @@
+MODULE_TOPDIR = ..
+
+SUBDIRS = \
+ r.categorize \
+ r.dst.combine \
+ r.dst.predict.bpn \
+ r.dst.predict.run
+
+include $(MODULE_TOPDIR)/include/Make/Dir.make
+
+default: htmldir
+
+htmldir: subdirs
+
+clean: cleansubdirs
Added: grass-addons/grass6/dst/raster/r.categorize/Makefile
===================================================================
--- grass-addons/grass6/dst/raster/r.categorize/Makefile (rev 0)
+++ grass-addons/grass6/dst/raster/r.categorize/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,11 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.categorize
+
+GT_LIB_RAST = -lgt_raster
+LIBES = $(GISLIB) $(DATETIMELIB) $(GT_LIB_RAST)
+EXTRA_CFLAGS = -I../../include
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
Added: grass-addons/grass6/dst/raster/r.categorize/description.html
===================================================================
--- grass-addons/grass6/dst/raster/r.categorize/description.html (rev 0)
+++ grass-addons/grass6/dst/raster/r.categorize/description.html 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,145 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<TITLE>r.categorize</TITLE>
+
+<body bgcolor="white">
+
+<h2>DESCRIPTION</h2>
+
+It is often necessary to summarise a raster map's range of values using categories.
+E.g. a floating point height map with values in the range 0.00 to 300.00 metres could be represented using 5 categories and descriptive labels:
+<p>
+<PRE>
+ Cat. Range Label
+ 0 0-50 Very low
+ 1 50-100 Low
+ 2 150-200 Medium
+ 3 200-250 High
+ 4 250-300 Very High
+</PRE>
+<p>
+Integer map categories do not have a range. They are simply numbered from 0 to <em>N</em> with <em>N</em> being the highest category:
+<p>
+<PRE>
+ Cat. Label
+ 0 Sand
+ 1 Clay
+ 2 Peat Soil
+ 3 Bedrock
+ 4 Debris
+</PRE>
+<p></p>
+GRASS offers category support for both floating point and integer maps. The <EM><A HREF="../../html/r.support.html">r.support</A></EM>
+program allows the user to define and label categories interactively.
+The <em>r.categorize</em> program allows the user to automatically define and label categories using one of several categorisation modes.
+It is possible to create categories by specifying category width or number
+ and to 'clean' maps that already contain category specifications by converting all cells to NULL that do not match any category.
+Floating point maps can also be turned into categorized integer maps by rounding or truncating the cell values.
+In any case, the output map will be fully classified, meaning that each cell either matches a category or is NULL.
+Category labels are written automatically. Information about the quantification mode is stored in the output map's metadata and
+can later be retrieved using <EM><A HREF="../../html/r.info.html">r.info</A></EM>.
+
+<h3>Flags</h3>
+<dl>
+<dt><strong>-c</strong></dt>
+ <dd>Only check and report input map categories. Do not create any output.</dd>
+<dt><strong>-n</strong></dt>
+ <dd>Also report NULL cells (in conjunction with <strong>-c</strong>).</dd>
+<dt><strong>-u</strong></dt>
+ <dd>Also report uncategorized cells (in conjunction with <strong>-c</strong>).</dd>
+<dt><strong>-z</strong></dt>
+ <dd>Also report zero count cells (in conjunction with <strong>-c</strong>).</dd>
+<dt><strong>-q</strong></dt>
+ <dd>Quiet operation: do not display progress on screen.</dd>
+</dl>
+
+<h3>Parameters</h3>
+<dl>
+<dt><B>input=</B><EM>name</EM></dt>
+ <dd>Name of input raster map.</dd>
+<dt><B>output=</B><EM>name</EM></dt>
+ <dd>Name of output raster map.</dd>
+<dt><B>mode=</B><EM>name,value</EM></dt>
+ <dd>Name of categorisation mode. Some modes require an additional value. See below for details.</dd>
+<dt><B>type=</B><EM>[float|int]</EM></dt>
+ <dd>Type of output map (<var>float</var> or <var>int</var>). Defaults to type of input map.</dd>
+<dt><B>min=</B><EM>value</EM></dt>
+ <dd>Lower limit of cutting range.</dd>
+<dt><B>max=</B><EM>value</EM></dt>
+ <dd>Upper limit of cutting rang. All values in the input map outside the cutting range will be converted to NULL in the output map.</dd>
+<dt><B>logfile=</B><EM>name</EM></dt>
+ <dd>If a logfile is specified, additional information will be written to that file.</dd>
+<dt><B>precision=</B><EM>value</EM></dt>
+ <dd>Number of decimal places to print in the logfile.</dd>
+</dl>
+<h3>Categorisation Modes</h3>
+
+The following modes can be used with <em>floating point</em> input maps:
+<dl>
+<dt><strong>clean</strong></dt>
+ <dd>Keeps categories already defined in input map and convert all cells that do not match a category range to NULL.</dd>
+<dt><strong>num</strong>,<em>n</em></dt>
+ <dd>Creates <em>n</em> categories of equal width for which the ranges are determined automatically.</dd>
+<dt><strong>width</strong>,<em>n</em></dt>
+ <dd>Creates categories of width <em>n</em>. The number of categories is determined automatically. The highest category can have a different width.</dd>
+<dt><strong>rwidth</strong>,<em>n</em></dt>
+ <dd>Same as width, except that the lowest category boundary is rounded to the nearest integer. Especially nice for creating height map categories.</dd>
+<dt><strong>round</strong></dt>
+ <dd>Creates categories by rounding all cell values to nearest integer value.</dd>
+<dt><strong>trunc</strong></dt>
+ <dd>Creates categories by truncating all cell values.</dd>
+</dl>
+
+The following modes are for use with <em>integer</em> input maps:
+<dl>
+<dt><strong>clean</strong></dt>
+ <dd>Keeps categories already defined in input map and convert all cells that do not match a category range to NULL.</dd>
+<dt><strong>num</strong>,<em>n</em></dt>
+ <dd>Creates <em>n</em> categories of equal width for which the ranges are determined automatically. The highest category can have a different width.</dd>
+<dt><strong>width</strong>,<em>n</em></dt>
+ <dd>Creates categories of width <em>n</em>. The number of categories is determined automatically. The highest category can have a different width.</dd>
+<dt><strong>rescale</strong></dt>
+ <dd>Scale range of values in input map to the range 0 to <em>N</em>.</dd>
+</dl>
+
+<h2>Examples</h2>
+To clean an input floating point map of all cells whose value does not fall into any category range or whose value is > 10:
+<PRE>
+ r.categorize input=mymap output=cleanmap mode=clean max=10
+</pre>
+To create a categorized elevation map with 10 m steps and lowest value rounded:
+<PRE>
+ r.categorize input=height output=height10 mode=rwidth,10
+</pre>
+To just report on a map's category structure including counts of uncategorized and NULL data cells:
+<pre>
+ r.categorize input=mymap -cnu
+</pre>
+You can also use this module to prepare a GRASS floating point raster map for export to a bitmap. E.g., to
+create an integer map from an FP map that preserves category structure and color table, you can run ...
+<pre>
+ r.categorize input=fpmap output=bitmap -i
+</pre>
+... and convert the result to, e.g. a geotiff bitmap file using <EM><A HREF="../../html/r.out.tiff.html">r.out.tiff</A></EM>:
+<pre>
+ r.out.tiff input=bitmap output=tiffmap compression=deflate -t
+</pre>
+
+
+<h3>Notes</h3>
+This program was originally developed as part of the GRASS 5 DST Predictive Modelling Toolkit.
+<h3>SEE ALSO</h3>
+<EM><A HREF="../../html/r.cats.html">r.cats</A></EM><br>
+<EM><A HREF="../../html/r.out.tiff.html">r.out.tiff</A></EM><br>
+<EM><A HREF="../../html/r.reclass.html">r.reclass</A></EM><br>
+<EM><A HREF="../../html/r.support.html">r.support</A></EM><br>
+<EM><A HREF="../../html/r.info.html">r.info</A></EM><br>
+<EM><A HREF="../../html/r.dst.bpa.html">r.dst.bpa</A></EM><br>
+<EM><A HREF="../../html/v.report.html">v.report</A></EM>
+
+<h3>AUTHOR</h3>
+Benjamin Ducke,<br>
+University of Kiel, Germany<br>
+<i>Last changed: 2005/07/31</i>
+</body>
+</html>
Property changes on: grass-addons/grass6/dst/raster/r.categorize/description.html
___________________________________________________________________
Added: svn:mime-type
+ text/html
Added: svn:keywords
+ Author Date Id
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.categorize/main.c
===================================================================
--- grass-addons/grass6/dst/raster/r.categorize/main.c (rev 0)
+++ grass-addons/grass6/dst/raster/r.categorize/main.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,629 @@
+/* TODO: - choosable precision for printf */
+/* - test quantifications for integer maps */
+
+/* r.categorize */
+/* Purpose: quickly create a categorized CELL raster map from any input map
+ In the output CELL map, every cell will belong to a category or be NULL
+
+ Synopsis:
+ r.categorize input=<cell|fcell|dcell> [output=<cell] [mode='']
+ [min=<num>] [max=<num>] [logfile=<file>] [-cq]
+
+ Example:
+
+ r.categorize fcell_map mode=num,10 output=tmp
+
+ If run only with 'input=' parameter, program will display information
+ about categories present in the input map (if any).
+ If run with the 'output=' parameter, program will do a default operation,
+ according to the type of input map:
+ - if already categorised and no values in the map, that
+ do not have a category assigned: simply copy input to output
+ - if categorised, but some values are unassigned:
+ replace unassigned values with NULL and copy categories to output map
+ - if no categories present:
+ input map in CELL format: do a 'scale' categorisation
+ input map in FCELL/DCELL format: do a 'trunc' categorisation
+
+ If no output name is given, default name of output map will be
+ <input_map_name>.categorised.
+
+ The user can also enforce a categorisation operation on any map, by
+ specifying the "mode=" argument, which may be:
+ for CELL maps:
+ - scale
+ - width
+ - num
+ for FCELL or DCELL maps:
+ - width
+ - num
+ - round
+ - trunc
+ for FCELL and DCELL maps, the user may also specify a round=<int>
+ parameter that controls rounding of upper and lower category
+ boundaries in modes 'width' and 'num'.
+
+ Explanation of 'mode=' choices:
+
+ 'mode=' is a multiple parameter. Some modes require specification of
+ a numerical value to control the operation:
+ - width, <float> set width of categories = <float>, FCELL maps
+ - width, <int> set width of categories = <int>, CELL maps
+ - num, <int> set number of categories = <int>
+
+ If 'logfile=' is given, program output will be written to the specified
+ file instead of the screen.
+
+ If a range is specified for the input map using 'min=' and 'max=' parameters,
+ all cells with values outside this range will be written as NULL cells
+ in the output map.
+
+ If flag '-c' is given, only a checking of the input map's categories
+ will be done and the results printed out.
+ The 'q' flag disables on-screen progress display.
+*/
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+
+#include <grass/gis.h>
+#include "gt/cat_engine.h"
+
+#define PROGVERSION 0.91
+
+int skip_display = -1; /* this works together with the 'zeroskip' flag. It prevents
+ categories with zero count from being displayed in the
+ logfile or on screen. */
+
+/* dump additional information to lofile */
+void write_logfile ( FILE *printer, char *output, char *mapset, int zeroskip, int ulskip ) {
+
+ int i, cats; /* number of categories in output map */
+ char **cats_description; /* category labels */
+ long *cat_count; /* category counts */
+ long null_count; /* number of NULL cells */
+ long nocat_count; /* number of cells that do not fall into the category range [0 .. n] */
+ long total; /* for calculating percentages */
+ double percentage;
+
+ cats = GT_get_stats (output,mapset,&null_count, &nocat_count, 0);
+ if ( cats < 1 ) {
+ G_fatal_error ("Logfile: Output map '%s' has no categories (%i).", output, cats);
+ }
+ cat_count = GT_get_counts (output,mapset, 0);
+ total = 0;
+ for (i=0; i<cats; i++) {
+ total = total + cat_count[i];
+ }
+ total = total + nocat_count;
+ total = total + null_count;
+
+ cats_description = GT_get_labels (output, mapset);
+ fprintf (printer, "\nCreated map '%s@%s' with %i categories:\n", output, mapset, cats);
+ if ( !zeroskip && ulskip ) {
+ fprintf (printer, "(skipping categories with zero counts)\n");
+ }
+ if ( !ulskip && zeroskip ) {
+ fprintf (printer, "(skipping unlabeled categories)\n");
+ }
+ if ( !zeroskip && !ulskip) {
+ fprintf (printer, "(skipping categories with zero counts and unlabeled categories)\n");
+ }
+
+
+ fprintf (printer, "Cat.\tCount\t (%%) Description\n");
+ for (i=0; i<cats; i++) {
+ percentage = (double) (cat_count[i]*100) / total;
+ if ( cat_count[i] > skip_display ) {
+ if ( (strlen (cats_description[i]) > 0) && (!ulskip) ) {
+ fprintf (printer, "%i\t%8li %6.2f%% '%s'\n", i, cat_count[i],
+ percentage,cats_description[i]);
+ } else {
+ /* does user wish to also see unlabeled categories? */
+ if (ulskip) {
+ fprintf (printer, "%i\t%8li %6.2f%% '%s'\n", i, cat_count[i],
+ percentage,cats_description[i]);
+ }
+ }
+ }
+ }
+ percentage = (double) (nocat_count*100) / total;
+ fprintf (printer, "NO CAT\t%8li %6.2f%%\n", nocat_count, percentage);
+ percentage = (double) (null_count*100) / total;
+ fprintf (printer, "NULL\t%8li %6.2f%%\n", null_count, percentage);
+ fprintf (printer,"TOTAL\t%8li\n",total);
+
+ fprintf (printer,"\n Use 'r.info' on result map '%s@%s' for more info.\n",
+ output, mapset);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ struct GModule *module;
+ struct
+ {
+ struct Option *input; /* raster map to work on */
+ struct Option *output; /* output map to write */
+ struct Option *mode; /* Categorisation mode */
+ struct Option *min; /* range of values to categorise ... */
+ struct Option *max; /* .. anything outside will be NULL in output */
+ struct Option *logfile; /* log output to this file instead of stdout */
+ struct Option *precision; /* decimal digits precision for log file */
+ }
+ parm;
+ struct
+ {
+ struct Flag *check; /* only check map categories */
+ struct Flag *null; /* also count NULL values? */
+ struct Flag *uncat; /* also count uncategorised cells? */
+ struct Flag *zeroskip; /* also show cats with zero count */
+ struct Flag *ulskip; /* also show unlabeled (CELL) cats */
+ struct Flag *intout; /* force integer map output */
+ struct Flag *quiet; /* no status display on screen */
+ }
+ flag;
+
+ int i;
+ int error;
+ time_t systime;
+
+ /* these vars are used to store information about the input map */
+ int cats; /* number of categories in input map */
+ char **cats_description; /* category labels */
+ long *cat_count; /* category counts */
+ long null_count; /* number of NULL cells */
+ long nocat_count; /* number of cells that do not fall into the category range [0 .. n] */
+ double min_region; /* store min and max values of input map in current region */
+ double max_region;
+
+ /* the next two vars are used to specify a cutting range */
+ /* all values in the input map outside of [min ... max] will be */
+ /* converted to NULL values in the output map */
+ double min = 0; /* setting min and max to the same value means that .. */
+ double max = 0; /* .. no range cutting will be performed by default */
+
+ char *outfile; /* name of output map */
+ FILE *printer;
+ char *mapset;
+ int log_to_file = 0; /* output is shown on screen per default */
+ int show_progress = 1; /* enable progress display by default */
+ long total; /* for calculating percentages */
+ double percentage;
+
+ char mode[255];
+ char *numstr;
+ double num = 0;
+
+ module = G_define_module ();
+ module->description = "Creates a fully categorized CELL raster map.";
+ /* do not pause after a warning message was displayed */
+ G_sleep_on_error (0);
+
+ /* DEFINE OPTIONS AND FLAGS */
+ /* input raster map */
+ parm.input = G_define_standard_option(G_OPT_R_INPUT) ;
+ parm.input->key = "input";
+ parm.input->type = TYPE_STRING;
+ parm.input->required = YES;
+ parm.input->description = "Input raster map in CELL, FCELL or DCELL format";
+ parm.input->gisprompt = "old,cell,raster" ;
+
+ /* Output map name */
+ parm.output = G_define_standard_option(G_OPT_R_OUTPUT);
+ parm.output->key = "output";
+ parm.output->type = TYPE_DOUBLE;
+ parm.output->required = NO;
+ parm.output->description = "Output map name";
+ parm.output->gisprompt = "cell,raster" ;
+
+ /* Categorisation mode */
+ parm.mode = G_define_option ();
+ parm.mode->key = "mode";
+ parm.mode->type = TYPE_STRING;
+ parm.mode->required = NO;
+ parm.mode->description = "Categorization mode (see manual)";
+
+ /* min raster value to categorise */
+ parm.min = G_define_option ();
+ parm.min->key = "min";
+ parm.min->type = TYPE_DOUBLE;
+ parm.min->required = NO;
+ parm.min->description = "Minimum value in input map to include in categorization";
+
+ /* max raster value to categorise */
+ parm.max = G_define_option ();
+ parm.max->key = "max";
+ parm.max->type = TYPE_DOUBLE;
+ parm.max->required = NO;
+ parm.max->description = "Maximum value in input map to include in categorization";
+
+ /* optional name of logfile */
+ parm.logfile = G_define_option ();
+ parm.logfile->key = "logfile";
+ parm.logfile->type = TYPE_DOUBLE;
+ parm.logfile->required = NO;
+ parm.logfile->description = "Name of ASCII logfile, if desired";
+
+ /* optional number of decimal digitis to store in logfile/show on screen */
+ parm.precision = G_define_option ();
+ parm.precision->key = "precision";
+ parm.precision->type = TYPE_DOUBLE;
+ parm.precision->required = NO;
+ parm.precision->answer = "2";
+ parm.precision->description = "Number of decimal digits for statistics/logfile";
+
+ /* only check? */
+ flag.check = G_define_flag ();
+ flag.check->key = 'c';
+ flag.check->description = "Only check categories of input map";
+
+ /* include NULL values in count? */
+ flag.null = G_define_flag ();
+ flag.null->key = 'n';
+ flag.null->description = "Print count/percentage of NULL cells";
+
+ /* include cells w/o categories in count? */
+ flag.uncat = G_define_flag ();
+ flag.uncat->key = 'u';
+ flag.uncat->description = "Print count/percentage of uncategorized cells";
+
+ /* enable display of cats with zero count? */
+ flag.zeroskip = G_define_flag ();
+ flag.zeroskip->key = 'z';
+ flag.zeroskip->description = "Enable display of categories with zero count";
+
+ /* enable display of cats without labels? */
+ flag.ulskip = G_define_flag ();
+ flag.ulskip->key = 'l';
+ flag.ulskip->description = "Enable display of unlabeled categories";
+
+ /* force integer (CELL) output map, even if input is floating point */
+ flag.intout = G_define_flag ();
+ flag.intout->key = 'i';
+ flag.intout->description = "Force integer output, even if input is floating point";
+
+ /* quiet operation? */
+ flag.quiet = G_define_flag ();
+ flag.quiet->key = 'q';
+ flag.quiet->description = "Disable on-screen progress display";
+
+ /* setup some basic GIS stuff */
+ G_gisinit (argv[0]);
+
+ if (G_parser(argc, argv))
+ exit(-1);
+
+ /* check for 'quiet' flag */
+ if ( flag.quiet->answer ) {
+ show_progress = 0;
+ }
+
+ /* set skipping of zero counts */
+ skip_display = skip_display + (1-flag.zeroskip->answer);
+
+ /* where are we going to send output to? */
+ if ( parm.logfile->answer != NULL ) {
+ printer = fopen (parm.logfile->answer,"w+");
+ if ( printer == NULL) {
+ G_fatal_error ("Could not open logfile for write access.");
+ }
+ log_to_file = 1;
+ } else {
+ printer = stdout;
+ }
+
+ /* check if input file is available */
+ mapset = G_find_cell (parm.input->answer,"");
+ if ( mapset == NULL) {
+ G_fatal_error ("The input map %s does not exist in the current database.",parm.input->answer);
+ }
+ cats = GT_get_stats (parm.input->answer,mapset,&null_count, &nocat_count, show_progress);
+ if ( cats < 0 ) {
+ G_fatal_error ("Could not stat input map. Do you have read access?");
+ }
+
+ /* get minimum and maximum values in current region */
+ /* (we need those, anyway) */
+ error = GT_get_range (parm.input->answer,mapset,&min_region, &max_region, show_progress);
+
+ /* before we do anything else: check, if -c flag is set */
+ /* if so, just display category information and exit. */
+ /* Also, if logging to file is activated, this same information will */
+ /* be printed to the log file header */
+ if ( (flag.check->answer) || (log_to_file) ) {
+ if ( log_to_file ) { /* LOGFILE HEADER */
+ systime = time (NULL);
+ fprintf (printer, "This logfile was created by 'r.categorize', %s", ctime(&systime));
+ }
+ fprintf (printer,"\nCategory information for '%s@%s':\n", parm.input->answer, mapset);
+ if ( G_raster_map_is_fp (parm.input->answer,mapset)) {
+ fprintf (printer,"Input map is a floating point raster.\n");
+ } else {
+ fprintf (printer,"Input map is an integer raster.\n");
+ }
+ if ( cats == 0 ) {
+ fprintf (printer,"Input map has no category definitions.\n");
+ if (flag.check->answer) return (0);
+ }
+ fprintf (printer,"Range of values in current region = %.3f to %.3f.\n",
+ min_region, max_region);
+ cat_count = GT_get_counts (parm.input->answer,mapset, 0);
+ total = 0;
+ for (i=0; i<cats; i++) {
+ total = total + cat_count[i];
+ }
+ if ( flag.uncat->answer) {
+ total = total + nocat_count;
+ }
+ if ( flag.null->answer) {
+ total = total + null_count;
+ }
+ cats_description = GT_get_labels (parm.input->answer,mapset);
+ fprintf (printer, "Number of categories = %i\n", cats);
+ if ( (cats > 0) ) {
+ if ( (!flag.zeroskip->answer) && (flag.ulskip->answer) ) {
+ fprintf (printer, "(skipping categories with zero counts)\n");
+ }
+ if ( (!flag.ulskip->answer) && (flag.zeroskip->answer) ) {
+ fprintf (printer, "(skipping unlabeled categories)\n");
+ }
+ if ( (!flag.zeroskip->answer) && (!flag.ulskip->answer)) {
+ fprintf (printer, "(skipping categories with zero counts and unlabeled categories)\n");
+ }
+
+ }
+ fprintf (printer, "Cat.\tCount\t (%%) Description\n");
+ for (i=0; i<cats; i++) {
+ percentage = (double) (cat_count[i]*100) / total;
+ if ( cat_count[i] > skip_display ) {
+ /* in CELL maps, there might be unlabeled categories. Skip those. */
+ if ( (strlen (cats_description[i]) > 0) && (!flag.ulskip->answer) ) {
+ fprintf (printer, "%i\t%8li %6.2f%% '%s'\n", i, cat_count[i],
+ percentage,cats_description[i]);
+ } else {
+ /* does user wish to also see unlabeled categories? */
+ if (flag.ulskip->answer) {
+ fprintf (printer, "%i\t%8li %6.2f%% '%s'\n", i, cat_count[i],
+ percentage,cats_description[i]);
+ }
+ }
+ }
+
+ }
+ if ( flag.uncat->answer ) { /* also print uncategorised cells? */
+ percentage = (double) (nocat_count*100) / total;
+ fprintf (printer, "NO CAT\t%8li %6.2f%%\n", nocat_count, percentage);
+ }
+ if ( flag.null->answer ) { /* also print NULL cells? */
+ percentage = (double) (null_count*100) / total;
+ fprintf (printer, "NULL\t%8li %6.2f%%\n", null_count, percentage);
+ }
+
+ fprintf (printer,"TOTAL\t%8li\n",total);
+
+ /* if we are in 'check only' mode: just return number of cats and adios */
+ if (flag.check->answer) {
+ return (cats);
+ }
+ }
+
+ /* construct default output file name */
+ if ( parm.output->answer == NULL ) {
+ outfile = G_calloc ((signed) strlen(parm.input->answer)+13, sizeof(char));
+ sprintf (outfile, "%s.categorized", parm.input->answer);
+ fprintf (printer, "Result file will be written to: %s\n", outfile);
+ } else {
+ outfile = parm.output->answer;
+ }
+
+ /* check for cutting range */
+ if ( (parm.min->answer != NULL) && (parm.max->answer == NULL)) {
+ min = atof (parm.min->answer);
+ max = max_region;
+ }
+ if ( (parm.max->answer != NULL) && (parm.min->answer == NULL)) {
+ max = atof (parm.max->answer);
+ min = min_region;
+ }
+ if ( (parm.max->answer != NULL) && (parm.min->answer != NULL)) {
+ max = atof (parm.max->answer);
+ min = atof (parm.min->answer);
+ }
+
+ /* write cutting range to logfile, if needed */
+ if ( (max != min) && (log_to_file) ) {
+ fprintf (printer,"\nCUT RANGE: All values smaller than %.3f and\nlarger than %.3f in the input map will be converted to NULL\nin the output map.\n",
+ min, max);
+ }
+
+ /* set decimal digits precision for history file and category labels */
+ GT_set_decdigits ((unsigned) atoi(parm.precision->answer));
+
+ /* default operation, if no 'mode' is given or 'clean' */
+ if ( (parm.mode->answer == NULL) || (strstr (parm.mode->answer,"clean") != NULL) ) {
+ /* clean cats */
+ error = GT_set_cats_only (parm.input->answer, mapset, outfile, flag.intout->answer, show_progress);
+ switch (error) {
+ case -1: G_fatal_error ("Invalid input map format.");
+ break;
+ case -2: G_fatal_error ("Input map read error.");
+ break;
+ case -3: G_fatal_error ("Output map write error.");
+ break;
+ case -4: G_fatal_error ("Input map contains no categories.");
+ }
+ if ( log_to_file ) {
+ fprintf ( printer, "\nMode of operation = 'clean'.\n" );
+ write_logfile ( printer, outfile, mapset, flag.zeroskip->answer, flag.ulskip->answer);
+ }
+ return (0);
+ } else {
+ /* if a mode is given: tokenise option string and check */
+ /* for valid combination of 'mode' and 'num' */
+ strcpy (mode, parm.mode->answer);
+ numstr = G_strstr (mode,",");
+ if ( numstr != NULL) {
+ /* convert 'num' option to a double value */
+ numstr ++;
+ num = strtod (numstr,NULL);
+ if ( num <= 0 ) {
+ G_fatal_error ("Invalid quantifier (must be a positive value).");
+ }
+ }
+ }
+
+ /* DETERMINE MODE OF OPERATION */
+ /* ANY MAP: NUMBER OF CLASSES */
+ if ( strstr (mode,"num") != NULL ) {
+ if ( (int) num <= 1 ) {
+ G_fatal_error ("Number of categories must be an integer > 1.\n");
+ }
+ /* create new map by truncating floating point values */
+ error = GT_set_cats_num (parm.input->answer, mapset, outfile,
+ min, max, (int) num, flag.intout->answer, show_progress);
+ switch (error) {
+ case 0: G_fatal_error ("No categories could be created for output map.");
+ break;
+ case -1: G_fatal_error ("Invalid input map format.");
+ break;
+ case -2: G_fatal_error ("Input map read error.");
+ break;
+ case -3: G_fatal_error ("Output map write error.");
+ }
+ if ( log_to_file ) {
+ fprintf ( printer, "\nMode of operation = 'num'.\n" );
+ write_logfile ( printer, outfile, mapset, flag.zeroskip->answer, flag.ulskip->answer);
+ }
+ return (0);
+ }
+
+ /* ANY MAP: WIDTH OF CLASSES WITH ROUNDED LOWEST CLASS BORDER */
+ if ( strstr (mode,"rwidth") != NULL ) {
+ if ( num <= 0 ) {
+ G_fatal_error ("Category width must be > 0.\n");
+ }
+ /* create new map by truncating floating point values */
+ error = GT_set_cats_width (parm.input->answer, mapset, outfile,
+ min, max, num, 1, flag.intout->answer, show_progress);
+ switch (error) {
+ case 0: G_fatal_error ("No categories could be created for output map.");
+ break;
+ case -1: G_fatal_error ("Invalid input map format.");
+ break;
+ case -2: G_fatal_error ("Input map read error.");
+ break;
+ case -3: G_fatal_error ("Output map write error.");
+ }
+ if ( log_to_file ) {
+ fprintf ( printer, "\nMode of operation = 'rwidth'.\n" );
+ write_logfile ( printer, outfile, mapset, flag.zeroskip->answer, flag.ulskip->answer);
+ }
+ return (0);
+ }
+
+ /* ANY MAP: WIDTH OF CLASSES */
+ if ( strstr (mode,"width") != NULL ) {
+ if ( num <= 0 ) {
+ G_fatal_error ("Category width must be > 0.\n");
+ }
+ /* create new map by truncating floating point values */
+ error = GT_set_cats_width (parm.input->answer, mapset, outfile,
+ min, max, num, 0, flag.intout->answer, show_progress);
+ switch (error) {
+ case 0: G_fatal_error ("No categories could be created for output map.");
+ break;
+ case -1: G_fatal_error ("Invalid input map format.");
+ break;
+ case -2: G_fatal_error ("Input map read error.");
+ break;
+ case -3: G_fatal_error ("Output map write error.");
+ }
+ if ( log_to_file ) {
+ fprintf ( printer, "\nMode of operation = 'width'.\n" );
+ write_logfile ( printer, outfile, mapset, flag.zeroskip->answer, flag.ulskip->answer);
+ }
+ return (0);
+ }
+
+ /* FP: TRUNCATION */
+ if ( strstr (mode,"trunc") != NULL ) {
+ /* create new map by truncating floating point values */
+ error = GT_set_f_cats_trunc (parm.input->answer, mapset, outfile,
+ min, max, show_progress);
+ switch (error) {
+ case 0: G_fatal_error ("No categories could be created for output map.");
+ break;
+ case -1: G_fatal_error ("Input map must be floating point for 'trunc' mode.");
+ break;
+ case -2: G_fatal_error ("Input map read error.");
+ break;
+ case -3: G_fatal_error ("Output map write error.");
+ }
+ if ( log_to_file ) {
+ fprintf ( printer, "\nMode of operation = 'trunc'.\n" );
+ write_logfile ( printer, outfile, mapset, flag.zeroskip->answer, flag.ulskip->answer);
+ }
+ return (0);
+ }
+
+ /* FP: ROUNDING */
+ if ( strstr (mode,"round") != NULL ) {
+ /* create new map by truncating floating point values */
+ error = GT_set_f_cats_round (parm.input->answer, mapset, outfile,
+ min, max, show_progress);
+ switch (error) {
+ case 0: G_fatal_error ("No categories could be created for output map.");
+ break;
+ case -1: G_fatal_error ("Input map must be floating point for 'round' mode.");
+ break;
+ case -2: G_fatal_error ("Input map read error.");
+ break;
+ case -3: G_fatal_error ("Output map write error.");
+ }
+ if ( log_to_file ) {
+ fprintf ( printer, "\nMode of operation = 'round'.\n" );
+ write_logfile ( printer, outfile, mapset, flag.zeroskip->answer, flag.ulskip->answer);
+ }
+ return (0);
+ }
+
+ /* INT: RESCALE */
+ if ( strstr (mode,"scale") != NULL ) {
+ /* create new map by truncating floating point values */
+ error = GT_set_c_cats_scale (parm.input->answer, mapset, outfile,
+ (int) min, (int) max, show_progress);
+ switch (error) {
+ case 0: G_fatal_error ("No categories could be created for output map.");
+ break;
+ case -1: G_fatal_error ("Input must be an integer map for 'scale' mode.");
+ break;
+ case -2: G_fatal_error ("Input map read error.");
+ break;
+ case -3: G_fatal_error ("Output map write error.");
+ }
+ if ( log_to_file ) {
+ fprintf ( printer, "\nMode of operation = 'scale'.\n" );
+ write_logfile ( printer, outfile, mapset, flag.zeroskip->answer, flag.ulskip->answer);
+ }
+ return (0);
+ }
+
+ /* something has been specified for 'mode', but obviously */
+ /* nothing correct */
+ if ( parm.mode->answer != NULL ) {
+ fprintf (stderr,"'%s' is not a valid quantification mode. Choose one of:\n"
+ , parm.mode->answer);
+ fprintf (stderr,"\tscale\n\tnum,<NUM>\n\twidth,<NUM>\n\trwidth,<NUM>\n\tround\n\ttrunc\n\tclean\n");
+ G_fatal_error ("Please refer to manual page.");
+ }
+
+ return (EXIT_SUCCESS);
+}
Property changes on: grass-addons/grass6/dst/raster/r.categorize/main.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/Makefile
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/Makefile (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,13 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.dst.combine
+
+GT_LIB_RAST = -lgt_raster
+XML_LIB = `xml2-config --libs`
+XML_INC = `xml2-config --cflags`
+LIBES = $(GISLIB) $(DATETIMELIB) $(GT_LIB_RAST) $(XML_LIB)
+EXTRA_CFLAGS = $(XML_INC) -I../../include -g -Wall -pedantic -Werror-implicit-function-declaration -fno-common
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/Makefile
___________________________________________________________________
Added: svn:executable
+ *
Added: grass-addons/grass6/dst/raster/r.dst.combine/defs.h
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/defs.h (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/defs.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,119 @@
+#ifndef BOOL
+ typedef unsigned short BOOL;
+#endif
+
+#ifndef TRUE
+ #define TRUE 1
+#endif
+
+#ifndef FALSE
+ #define FALSE 0
+#endif
+
+#ifndef ON
+ #define ON 1
+#endif
+
+#ifndef OFF
+ #define OFF 0
+#endif
+
+#ifndef STATE
+ typedef BOOL STATE;
+#endif
+
+#ifndef Uint
+ typedef unsigned int Uint;
+#endif
+
+#ifndef Ushort
+ typedef unsigned short Ushort;
+#endif
+
+#ifndef Ulong
+ typedef unsigned long Ulong;
+#endif
+
+#ifndef YES
+ #define YES 1
+#endif
+
+#ifndef NO
+ #define NO 0
+#endif
+
+
+#define MALLOC_ERROR 1
+#define FILE_OPEN_ERROR 2
+
+#ifndef BIG_NUM
+ #define BIG_NUM 1000000
+#endif
+
+/* global variables (yuck!) */
+#ifdef LOCAL
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+#include <stdio.h>
+
+#define PROGVERSION 1.5
+
+#define CONST_MODE 0
+#define RAST_MODE 1
+#define VECT_MODE 2
+#define SITE_MODE 3
+
+/* possible DST values to output */
+
+#define NUMVALS 10 /* how many different DST values have we got? */
+
+#define BEL 0
+#define PL 1
+#define DOUBT 2
+#define COMMON 3
+#define BINT 4
+#define WOC 5
+#define MAXBPA 6
+#define MINBPA 7
+#define MAXSRC 8
+#define MINSRC 9
+
+/* possible warnings for combining evidence */
+#define WARN_NOT_ONE 1
+
+EXTERN int NO_SINGLETONS; /* number of singleton hypotheses in Theta */
+EXTERN int N; /* number of evidence maps to combine */
+
+EXTERN int NULL_SIGNAL; /* set to 1 to signal a copy-thru */
+
+EXTERN struct GModule *module;
+EXTERN struct
+{
+ struct Option *file;
+ struct Option *groups; /* combine all or selected groups (data sources) */
+ struct Option *type; /* type of evidence to combine */
+ struct Option *output; /* basename of output maps */
+ struct Option *vals; /* which DST metrics to output */
+ struct Option *hyps; /* which hypotheses to output */
+ struct Option *logfile; /* file to store logging output */
+ struct Option *warnings; /* name of site list to store locations of warnings */
+}
+parm;
+
+EXTERN struct
+{
+ struct Flag *norm; /* used to switch off automatic normalisation of evidence */
+ struct Flag *quiet; /* do not show progress display */
+ struct Flag *append;
+}
+flag;
+
+EXTERN FILE *lp; /* this defines where program output goes to */
+EXTERN FILE *warn; /* stores locations of warnings, if desired */
+
+EXTERN long ReadX, ReadY; /* current position to read from all raster evidence maps */
+
+EXTERN long no_assigns;
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/defs.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/description.html
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/description.html (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/description.html 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,316 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<TITLE>dst.combine</TITLE>
+
+<body bgcolor="white">
+
+<h2>DESCRIPTION</h2>
+
+This program combines evidence maps (currently GRASS floating point raster only) using <em>Dempster's
+Rule of Combination</em>.
+It is part of a general framework for Dempster-Shafer Theory (DST) modelling with GRASS GIS.<p>
+
+<h3>Introduction to the DST</h3>
+
+<font size="-1">(Note: the following is a very brief introduction to DST. Many details have been
+left out to keep everything easy to understand. If you want the full mathematical background,
+refer to one of the many excellent sources on the internet that can be found by using "Dempster Shafer
+Theory" as a search phrase. The original publication is: Shafer, G. (1976). A Mathematical Theory of Evidence.
+Princeton University Press, Princeton, New Jersey, USA.)</font><p></p>
+Consider a standard situation in GIS-based research.
+A scientist wants to build a spatial model and check its plausibility. He/she has:
+<ol>
+ <li>written down a number of <em>hypotheses</em>. These hypotheses include all possible outcomes of the model,
+ </li>
+ <li>created a number of GIS maps that encode variables (evidences) which he/she deems to be of importance for the
+model,
+ </li>
+ <li>
+ found a way to quantify the evidence.
+ </li>
+</ol>
+For each hypothesis, our scientist would now simply like to combine all supporting evidences and calculate
+the total degree of <em>belief</em> he/she can have in that hypothesis. These belief values should then
+be written to GIS maps to form a spatial model.<p></p>
+The mathematical framework to achieve this is provided by the <em>Dempster-Shafer Theory of Evidence</em> (DST).
+To clarify things, we will need to make some definitions:<p></p>
+
+<ul>
+<li>The set of hypotheses <i>H<sub>1..n</sub></i> which represent <em>all</em> possible model outcomes is called <em>Frame of Discernment</em> (FOD).</li>
+<li>A GIS map that encodes a variable with relevance to the FOD is a <em>source of evidence</em>.
+A map object (e.g. a cell in a raster map) is turned into an <em>evidence</em> through a
+<em>Basic Probability Assignment (BPA)</em>.
+</li>
+<li>A BPA is the basic quantification of evidence in the DST.
+It consists of a value <i>m<sub>n</sub></i> in the range 0 to 1 for each hypothesis in the FOD.
+The restriction is that <i>m<sub>1..n</sub></i> must sum to 1.
+</li>
+</ul>
+BPAs can be assigned to a singleton hypothesis in <i>H</i> as well as to subsets such
+as {<i>H<sub>1</sub></i>,<i>H<sub>2</sub></i>}.
+What this means is that DST has the ability to represent <em>uncertainty</em> as subsets
+of <i>H</i>.
+E.g. if two hypotheses <i>H<sub>1</sub></i>='a' and <i>H<sub>2</sub></i>='b' are supplied,
+then there will always also exist a set of hypotheses <i>A</i>={<i>H<sub>1</sub></i>,<i>H<sub>2</sub></i>}
+to represent the belief that both could be true ('a OR b').<p></p>
+Evidences from a variety of source can be combined using Dempster's Rule of Combination:
+
+<p align="center"><img src="dst.combine.001.png" alt="BPA chart"></p>
+
+In words: Dempster's Rule computes a measure of agreement between two sources of
+evidence for various (sets of) hypotheses
+in the FOD (in the formula above: <i>A</i>,<i>B</i>,<i>C</i>). It focuses on the hypotheses which both
+sources support. The resulting BPA is calculated
+by combining the BPAs of the hypotheses from both sources that yield the hypotheses of the combined
+body. The result is also normalised (denominator) to ensure that it is a valid BPA.
+From the BPAs, a number of useful DST functions can be calculated. The most important ones
+are <em>belief</em> and <em>plausibility</em>.<p>
+
+The <em>belief function Bel(H)</em> computes the total belief in a hypothesis (set) <i>A</i>.
+The total belief in <i>A</i> is the BPA mass
+of <i>A</i> itself plus the BPA mass attached to all the subsets of (<i>B</i> in the formula
+below:
+
+<p align="center"><img src="dst.combine.002.png" alt="BPA chart"></p>
+
+In words: <em>Bel(A)</em> is all the evidence that speaks in favour of <i>A</i>.<p>
+
+DST has a very important characteristic which makes it different from probability theory: if <i>Bel(H)</i>< 1, then
+the remaining evidence 1-<i>Bel(H)</i> does not necessarily refute <i>H</i> (in probability theory we would have
+<i>H<sub>2</sub></i>=1-<i>H<sub>1</sub></i> if the FOD was {<i>H</i>=<i>H<sub>1</sub></i>,<i>H<sub>2</sub></i>}).
+Thus, some of the remaining evidence might <em>plausibly</em> be assigned to (sets of) hypotheses that are subsets
+of or include <i>A</i>. This is represented by the <em>plausibility function</em>:
+
+<p align="center"><img src="dst.combine.003.png" alt="BPA chart"></p>
+
+In words: <em>Pl(A)</em> represents the maximum possible belief in <i>A</i> that could
+be achieved if there was no uncertainty at all.
+
+<h3>Program Functionality</h3>
+
+The <em>dst.combine</em> program can be used to combine evidences from different
+sources using Dempster's Rule of combination. Currently, all evidences must be
+in GRASS 5 floating point raster map format. In order to turn any raster map into
+an evidence map, the BPAs have to be calculated. The way to do this is totally
+dependent on the model design and it is left up to the user to e.g. create a
+custom <EM><A HREF="../../html/r.mapcalc.html">r.mapcalc</A></EM> script to take care of
+BPA calculations (with one exception:
+for predictive models, the <EM><A HREF="r.dst.bpa.html">r.dst.bpa</A></EM> program can be
+used).<p>
+The model layout, i.e. evidences and associated hypotheses must respect some formal
+mathematical restrictions. To take the burden of this from the user, all evidences
+and hypotheses are stored in a special XML format element called <em>
+DST knowledge base file</em> in the current working location. This file and its
+contents can
+be managed by using the <EM><A HREF="dst.update.html">dst.update</A></EM> command.<p>
+From the sources of evidence listed in the DST knowledge base file,
+one or more of the following DST functions can
+be calculated (for each hypothesis/set of hypotheses in the knowledge base file)
+and the result(s) output to a new GRASS raster map
+(all values will be in the range 0 to 1):
+
+<dl>
+<dt><b>Belief</b></dt>
+ <dd><em>Bel(A)</em> is the total belief in a hypothesis. This is the most basic DST
+ function.</dd>
+<dt><b>Plausibility</b></dt>
+ <dd><em>Pl(A)</em> is the maximum achievable belief given that there is no uncertainty.</dd>
+<dt><b>Doubt</b></dt>
+ <dd>This is simply defined as 1-<em>Pl(A)</em>.</dd>
+<dt><b>Commonality</b></dt>
+ <dd>(Definition missing).</dd>
+<dt><b>Belief Interval</b></dt>
+ <dd>Another aspect of representing uncertainty, the <em>belief interval</em> measures
+ the difference between current belief and maximum achievable belief.
+ It is defined as <em>Pl(A)-Bel(A)</em>. Areas with high values for
+ the belief interval represent "hot spots" where additional/better
+ information would improve model results.</dd>
+<dt><b>Weight of Conflict</b></dt>
+ <dd>If the <em>weight of conflict</em> is > 0 it indicates that evidences
+ from different sources disagree with each other. A high weight of
+ conflict might indicate a serious flaw in the model design or
+ disagreement of evidences supplied by different people.</dd>
+<dt><b>Maximum BPA</b></dt>
+ <dd>This gives the maximum belief mass contributed by any of the sources of evidence.</dd>
+<dt><b>Minimum BPA</b></dt>
+ <dd>This gives the minimum belief mass contributed by any of the sources of evidence.</dd>
+<dt><b>Maximum BPA source</b></dt>
+ <dd>This identifies the source of evidence by name, which has contributed the
+ highest belief mass. It is a useful tool in combination with the
+ "maximum BPA" measure.</dd>
+<dt><b>Minimum BPA source</b></dt>
+ <dd>This identifies the source of evidence by name, which has contributed the
+ lowest belief mass. It is a useful tool in combination with the
+ "minimum BPA" measure.</dd>
+</dl>
+
+<h3>DST Predictive Modelling</h3>
+
+If you have need for a flexible, raster-based spatial predictive modelling framework, DST might be
+just the right tool for you.
+In fact, this software has been developed with predictive models in mind for which the
+DST approach has a number of benefits:
+
+<ul>
+<li>Simplicity: a DST predictive model can be set up in just a few steps (as outlined below).</li>
+<li>Flexibility: DST has the ability to combine information from different sources, regardless
+ of distribution parameters.</li>
+<li>Interpretability: the functions calculated are much more meaningful than standard statistical
+ metrics.</li>
+<li>Efficiency: calculations are faster than statistical algorithms and the memory footprint will
+ always be very small, regardless of region extent and resolution.</li>
+</ul>
+
+A DST predictive model may be very simple and consist of only two hypotheses for 'site' and 'no site'
+(plus the combination of the two to represent uncertainty). It can be built like this:
+<ol>
+<li>Save your known site locations in a GRASS site list and take a random <em>sample</em> using
+<EM><A HREF="v.random.sample.html">v.random.sample</A></EM>.</li>
+<li>Convert all sources of evidence (coverage maps, buffer objects, height maps etc.) into evidence
+raster maps using <EM><A HREF="../../html/r.categorize.html">r.categorize</A></EM> and
+<EM><A HREF="r.dst.bpa.html">r.dst.bpa</A></EM> (with the random sample).</li>
+<li>Register all evidence maps and hypotheses in a DST knowledge base file using
+<EM><A HREF="dst.update.html">dst.update</A></EM> (this will automatically create all
+additional uncertainty hypotheses sets).</li>
+<li>Associate sources of evidence using <EM><A HREF="dst.source.html">dst.source</A></EM>.</li>
+<li>Combine evidence from the sources in the knowledge base using <em>dst.combine</em>.</li>
+<li>Take a look at the output maps and verify results with the <em>full</em> set of known sites
+(use <EM><A HREF="v.report.html">v.report</A></EM> for convenience).</li>
+</ol>
+</i>NEW</i> as of version 1.5: You can now use <EM><A HREF="dst.predict.html">dst.predict</A></EM>
+to create predictive models with a single, easy-to-use command!
+<p>
+A protocol of a GRASS command line session might look like this:
+<pre>
+# A predictive model of lost Maya towns in the jungle.
+# (do not take serious ;)
+
+# (point positions of known Maya towns are stored in vector map "locations")
+# take a random sample of 50%
+v.random.sample input=locations output=sample size=50
+
+# Create a digital elevation raster map from height measurements.
+# Turn into an integer map with categories 0-5m, 5-10m, etc.
+s.surf.rst input=elevations elev=height
+r.categorize input=height output=height_5m mode=width,5
+
+# Import a vector map showing jungle vegetation coverages.
+# Interactively label vegetation categories.
+v.to.rast in=vegetation output=vegetation
+r.support
+
+# Create evidence maps. The idea is that Maya towns are
+# found at certain heights and in areas with specific vegetation.
+r.dst.bpa raster=height_5m sites=sample output=bpa.height
+r.dst.bpa raster=vegetation sites=sample output=bpa.vegetation
+
+# Create new knowledge base file.
+dst.create mayatowns
+
+# Register hypotheses in a knowledge base file.
+# Attach evidences to hypotheses.
+dst.update mayatowns add=SITE
+dst.update mayatowns add=NOSITE
+dst.update mayatowns rast=bpa.height.SITE hyp=SITE
+dst.update mayatowns rast=bpa.height.NOSITE hyp=NOSITE
+dst.update mayatowns rast=bpa.height.SITE_NOSITE hyp=SITE,NOSITE
+dst.update mayatowns rast=bpa.vegetation.SITE hyp=SITE
+dst.update mayatowns rast=bpa.vegetation.NOSITE hyp=NOSITE
+dst.update mayatowns rast=bpa.vegetation.SITE_NOSITE hyp=SITE,NOSITE
+
+# Define sources of evidence.
+dst.source mayatowns add=height
+dst.source mayatowns add=vegetation
+dst.source mayatowns source=height rast=bpa.height.SITE hyp=SITE
+dst.source mayatowns source=height rast=bpa.height.NOSITE hyp=NOSITE
+dst.source mayatowns source=height rast=bpa.height.SITE_NOSITE hyp=SITE,NOSITE
+dst.source mayatowns source=vegetation rast=bpa.vegetation.SITE hyp=SITE
+dst.source mayatowns source=vegetation rast=bpa.vegetation.NOSITE hyp=NOSITE
+dst.source mayatowns source=vegetation rast=bpa.vegetation.SITE_NOSITE hyp=SITE,NOSITE
+
+# Combine sources of evidence and output belief maps
+# for all hypotheses.
+dst.combine mayatowns sources=height,vegetation output=dst.mayatown
+
+# Compare with the full set of sites to see how well the
+# model does (most of the sites should fall into cells
+# with high belief values for "SITE").
+v.report map=dst.mayatown.SITE.bel sites=locations
+
+</pre>
+
+
+
+<h3>Flags</h3>
+<dl>
+<dt><B>-a</b></dt>
+ <dd>Append log output to existing ASCII file.</dd>
+<dt><B>-q</b></dt>
+ <dd>Quiet operation: do not display progress on screen.</dd>
+<dt><B>-n</b></dt>
+ <dd>Turn off normalisation and signal a warning if evidence does not sum to 1. Per default, the
+ program will normalise evidences to force all evidences to have the same weight and
+ ensure that the results will be in the range 0 to 1. You can turn this off if you want
+ to check for potential errors in your own BPA assignments.</dd>
+</dl>
+
+<h3>Parameters</h3>
+<dl>
+<dt><B>file=</B><EM>name</EM></dt>
+ <dd>Name of DST knowledge base file to use. You can get a listing of DST
+ knowledge base files in your current mapset by invoking
+ <EM><A HREF="dst.list.html">dst.list </A></EM>.</dd>
+<dt><B>sources=</B><EM>name,[name,...]</EM></dt>
+ <dd>Specify which sources of evidence in the knowledge base file to combine. The
+ default is all sources.</dd>
+<dt><B>type=</B><EM>name</EM></dt>
+ <dd>Select what type of evidence to combine. This refers to the GIS data format in which
+ the evidence is stored. Currently only 'rast' is a valid choice and also the default.</dd>
+<dt><B>output=</B><EM>name</EM></dt>
+ <dd>Basename of all output maps. This is set to the name of the current location by default
+ and will be suffixed with [hypothesis].[value] (see below).</dd>
+<dt><B>hypotheses=</B><EM>name,[name,...]</EM></dt>
+ <dd>Choose for which hypotheses the DST values (see below) should be calculated. The default
+ is all (including the NULL hypothesis). NOTE: if you want to specify hypotheses sets, you
+ must enclose this parameter in double quotes and all set names in "set brackets"! E.g:
+ hypotheses="a,b,c,{a,c},{a,b,c}". Be sure to use the correct element order when specifying
+ sets.</dd>
+<dt><B>values=</B><EM>name,[name,...]</EM></dt>
+ <dd>Valid choices are: bel,pl,doubt,common,bint,woc. See section on "Program functionality"
+ for a description. The default is to calculate only belief (bel) values. </dd>
+<dt><B>logfile=</B><EM>name</EM></dt>
+ <dd>Specfiy a valid file name if you want a full log of the calculations.</dd>
+
+
+<h3>Notes</h3>
+This program was developed as part of the GRASS 5 DST Predictive Modelling Toolkit.<br>
+A big "Thank You!" goes to Gavin Powell, 3d Vision and Geometry, Dept of Computer Science,
+Cardiff University, for the DST core routines
+used in this program, help and advise and his permission to publish his code as part
+of a GPL'd software.<br>
+A lot of the information in this document was also taken from the work of Mounia Lalmas
+et al. on information retrieval from structured documents using DST.<br>
+The term 'knowledge base file' was first used in the manual of the
+<A HREF="www.clarklabs.org" target="_blank"> IDRISI GIS </A> software which also offers some DST functionality.<br>
+GIS-based predictive modelling using belief values is also discussed in a paper by
+<a href="http://gis.esri.com/library/userconf/proc99/proceed/papers/pap295/p295.htm" target="_blank">
+ Eric J. Lorup </a> and another one by <a href="http://websrv5.sdu.dk/ejstrud/forskning.html" target="_blank">
+Bo Ejstrud</a>.
+<h3>SEE ALSO</h3>
+<EM><A HREF="dst.predict.html">dst.predict</A></EM><br>
+<EM><A HREF="dst.source.html">dst.source</A></EM><br>
+<EM><A HREF="dst.update.html">dst.update</A></EM><br>
+<EM><A HREF="../../html/r.categorize.html">r.categorize</A></EM><br>
+<EM><A HREF="r.dst.bpa.html">r.dst.bpa</A></EM><br>
+<EM><A HREF="../../html/r.mapcalc.html">r.mapcalc</A></EM><br>
+<EM><A HREF="../../html/v.random.sample.html">v.random.sample</A></EM><br>
+<EM><A HREF="../../html/v.report.html">v.report</A></EM><br>
+<h3>AUTHORS</h3>
+Benjamin Ducke,<br>
+University of Bamberg, Germany<br>
+Gavin Powell,<br>
+3d Vision and Geometry, Dept of Computer Science,<br>
+Cardiff University<p></p>
+<i>Last changed: 2005/02/20</i>
+</body>
+</html>
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/description.html
___________________________________________________________________
Added: svn:mime-type
+ text/html
Added: svn:keywords
+ Author Date Id
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/dst.c
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/dst.c (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/dst.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,363 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "structs.h"
+#include "dst.h"
+#include "print.h"
+#include "sets.h"
+#include "garbage.h"
+
+int times_called = 0;
+
+/* the following functions retrieve DST values from a frame */
+/* hyp is an index from 0 to no_sets-1 */
+double get_bel (Shypothesis *frame, int hyp) {
+ return (frame[hyp].bel);
+}
+
+double get_pl (Shypothesis *frame, int hyp) {
+ return (frame[hyp].pl);
+}
+
+double get_bint (Shypothesis *frame, int hyp) {
+ return (frame[hyp].bint);
+}
+
+double get_doubt (Shypothesis *frame, int hyp) {
+ return (frame[hyp].doubt);
+}
+
+double get_common (Shypothesis *frame, int hyp) {
+ return (frame[hyp].common);
+}
+
+double get_bpn (Shypothesis *frame, int hyp) {
+ return (frame[hyp].bpn);
+}
+
+double get_minbpn (Shypothesis *frame, int hyp) {
+ return (frame[hyp].minbpn);
+}
+
+double get_maxbpn (Shypothesis *frame, int hyp) {
+ return (frame[hyp].maxbpn);
+}
+
+int get_minbpnev (Shypothesis *frame, int hyp) {
+ return (frame[hyp].minbpnev);
+}
+
+int get_maxbpnev (Shypothesis *frame, int hyp) {
+ return (frame[hyp].maxbpnev);
+}
+
+int get_isNull (Shypothesis *frame, int hyp) {
+ return (frame[hyp].isNull);
+}
+
+
+
+
+/*=====================================================
+ combine 2 sets of evidence (frames of discernment
+ memory of original frames is NOT free'd
+=====================================================*/
+/* returns the Weight of Conflict */
+/* WOC is a measure of agreement between to frames */
+/* the closer it is to 0, the less disagreement of evidence */
+/* there is. */
+double combine_bpn(Shypothesis *frame1, Shypothesis *frame2, BOOL **garbage, int MODE)
+{
+ Uint A, B, C, no_of_sets, i;
+ double empty_set_bpn;
+ Shypothesis *combined_frames;
+ Shypothesis intersectionSet;
+ double woc;
+ struct Cell_head region;
+
+ G_get_window (®ion);
+ no_of_sets = (Uint) pow((float) 2, (float) NO_SINGLETONS);
+
+ /** set up the initial frame of discernment **/
+ combined_frames = frame_discernment( garbage );
+
+ for(A=0; A<no_of_sets; A++) /** check that frames are combinable **/
+ for(B=0; B<no_of_sets; B++)
+ for(C=0; C<no_of_sets; C++) {
+ intersectionSet = set_intersection(frame1[B], frame2[C]);
+ if(set_equal(intersectionSet, combined_frames[A])) {
+ combined_frames[A].bpn += (frame1[B].bpn * frame2[C].bpn);
+ }
+ G_free (intersectionSet.type);
+ }
+
+ if(combined_frames[0].bpn >= 1)
+ {
+ if ( MODE == CONST_MODE ) {
+ G_warning ("Sets do not combine to < 1 (%.5f).\n",combined_frames[0].bpn);
+ }
+ if ( MODE == RAST_MODE ) {
+ G_warning ("Sets do not combine to < 1 (%.5f) at %.2f, %.2f.\n",
+ combined_frames[0].bpn,
+ G_col_to_easting ((double) ReadX,®ion),
+ G_row_to_northing ((double) ReadY,®ion));
+ fprintf (lp,"%.2f\t%.2f\tWARNING %i: Sets do not combine to < 1 (%.5f)\n",
+ G_col_to_easting ((double) ReadX,®ion),
+ G_row_to_northing ((double) ReadY,®ion),
+ WARN_NOT_ONE,
+ combined_frames[0].bpn );
+ if ( warn != NULL ) {
+ /* user wants to store coordinates of problems in a site file */
+ }
+ }
+ }
+
+ /** weight by the empty set total **/
+ /* the weighting measure (1-empty set) shows how much conflict */
+ /* there is between the pieces of evidence */
+ empty_set_bpn = combined_frames[0].bpn;
+ /* woc = fabs (log10 (1-empty_set_bpn)); */
+
+ for(A=0; A<no_of_sets; A++)
+ combined_frames[A].bpn /= (1 - empty_set_bpn); /** empty set is at [0] **/
+
+ /** This way is easier for combining (this func) lots of data sets within a loop **/
+ /** if you want to change it just return the 'combined_frames' and don't free, obviously **/
+ for(i=0;i<no_of_sets;i++) /** swap the combined set back to frame1 of the arg **/
+ frame1[i] = combined_frames[i];
+ /** empty_set_bpn is the weight of conflict 'k' **/
+ woc = (empty_set_bpn);
+ /** reset the empty set to 0 so it doesn't go into the next one when the func is called in loops**/
+ frame1[0].bpn = 0;
+
+ G_free (combined_frames);
+
+ /* UPDATE GLOBAL MIN AND MAX */
+ if (woc > WOC_MAX) {
+ WOC_MAX=woc;
+ }
+ if (woc < WOC_MIN) {
+ WOC_MIN=woc;
+ }
+
+ return (woc);
+}
+
+/*===========================================================
+ set the beliefs in a frame of discernment from the bpn's
+===========================================================*/
+/* Calculate Belief value */
+
+void set_beliefs(Shypothesis *frame)
+{
+ Uint B, no_of_sets, A;
+ double *temp;
+
+ no_of_sets = (Uint) pow((float) 2, (float) NO_SINGLETONS);
+
+ /** sets all to zero **/
+ temp = (double*) G_calloc ((unsigned) no_of_sets, sizeof(double));
+
+ for(A=0; A<no_of_sets; A++)
+ for(B=0; B<no_of_sets; B++) /** empty set is always first in frame of discernment **/
+ if(subset(frame[B], frame[A]))
+ temp[A] += frame[B].bpn;
+
+ /** swap values to the frame **/
+ for(A=0; A<no_of_sets; A++)
+ frame[A].bel = temp[A];
+
+ G_free(temp);
+}
+
+/* calculate commonality */
+/* commonality(A) = summed bpns for all (subset (A,B)) */
+void set_commonalities (Shypothesis *frame)
+{
+ Uint B, no_of_sets, A;
+
+ no_of_sets = (Uint) pow((float) 2, (float) NO_SINGLETONS);
+
+ for(A=0; A<no_of_sets; A++)
+ for(B=0; B<no_of_sets; B++) /** empty set is always first in frame of discernment **/
+ if(subset(frame[B], frame[A]))
+ frame[B].common += frame[A].bpn;
+}
+
+/* calculate Belief Interval */
+/* This acts as a measure of uncertainty ! */
+/* Bel and Pl have to be calculated prior to calculating BInt */
+void set_bint (Shypothesis *frame)
+{
+ Uint B, no_of_sets, A;
+
+ B = 0;
+ no_of_sets = (Uint) pow((float) 2, (float) NO_SINGLETONS);
+
+ for(A=0; A<no_of_sets; A++)
+ for(B=0; B<no_of_sets; B++) /** empty set is always first in frame of discernment **/
+ frame[B].bint = fabs (frame[B].pl - frame[B].bel);
+
+}
+
+/*===================================================================
+ set the plausibilities in the frame of discernment from the bpn's
+===================================================================*/
+
+void set_plausibilities(Shypothesis *frame)
+{
+ Uint B, no_of_sets, A;
+ double *temp;
+ Shypothesis emptySet;
+ Shypothesis intersectionSet;
+
+ no_of_sets = (Uint) pow((float) 2, (float) NO_SINGLETONS);
+
+ temp = (double*) G_calloc ((unsigned) no_of_sets, sizeof(double));
+
+ emptySet = empty_set();
+
+ for(A=0; A<no_of_sets; A++)
+ for(B=0; B<no_of_sets; B++) {
+ intersectionSet = set_intersection(frame[B], frame[A]);
+ if(!set_equal(intersectionSet, emptySet))
+ temp[A] += frame[B].bpn;
+ G_free (intersectionSet.type);
+ }
+
+ /** swap values to the frame **/
+ for(A=0; A<no_of_sets; A++)
+ frame[A].pl = fabs (temp[A]);
+
+
+ G_free (emptySet.type);
+ G_free(temp);
+}
+
+/* calculate commonality */
+/* doubt(A) = 1-Pl(A) */
+void set_doubts (Shypothesis *frame)
+{
+ Uint B, no_of_sets, A;
+ double *temp;
+ Shypothesis emptySet;
+ Shypothesis intersectionSet;
+
+ no_of_sets = (Uint) pow((float) 2, (float) NO_SINGLETONS);
+
+ temp = (double*) G_calloc ((unsigned) no_of_sets, sizeof(double));
+
+ emptySet = empty_set();
+
+ for(A=0; A<no_of_sets; A++)
+ for(B=0; B<no_of_sets; B++) {
+ intersectionSet = set_intersection(frame[B], frame[A]);
+ if(!set_equal(intersectionSet, emptySet))
+ temp[A] += frame[B].bpn;
+ G_free (intersectionSet.type);
+ }
+
+ /** swap values to the frame **/
+ for(A=0; A<no_of_sets; A++)
+ frame[A].doubt = fabs (1-temp[A]);
+
+ G_free (emptySet.type);
+ G_free(temp);
+}
+
+
+/*==============================================================
+ total the bpns in a frame of discernment, for error checking
+==============================================================*/
+
+double get_bpn_sum(Shypothesis *frame)
+{
+ Uint set, no_of_sets;
+ double bpn_total=0;
+
+ no_of_sets = (Uint) pow((float) 2, (float) NO_SINGLETONS);
+
+ for(set=0;set<no_of_sets; set++)
+ bpn_total += frame[set].bpn;
+
+ return( fabs (bpn_total) );
+}
+
+
+/*=====================================================================
+ create a frame of discernment given the no of singleton hypothesis.
+ relate to types in def.h
+ Memory must be free'd by caller!
+=====================================================================*/
+
+Shypothesis* frame_discernment( BOOL **garbage )
+{
+ Shypothesis *frame;
+ Uint x, no_of_sets, set, i;
+ Ushort *counter;
+ long offset, max_offset;
+
+ no_of_sets = (Uint) pow((float) 2, (float) NO_SINGLETONS);
+
+ offset = no_of_sets * times_called;
+ max_offset = N+(N-1);
+ times_called ++;
+ if (times_called == max_offset ) {
+ times_called = 0;
+ }
+
+ frame = (Shypothesis*) G_malloc ((unsigned) no_of_sets * (signed) sizeof(Shypothesis));
+ counter = (Ushort*) G_malloc ((unsigned) NO_SINGLETONS * (signed) sizeof(Ushort));
+
+ /** init counter array */
+ for(x=0;x<NO_SINGLETONS;x++)
+ counter[x] = TRUE;
+
+ for(set=0;set<no_of_sets;set++)
+ {
+ /* set the binary states in the counter representing the on/off
+ of each type in the hypothesis */
+ for(x=0;x<NO_SINGLETONS;x++)
+ {
+ if(counter[x] == FALSE)
+ {
+ counter[x] = TRUE;
+ break;
+ }
+ else
+ counter[x] = FALSE;
+ }
+ /* transfer the binary states to the frame of discernment, and
+ init values */
+ frame[set].type = (BOOL*) G_malloc((unsigned) NO_SINGLETONS * (signed) sizeof(BOOL));
+ for(i=0;i<NO_SINGLETONS;i++) {
+ frame[set].type[i] = counter[i];
+ }
+ /* keep pointers in a BOOL array to free later */
+ garbage_throw (garbage, (signed)offset + (signed) set, frame[set].type);
+
+ no_assigns ++;
+ frame[set].pl = 0;
+ frame[set].bel = 0;
+ frame[set].bpn = 0;
+ frame[set].common = 0;
+ frame[set].doubt = 0;
+ }
+ G_free(counter);
+
+ return frame;
+}
+
+
+/** return an empty set **/
+Shypothesis empty_set(void)
+{
+ Shypothesis empty_set;
+ int i;
+
+ empty_set.type = (BOOL*) G_malloc((unsigned) NO_SINGLETONS * (signed) sizeof(BOOL));
+ for ( i = 0; i < NO_SINGLETONS; i++)
+ empty_set.type[i] = FALSE;
+ return empty_set;
+}
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/dst.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/dst.combine.001.png
===================================================================
(Binary files differ)
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/dst.combine.001.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Added: grass-addons/grass6/dst/raster/r.dst.combine/dst.combine.002.png
===================================================================
(Binary files differ)
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/dst.combine.002.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Added: grass-addons/grass6/dst/raster/r.dst.combine/dst.combine.003.png
===================================================================
(Binary files differ)
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/dst.combine.003.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Added: grass-addons/grass6/dst/raster/r.dst.combine/dst.h
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/dst.h (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/dst.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,22 @@
+void set_beliefs(Shypothesis *frame);
+void set_plausibilities(Shypothesis *frame);
+void set_commonalities (Shypothesis *frame);
+void set_bint (Shypothesis *frame);
+void set_doubts (Shypothesis *frame);
+Shypothesis* frame_discernment( BOOL **garbage );
+double get_bpn_sum(Shypothesis *frame);
+double combine_bpn(Shypothesis *frame1, Shypothesis *frame2, BOOL **garbage, int MODE);
+void get_frame_bpn(Shypothesis *frame);
+Shypothesis empty_set(void);
+
+double get_bel (Shypothesis *frame, int hyp);
+double get_pl (Shypothesis *frame, int hyp);
+double get_bint (Shypothesis *frame, int hyp);
+double get_doubt (Shypothesis *frame, int hyp);
+double get_common (Shypothesis *frame, int hyp);
+double get_bpn (Shypothesis *frame, int hyp);
+double get_minbpn (Shypothesis *frame, int hyp);
+double get_maxbpn (Shypothesis *frame, int hyp);
+int get_minbpnev (Shypothesis *frame, int hyp);
+int get_maxbpnev (Shypothesis *frame, int hyp);
+int get_isNull (Shypothesis *frame, int hyp);
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/dst.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/file_io.c
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/file_io.c (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/file_io.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,482 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#include <grass/gis.h>
+
+#include "structs.h"
+#include "file_io.h"
+#include "dst.h"
+
+
+#define MAX_XML_PATH_LENGTH 4096
+
+/* global XML vars */
+int first_allocation = 1;
+DCELL *dcell_buf;
+
+
+/*
+ This starts the XML parser at 'doc' which is an xmlDocPtr that must not have
+ have been allocated by the caller.
+
+ This also sets the number of singleton hyps and groups found in the
+ knowledge base file.
+
+*/
+xmlDocPtr stat_XML (char *file, int *no_singletons, int *n ) {
+
+ xmlDocPtr root;
+ xmlNodePtr cur;
+ int check;
+ char *xmlfile;
+
+ xmlfile = G_malloc ( MAX_XML_PATH_LENGTH * sizeof (char) );
+
+ check = snprintf ( xmlfile, MAX_XML_PATH_LENGTH, "%s/%s/DST/%s",G_location_path(),G_mapset(),file );
+ if ( check >= MAX_XML_PATH_LENGTH ) {
+ G_fatal_error ("XML path too long. Output truncated.\n");
+ }
+
+ root = xmlParseFile (xmlfile);
+ if ( root == NULL ) {
+ xmlFreeDoc(root);
+ G_fatal_error ("Could not parse XML structure of knowledge base!\n");
+ }
+
+ cur = xmlDocGetRootElement(root);
+ if (cur == NULL) {
+ xmlFreeDoc(root);
+ G_fatal_error ("Knowledge base is an empty file!\n");
+ }
+
+ if (xmlStrcmp(cur->name, (const xmlChar *) "dst-kb")) {
+ xmlFreeDoc(root);
+ G_fatal_error ("File is not a DST knowledge base!\n");
+ }
+
+ *no_singletons = atoi ((char*) xmlGetProp(cur, (xmlChar*) "N_SINGLETONS"));
+ *n = atoi ((char*) xmlGetProp(cur, (xmlChar*) "N_GROUPS"));
+
+ G_free ( xmlfile);
+
+ return ( root );
+}
+
+
+
+/*
+ This returns an array of group names found in the XML file. Again, memory
+ for this must not be allocated by the caller.
+
+ n must be set to the number of groups in the XML file; run stat_XML first to know this value!
+
+*/
+char **get_groups_XML ( int n, xmlDocPtr doc ) {
+
+ xmlNodePtr cur;
+ int i;
+ char **groups;
+
+ /* allocate memory to store group names */
+ groups = (char**) G_malloc ( sizeof (char*) * n);
+
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ i = 0;
+ while ( cur != NULL ) {
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "grp"))) {
+ groups[i] = (char*) G_malloc ( sizeof (char) * (strlen ((char*) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) + 1) );
+ strcpy (groups[i],(char*) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+ i ++;
+ }
+ cur=cur->next;
+ }
+
+ if ( i != n ) {
+ G_fatal_error ("XML file corruption. Please run m.dst.check on this file.\n");
+ }
+
+ return ( groups );
+}
+
+
+
+
+/* read names of all hypotheses in a knowledge base into a char array */
+/* number of names in array is written to *no_all_hyps */
+char **get_hyp_names_XML ( int *no_all_hyps, xmlDocPtr doc) {
+
+ xmlNodePtr cur;
+ char **hyps;
+ int no_sets, i;
+
+ cur = xmlDocGetRootElement(doc);
+
+ no_sets = atoi ((char*) xmlGetProp(cur, (xmlChar*) "N_HYPOTHESES"));
+ *no_all_hyps = no_sets;
+
+ /* allocate memory and store hyp names */
+ hyps = (char**) G_malloc (sizeof (char*) * no_sets);
+
+ cur = cur->xmlChildrenNode;
+ i = 0;
+ while ( cur != NULL ) {
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ hyps[i] = (char*) G_malloc ( sizeof (char) * (strlen ((char*)cur->name) ) + 1 );
+ hyps[i] = strdup ((char*) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+ i ++;
+ }
+ cur=cur->next;
+ }
+
+ return (hyps);
+}
+
+
+/* Retrieve sample bpns from XML knowledge base file */
+/* A bpn can be a probability assignment, but does not */
+/* necessarily have to be one (could also be, eg. a ranking score) */
+/* i.e. any measure of subjective believe in the truth of an evidence */
+/* all lines added together must equal "1" */
+/* This can always be achieved by simply normalising the evidence */
+/* The sample file is read in a specific order. */
+/* That order is determined by a simple algorithm: */
+/* 1. list = empty set
+ 2. add next singleton from file to list. EXIT on EOF
+ 3. try if a subset not currently on the list can
+ be build using the available singletons (w/o the empty set).
+ YES: build subset, add to list and GOTO 3
+ NO: GOTO 2
+*/
+/* I.E.: DST needs a Frame of Decision that constitutes a COMPLETE
+ universe of ALL POSSIBLE combinations and their hierarchical
+ combinations */
+
+/* e.g. for Omega = {a, b, c}
+{0} (empty set)
+{a}
+{b}
+{a, b}
+{c}
+{a, c}
+{b, c}
+{a, b, c}
+*/
+/* in real applications, the bpn for {0} should always be */
+/* zero, so that the remaining hypotheses form the COMPLETE */
+/* set of all possible outcomes */
+/* according to DST rules, {a}*{b} does not have to be equal */
+/* to {a,b}! */
+/* all SINGLETON hypotheses, however ({a},{b},{c]), MUST be */
+/* mutually exclusive! */
+
+/* get all groups with CONST evidence from XML knowledge base */
+/* file and store evidence as Shypothesis */
+
+/* TODO: CHECK if const evidence really exists for this group! */
+Shypothesis *get_const_samples_XML ( char* group, int norm, BOOL **garbage, xmlDocPtr doc ) {
+
+ xmlNodePtr cur, hypNode, evidenceNode;
+ Shypothesis *sample;
+ unsigned int no_sets, i;
+ int k;
+ double total;
+
+ no_sets = (Uint) pow((float) 2, (float) NO_SINGLETONS);
+
+ sample = frame_discernment( garbage );
+
+ cur = xmlDocGetRootElement(doc);
+ cur = cur->xmlChildrenNode;
+ i = 0;
+ k = -1; /* position to insert bpa in Omega, set to -1 to discount NULL Hyp */
+ sample[0].bpn = 0; /* NULL hypothesis is always = 0 ! */
+ while ( (cur != NULL) ) {
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ k ++;
+ hypNode = cur->xmlChildrenNode;
+ /* check all evidence entries */
+ while ( hypNode != NULL ) {
+ if ( !strcmp ( (char*) hypNode->name , "const" ) ) {
+ /* check all evidence childs */
+ evidenceNode = hypNode->xmlChildrenNode;
+ while ( evidenceNode != NULL ) {
+ /* check all assigns */
+ if ( !xmlStrcmp (evidenceNode->name, (xmlChar*)"assign") ) {
+ /* check if assignment is to current group */
+ if ( !xmlStrcmp ( (xmlChar*) group, (const xmlChar *)
+ xmlNodeListGetString(doc, evidenceNode->xmlChildrenNode, 1)) ) {
+ i = 1; /* signal that an assignment has been made */
+ sample[k].bpn = atof
+ ((char*)xmlNodeListGetString(doc, hypNode->xmlChildrenNode, 1));
+ if (sample[k].bpn < 0) {
+ G_fatal_error ("Negative bpn! Please check your data using m.dst.check.\n");
+ }
+ }
+ }
+ evidenceNode = evidenceNode->next;
+ if ( i == 0 ) { /* no assignment for this hyp, so set to 0! */
+ sample[k].bpn = 0;
+ i = 0;
+ }
+ }
+ }
+ hypNode = hypNode->next;
+ }
+ }
+ cur = cur->next;
+ }
+
+
+ /* normalise sample */
+ total = 0;
+ for (i=0; i < no_sets; i++) {
+ total = total + sample[i].bpn;
+ }
+ if ( norm ) {
+ for (i=0; i < no_sets; i++) {
+ sample[i].bpn = sample[i].bpn / total;
+ }
+ }
+
+
+ /* user has not given any evidence for this group! */
+ if ( total == 0 ) {
+ G_fatal_error ("Evidence sums to 0! Please check your data with m.dst.check.\n");
+ }
+
+ /* if normalisation is turned off, we must check that evidence sums to 1 */
+ if ( !norm ) {
+ total = 0;
+ for (i=0; i < no_sets; i++) {
+ total = total + sample[i].bpn;
+ }
+ /* sample needs normalisation */
+ if ( total != 1 ) {
+ G_fatal_error ("Evidence does not sum to 1! Normalisation required.\n");
+ }
+ }
+
+ return ( sample );
+}
+
+/* open all raster evidence maps for reading
+ has to be called before get_rast_samples_XML can return anything
+ useful!
+
+ This returns an array of file pointers to handle all the raster maps.
+
+*/
+
+Sfp_struct* test_rast_XML ( char **groups, xmlDocPtr doc ) {
+
+ xmlNodePtr root, cur, hypNode, evidenceNode;
+ int i, k;
+ int no_sets;
+ Sfp_struct* file_pointers;
+
+ root = xmlDocGetRootElement(doc);
+ cur = root->xmlChildrenNode;
+
+ /* create file pointer structs for all groups */
+ no_sets = (int) pow((float) 2, (float) NO_SINGLETONS);
+ file_pointers = (Sfp_struct*) G_malloc (sizeof (Sfp_struct) * N+1); /* STRANGE: why does this have to be N+1? Obviously, the size of this struct is not correctly calculated! */
+ for (i=0; i<N; i++) {
+ file_pointers[i].fp = (int*) G_malloc (sizeof (int) * no_sets);
+ file_pointers[i].filename = (char**) G_malloc (sizeof (char*) * no_sets);
+ for (k=0; k< no_sets; k++) {
+ file_pointers[i].fp[k] = -1;
+ file_pointers[i].filename[k] = NULL;
+ }
+ }
+
+ k = -1;
+ while ( (cur != NULL) ) {
+ if ((!xmlStrcmp(cur->name, (const xmlChar *) "hyp"))) {
+ k ++;
+ hypNode = cur->xmlChildrenNode;
+ /* check all evidence entries */
+ while ( hypNode != NULL ) {
+ if ( !strcmp ( (char*) hypNode->name , "rast" ) ) {
+ /* check all evidence childs */
+ evidenceNode = hypNode->xmlChildrenNode;
+ while ( evidenceNode != NULL ) {
+ /* check all assigns */
+ if ( !xmlStrcmp (evidenceNode->name, (xmlChar*)"assign") ) {
+ /* check if assignment is to one of the groups */
+ for ( i=0; i<N; i++ ) {
+ if ( !xmlStrcmp ( (xmlChar*) groups[i], (const xmlChar *)
+ xmlNodeListGetString(doc, evidenceNode->xmlChildrenNode, 1)) ) {
+ /* attempt to open raster map and alloc file pointer */
+ if ( G_find_cell ( (char*) xmlNodeListGetString(doc, hypNode->xmlChildrenNode, 1),
+ "") == NULL ) {
+ G_fatal_error ("Raster evidence map '%s' not found in search path.",
+ (char*) xmlNodeListGetString
+ (doc, hypNode->xmlChildrenNode, 1));
+ }
+
+ file_pointers[i].fp[k] = G_open_cell_old ((char*) xmlNodeListGetString(doc, hypNode->xmlChildrenNode, 1),
+ G_find_cell ( (char*) xmlNodeListGetString
+ (doc, hypNode->xmlChildrenNode, 1),""));
+ if ( file_pointers[i].fp[k] < 0 ) {
+ G_fatal_error ("Raster evidence map '%s' not readable.",
+ (char*) xmlNodeListGetString(doc,
+ hypNode->xmlChildrenNode, 1));
+ }
+
+ /* allocate mem and copy filename into the structure */
+ file_pointers[i].filename[k] = G_strdup ((char*) xmlNodeListGetString
+ (doc, hypNode->xmlChildrenNode, 1));
+
+ /* close the connection to this map for now */
+ /* we will open it again when we need it */
+ /* keeping these handles open will make the prg crash on Win32! */
+ G_close_cell (file_pointers[i].fp[k]);
+ file_pointers[i].fp[k] = -1;
+
+ }
+ }
+ }
+ evidenceNode = evidenceNode->next;
+ }
+ }
+ hypNode = hypNode->next;
+ }
+ }
+ cur = cur->next;
+ }
+
+ return ( file_pointers);
+}
+
+/* close all open raster file descriptors */
+void close_rasters ( Sfp_struct* file_pointers ) {
+
+ int i,k;
+ Uint no_sets;
+
+ no_sets = (Uint) pow((float) 2, (float) NO_SINGLETONS);
+
+ for (i=0; i<N; i++) {
+ fprintf (lp,"CLOSING SAMPLE %i:\n",i);
+ for (k=0; k< no_sets; k++) {
+ if ( file_pointers[i].fp[k] > -1 ) {
+ fprintf (lp,"\tHYP=%i\n",k);
+ G_close_cell (file_pointers[i].fp[k]);
+ }
+ if ( file_pointers[i].filename[k] !=NULL ) {
+ G_free (file_pointers[i].filename[k]);
+ }
+ }
+ }
+}
+
+/* get next float value from raster evidence map */
+/* hyp_idx runs from 0 to (no_sets-1) */
+/* no out of bounds checking is done (performance!) */
+DCELL get_next_dcell_rast ( int group_idx, int hyp_idx, Sfp_struct* file_pointers ) {
+
+ DCELL dcell_val;
+
+ if (first_allocation == 1) {
+ dcell_buf = (DCELL*) G_allocate_d_raster_buf ();
+ }
+ first_allocation = 0;
+
+ if ( file_pointers[group_idx].fp[hyp_idx] == -1 ) {
+ return (0);
+ } else {
+
+ /* why does on-demand reading of raster row not work? */
+ /* if ( ReadX == 0 ) { */
+ G_get_d_raster_row (file_pointers[group_idx].fp[hyp_idx],dcell_buf,ReadY);
+ /*}*/
+ dcell_val = dcell_buf[ReadX];
+ if ( G_is_d_null_value (&dcell_val) ) {
+ NULL_SIGNAL = 1;
+ return (0);
+ }
+ return (dcell_val);
+ }
+}
+
+/* read a sample from several raster maps */
+/* file_pointers have to be assigned using G_open_cell_old before calling this !!! */
+Shypothesis *get_rast_samples_XML ( char* group, int group_idx, int norm, Uint *nsets,
+ BOOL **garbage, xmlDocPtr doc, Sfp_struct* file_pointers ) {
+
+ Shypothesis *sample;
+ Uint no_sets, i;
+ int k;
+ double total;
+ struct Cell_head region;
+
+ no_sets = (Uint) pow((float) 2, (float) NO_SINGLETONS);
+ *nsets = no_sets;
+ G_get_window (®ion);
+
+ sample = frame_discernment( garbage );
+
+ for (k=0; k<no_sets; k++) {
+ sample[k].bpn = (double) get_next_dcell_rast (group_idx, k, file_pointers);
+ if (sample[k].bpn < 0) {
+ G_warning ("Negative BPN (%.5f) at %.2f, %.2f.\n",
+ sample[k].bpn,
+ G_col_to_easting ((double) ReadX,®ion),
+ G_row_to_northing ((double) ReadY,®ion));
+ NULL_SIGNAL = 1;
+
+ }
+ sample[k].bpa = sample[k].bpn;
+ if ( NULL_SIGNAL ) {
+ sample[k].isNull = 1; /* store for debug */
+ }
+ }
+
+ if ( NULL_SIGNAL == 1 ) {
+ return (sample);
+ }
+
+ /* normalise sample */
+ total = 0;
+ for (i=0; i < no_sets; i++) {
+ total = total + sample[i].bpn;
+ }
+ if ( norm ) {
+ for (i=0; i < no_sets; i++) {
+ sample[i].bpn = sample[i].bpn / total;
+ }
+ }
+
+ /* user has not given any evidence for this group! */
+ if ( total == 0 ) {
+ G_warning ("Evidence sums to 0 at %.2f, %.2f.\n",
+ G_col_to_easting ((double) ReadX,®ion),
+ G_row_to_northing ((double) ReadY,®ion));
+ NULL_SIGNAL = 1;
+ }
+
+ /* if normalisation is turned off, we must check that evidence sums to 1 */
+ if ( !norm ) {
+ total = 0;
+ for (i=0; i < no_sets; i++) {
+ total = total + sample[i].bpn;
+ }
+ /* sample needs normalisation */
+ if ( total != 1 ) {
+ G_warning ("Evidence does not sum to 1 (%f) at %.2f, %.2f.\n",
+ total,
+ G_col_to_easting ((double) ReadX,®ion),
+ G_row_to_northing ((double) ReadY,®ion));
+
+ NULL_SIGNAL = 1;
+ }
+ }
+
+ return (sample);
+}
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/file_io.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/file_io.h
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/file_io.h (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/file_io.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,7 @@
+xmlDocPtr stat_XML ( char *file, int *no_singletons, int *n );
+char **get_groups_XML ( int n, xmlDocPtr doc );
+Sfp_struct* test_rast_XML ( char **groups, xmlDocPtr doc );
+char **get_hyp_names_XML ( int *no_all_hyps, xmlDocPtr doc );
+Shypothesis *get_const_samples_XML ( char* group, int norm, BOOL **garbage, xmlDocPtr doc );
+Shypothesis *get_rast_samples_XML ( char* group, int group_idx, int norm, Uint *nsets, BOOL **garbage, xmlDocPtr doc, Sfp_struct* file_pointers );
+void close_rasters ( Sfp_struct* file_pointers );
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/file_io.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/garbage.c
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/garbage.c (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/garbage.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <grass/gis.h>
+
+#include "structs.h"
+#include "dst.h"
+#include "print.h"
+#include "sets.h"
+#include "garbage.h"
+
+BOOL **garbage_init ( void ) {
+ BOOL **garbage;
+ long i;
+
+ garbage = (BOOL **) G_malloc ((unsigned)(garbage_size() * sizeof (BOOL*)));
+ for (i=0; i<garbage_size(); i++) {
+ garbage[i] = NULL;
+ }
+ return (garbage);
+}
+
+void garbage_throw ( BOOL **garbage, int k, BOOL *item ) {
+ if ( garbage[k] != NULL ) {
+ G_fatal_error ("Garbage allocation error!\n");
+ }
+ garbage[k] = item;
+}
+
+void garbage_print ( BOOL **garbage ) {
+ long i;
+
+ fprintf (lp,"GARBAGE: \n");
+ for (i=0; i<garbage_size(); i++) {
+ fprintf (lp,"%li = %i\n",i,*garbage[i]);
+ }
+}
+
+long garbage_size ( void ) {
+ Uint no_of_sets;
+ long slots;
+
+ no_of_sets = (Uint) pow((float) 2, (float) NO_SINGLETONS);
+ slots = (N + (N-1)) * no_of_sets;
+ return (slots);
+}
+
+void garbage_free ( BOOL **garbage ) {
+ int i;
+
+ for ( i=0; i<garbage_size(); i++ ) {
+ G_free (garbage[i]);
+ }
+ G_free (garbage);
+}
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/garbage.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/garbage.h
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/garbage.h (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/garbage.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,6 @@
+/* MEM */
+BOOL **garbage_init ( void );
+void garbage_free ( BOOL **garbage );
+void garbage_throw ( BOOL **garbage, int k, BOOL *item );
+void garbage_print ( BOOL **garbage );
+long garbage_size ( void );
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/garbage.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/globals.h
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/globals.h (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/globals.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,5 @@
+#ifdef LOCAL
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/globals.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/main.c
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/main.c (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/main.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,1178 @@
+
+/* Based on mathematical core routines: */
+
+
+/* Dempster-Shafer Core Routines
+
+By Gavin Powell, 3d Vision and Geometry, Dept of Computer Science, Cardiff University. g.r.powell at cs.cf.ac.uk
+
+*/
+
+/* Integration into GRASS 5 GIS and conversion to generic GIS module */
+/* By Benjamin Ducke, University of Bamberg, Germany, benducke at compuserve.de */
+/* */
+
+/* TODO: */
+/* - make on-demand reading of raster rows work */
+/* - make finding hyp_names independent of singleton order */
+/* - implement warning messages and log to file w/ccordinates */
+/* - OUTPUT MAPS: write different color schemes for different DST metrics? */
+/* BUGS: */
+/* - opening a rast map twice results in weird behavior in GRASS */
+/* - reading CONST evidence from XML file leaks MEM in tiny amounts */
+
+
+#define LOCAL
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+#include <string.h>
+#include <errno.h>
+
+#include <grass/gis.h>
+
+#include "main.h"
+#include "print.h"
+#include "dst.h"
+#include "file_io.h"
+#include "garbage.h"
+
+/* checks if all groups listed by the user do really exist */
+/* at the same time, this returns the number of groups */
+/* specified on the command line */
+int check_groups ( char **groups ) {
+
+ int i,j;
+ int check = 0;
+ int n_groups;
+
+
+ i = 0;
+ n_groups = 0;
+ while ( parm.groups->answers[i] != NULL ) {
+ check = 1;
+ for ( j=0; j < N; j++ ) {
+ if ( strcmp (parm.groups->answers[i], groups[j]) == 0 ) {
+ check = 0;
+ n_groups ++;
+ }
+ }
+ if (check == 1) {
+ G_warning ("Group '%s' does not exist!\n", parm.groups->answers[i]);
+ }
+ i++;
+ }
+
+ if ( check == 1 ) {
+ G_fatal_error ("Please specify only groups declared in the knowledge base.\n");
+ }
+
+ return (n_groups);
+}
+
+
+
+/* This parses the list of hypotheses given by the user. */
+/* specificially, it tokenises the comma-separated input */
+/* and merges tokens that are enclosed by single quotes */
+/* into one SET name, such as 'a,b'. */
+/* Also removes duplicate specifiations. */
+/* This function returns a pointer to an array of hypothesis names which */
+/* can then be passed to the check_hyps() function. */
+/* The number of unique hypotheses found in the *hypspect string is */
+/* written to *num */
+char **parse_hyps (char *hypspec, int *num) {
+ char *tmp;
+ char *hypname;
+ char *quotep;
+ char **outhyps;
+ int i,j;
+ int quote_open;
+ int quote_closed;
+ int duplicate;
+
+ quotep = NULL;
+ *num = 0;
+ j = 0;
+ quote_open = 0;
+ quote_closed = 0;
+ tmp = G_calloc (255, sizeof(char));
+ hypname = G_calloc (255, sizeof(char));
+ outhyps = G_malloc (sizeof (char*));
+
+ /* parse string to detect number of hyps given */
+ tmp = strtok (hypspec, ",");
+ while ( tmp != NULL ) {
+ /* check if it is enclosed in brackets, that is a SET specification like {a,b} */
+ if ( strchr (tmp, '{') != NULL ) {
+ if (quote_open == 1) {
+ /* ERROR: got two opening brackets in a row. */
+ G_fatal_error ("Hypotheses specification string is malformed.\nExpected '}' but got '{'.");
+ }
+ quotep = tmp;
+ if (quote_open == 0) { /* it's an opening bracket */
+ quote_open = 1;
+ quotep ++; /* this now points to the token + 1 (skips bracket) */
+ strcpy (hypname,"");
+ }
+ }
+ if ( strchr (tmp, '}') != NULL ) {
+ if (quote_closed == 1) {
+ /* ERROR: got two closing brackets in a row. */
+ G_fatal_error ("Hypotheses specification string is malformed.\nExpected '{' but got '}'.");
+ }
+ quote_open = 0; /* it's a closing quote */
+ quote_closed = 1;
+ }
+ if ( (quote_open) && (!quote_closed) ) {
+ /* keep copying tokens into the set */
+ strcat (hypname, quotep);
+ strcat (hypname, ",");
+ }
+ if ( (!quote_open) && (quote_closed) ) {
+ /* this is the final set */
+ strncat (hypname, tmp, strlen (tmp)-1); /* remove closing quote */
+ /* check for duplicates */
+ duplicate = 0;
+ for (i=0;i<j;i++) {
+ if (!strcmp (outhyps[i], hypname)) {
+ duplicate = 1;
+ }
+ }
+ if ( duplicate == 0) {
+ /* copy into array */
+ outhyps = G_realloc (outhyps, (unsigned) (j * sizeof (char*)));
+ outhyps [j] = G_calloc ((unsigned) (strlen(hypname)+1), sizeof (char));
+ strcpy (outhyps[j], hypname);
+ j ++;
+ }
+ }
+ if ( (!quote_open) && (!quote_closed) ) {
+ strcpy (hypname, tmp);
+ /* check for duplicates */
+ duplicate = 0;
+ for (i=0;i<j;i++) {
+ if (!strcmp (outhyps[i], hypname)) {
+ duplicate = 1;
+ }
+ }
+ if ( duplicate == 0 ) {
+ /* copy into array */
+ outhyps = G_realloc (outhyps, (unsigned)(j * sizeof (char*)));
+ outhyps [j] = G_calloc ((unsigned)(strlen(hypname)+1), sizeof (char));
+ strcpy (outhyps[j], hypname);
+ j ++;
+ }
+ }
+ tmp = strtok (NULL, ",");
+ quote_closed = 0;
+ }
+
+ *num = j;
+ G_free (tmp);
+ G_free (hypname);
+ return (outhyps);
+}
+
+/* checks if all hypotheses specified by the user do exist */
+int check_hyps ( char **user_hyps, int no_hyps, xmlDocPtr doc ) {
+
+ int i,j;
+ int check = 0;
+ int n_hyps;
+ int no_all_hyps;
+ char **all_hyps;
+
+ all_hyps = get_hyp_names_XML ( &no_all_hyps, doc );
+ n_hyps = 0;
+ for (i=0; i < no_hyps; i++) {
+ check = 1;
+ for ( j=0; j < no_all_hyps ; j++ ) {
+ if ( strcmp (user_hyps[i], all_hyps[j]) == 0 ) {
+ check = 0;
+ n_hyps ++;
+ }
+ }
+ if (check == 1) {
+ G_warning ("Hypothesis '%s' does not exist!\n", user_hyps[i]);
+ }
+ }
+
+ if ( check == 1 ) {
+ G_fatal_error ("One or more hypotheses were not found in DST knowledge base file.\n");
+ }
+
+ for ( i=0; i < no_all_hyps; i++ ) {
+ G_free (all_hyps[i]);
+ }
+ G_free (all_hyps);
+ return (n_hyps);
+}
+
+/* finds index of hyp "hyp_name" in Theta [0..(no_hyps-1)] */
+/* returns -1 on error */
+long find_hyp_idx ( char *hyp_name, xmlDocPtr doc ) {
+ int no_all_hyps;
+ long i, j;
+ char **all_hyps;
+
+ all_hyps = get_hyp_names_XML ( &no_all_hyps, doc );
+ for ( i=0; i < no_all_hyps ; i++ ) {
+ if ( strcmp (hyp_name, all_hyps[i]) == 0 ) {
+ /* free mem first */
+ for ( j=0; j < no_all_hyps; j++ ) {
+ G_free (all_hyps[j]);
+ }
+ G_free (all_hyps);
+ return (i);
+ }
+ }
+
+ /* oops, hyp does not exist */
+ for ( i=0; i < no_all_hyps; i++ ) {
+ G_free (all_hyps[i]);
+ }
+ G_free (all_hyps);
+ return (-1);
+}
+
+
+void free_sample (Shypothesis *sample) {
+
+ G_free (sample);
+}
+
+
+void do_calculations_const (Shypothesis **samples, char **groups, int norm, xmlDocPtr doc) {
+
+ int i;
+ double woc;
+ BOOL **garbage;
+ char **hyps;
+ int no_hyps;
+
+ garbage=garbage_init();
+ woc = 0;
+ hyps = get_hyp_names_XML ( &no_hyps, doc );
+
+ for (i=0; i<N; i++) {
+ samples[i] = get_const_samples_XML (groups[i], norm, garbage, doc);
+ }
+
+ for(i=0;i<N;i++) /* set the bel and pl */
+ {
+ set_beliefs(samples[i]);
+ set_plausibilities(samples[i]);
+ }
+
+ for(i=0;i<N-1;i++) /* combine the sets */
+ {
+ woc = combine_bpn(samples[0], samples[i+1], garbage, CONST_MODE );
+ set_beliefs(samples[0]);
+ set_plausibilities(samples[0]);
+ }
+
+ set_commonalities(samples[0]);
+ set_doubts(samples[0]);
+ set_bint(samples[0]);
+
+
+ fprintf(lp, "\nCONST Evidence Combined:\n");
+ print_frame(samples[0], hyps);
+ fprintf (lp, "Weight of Conflict: %.3f\n",woc);
+
+ garbage_free ( garbage );
+
+ G_free (samples);
+}
+
+
+
+
+
+ void make_result_row ( int val, char *basename, char **hyps, int no_hyps, Sresult_struct *result_row, xmlDocPtr doc ) {
+ int i;
+ char* val_names[NUMVALS]={"bel","pl","doubt","common","bint","woc","maxbpa","minbpa",
+ "maxsrc","minsrc"};
+ DCELL *v1;
+ DCELL *v2;
+
+ result_row->use = YES;
+ /* need an array of DCELL rows to store bel, pl and other DST values */
+ if ( val == WOC ) {
+ /* WOC (Weight of Conflict is always treated a bit differently,
+ because we need this only once for all hypotheses in the FOD */
+ result_row->row[0] = (DCELL*) G_allocate_d_raster_buf ();
+ } else {
+ if (( val == MAXSRC) || ( val == MINSRC)) {
+ for (i = 0; i < no_hyps; i++ ) {
+ result_row->crow[i] = (CELL*) G_allocate_c_raster_buf ();
+ }
+ } else {
+ for (i = 0; i < no_hyps; i++ ) {
+ result_row->row[i] = (DCELL*) G_allocate_d_raster_buf ();
+ }
+ }
+ }
+
+ if ( val == WOC ) {
+ result_row->filename = (char**) G_calloc ( sizeof (char*), 1);
+ /* there is only one file for storing the WOC */
+ result_row->filename[0] = G_malloc ((unsigned) ((sizeof (char) * strlen (basename)) +
+ (sizeof (char) * strlen (val_names[val])) +
+ 2));
+ strcpy (result_row->filename[0],basename);
+ strcat (result_row->filename[0],".");
+ strcat (result_row->filename[0],val_names[val]);
+ } else {
+ result_row->filename = (char**) G_calloc ( sizeof (char*), (unsigned) no_hyps);
+ /* for all other metrics, we need one output file per hypothesis */
+ for (i=0; i<no_hyps;i++) {
+ result_row->filename[i] = G_malloc ((unsigned)((sizeof (char) * strlen (basename)) +
+ (sizeof (char) * strlen (hyps[i])) +
+ (sizeof (char) * strlen (val_names[val])) +
+ 3));
+ strcpy (result_row->filename[i],basename);
+ strcat (result_row->filename[i],".");
+ strcat (result_row->filename[i],hyps[i]);
+ strcat (result_row->filename[i],".");
+ strcat (result_row->filename[i],val_names[val]);
+ G_strchg (result_row->filename[i], ',', '.');
+ }
+ }
+ /* allocate file descriptors */
+ if ( val == WOC ) {
+ result_row->fd = (int*) G_calloc ( sizeof (int), 1);
+ result_row->fd[0] = -1;
+ } else {
+ result_row->fd = (int*) G_calloc ( sizeof (int), (unsigned) no_hyps);
+ for (i=0; i<no_hyps;i++) {
+ result_row->fd[i] = -1;
+ }
+ }
+ /* init color tables for output maps */
+ v1 = (DCELL*) G_malloc (sizeof (DCELL));
+ v2 = (DCELL*) G_malloc (sizeof (DCELL));
+ if ( val == WOC ) {
+ result_row->colors = (struct Colors **) G_calloc ( sizeof (struct Colors*), 1);
+ result_row->colors[0] = G_malloc ( sizeof (struct Colors));
+ G_init_colors (result_row->colors[0]);
+ /* *v1 = (DCELL) WOC_MIN; *v2 = (DCELL) WOC_MAX; */
+ *v1 = 0; *v2 = 1.001;
+ G_add_d_raster_color_rule (v1,0,0,0,v2,255,0,0, result_row->colors[0]);
+ }
+ if (( val == BINT ) || (val==MAXBPA) || (val==MINBPA) ){
+ result_row->colors = (struct Colors **) G_calloc ( sizeof (struct Colors*), (unsigned) no_hyps);
+ for (i=0; i<no_hyps;i++) {
+ result_row->colors[i] = G_malloc ( sizeof (struct Colors));
+ G_init_colors (result_row->colors[i]);
+ *v1 = 0; *v2 = 1.001;
+ G_add_d_raster_color_rule (v1,0,0,0,v2,255,0,0, result_row->colors[i]);
+ }
+ }
+ if ((val == BEL) || (val==PL) || (val==DOUBT) || (val==COMMON )) {
+ result_row->colors = (struct Colors **) G_calloc ( sizeof (struct Colors*), (unsigned) no_hyps);
+ for (i=0; i<no_hyps;i++) {
+ result_row->colors[i] = G_malloc ( sizeof (struct Colors));
+ G_init_colors (result_row->colors[i]);
+ *v1 = 0; *v2 = 0.5;
+ G_add_d_raster_color_rule (v1,36,216,72,v2,216,201,36, result_row->colors[i]);
+ *v1 = 0.500001; *v2 = 1.001;
+ G_add_d_raster_color_rule (v1,216,201,36,v2,216,36,39, result_row->colors[i]);
+ /*
+ *v1 = 0; *v2 = 0.333333;
+ G_add_d_raster_color_rule (v1,36,216,072,v2,36,216,072, result_row->colors[i]);
+ *v1 = 0.333334; *v2 = 0.666666;
+ G_add_d_raster_color_rule (v1,216,201,36,v2,216,201,36, result_row->colors[i]);
+ *v1 = 0.666667; *v2 = 1;
+ G_add_d_raster_color_rule (v1,216,36,39,v2,216,36,39, result_row->colors[i]);
+ */
+ }
+ }
+
+ /* allocate pointers into array of ordered hypotheses */
+ /* this is a look-up table for faster access to the 'real' */
+ /* index of a hypothesis in Theta */
+ {
+ result_row->hyp_idx = (long*) G_calloc ( sizeof (int), (unsigned) no_hyps);
+ for (i=0; i<no_hyps;i++) {
+ result_row->hyp_idx[i] = find_hyp_idx( hyps[i], doc );
+ }
+ }
+}
+
+
+/* writes one GRASS DCELL null value into the output row */
+void write_row_null (DCELL *row, long easting) {
+ G_set_d_null_value (&row[easting], 1);
+}
+
+void write_crow_null (CELL *row, long easting) {
+ G_set_c_null_value (&row[easting], 1);
+}
+
+/* writes a DST metric into the output row */
+/* WOC (weight of conflict) is the only metric not directly stored */
+/* in the Shypothesis struc. Thus, it must be passed explicitly */
+void write_row_val (DCELL *row, long easting, Shypothesis *frame, long hyp, int val
+ , double woc) {
+ switch ( val ) {
+ case BEL:
+ row[easting] = get_bel (frame,hyp);
+ break;
+ case PL:
+ row[easting] = get_pl (frame,hyp);
+ break;
+ case DOUBT:
+ row[easting] = get_doubt (frame,hyp);
+ break;
+ case COMMON:
+ row[easting] = get_common (frame,hyp);
+ break;
+ case BINT:
+ row[easting] = get_bint (frame,hyp);
+ break;
+ case WOC:
+ /* need to process a bit differently */
+ row[easting] = woc;
+ break;
+ case MAXBPA:
+ row[easting] = get_maxbpn (frame,hyp);
+ break;
+ case MINBPA:
+ row[easting] = get_minbpn (frame,hyp);
+ break;
+ }
+}
+
+void write_row_file ( DCELL *row, int fd) {
+ G_put_d_raster_row (fd, row);
+}
+
+
+/* same as above, for maps of type CELL */
+void write_crow_val (CELL *row, long easting, Shypothesis *frame, long hyp,
+ int val) {
+
+ switch ( val ) {
+ case MAXSRC:
+ row[easting] = get_maxbpnev (frame, hyp);
+ break;
+ case MINSRC:
+ row[easting] = get_minbpnev (frame, hyp);
+ break;
+ }
+}
+
+
+void write_crow_file ( CELL *row, int fd) {
+ G_put_c_raster_row (fd, row);
+}
+
+
+void do_calculations_rast (Shypothesis **samples, char **groups, int norm,
+ char* basename, char **outvals, char *hypspec, int quiet_flag,
+ char *logfile, xmlDocPtr doc, Sfp_struct* file_pointers) {
+
+ long y,x;
+ int i, j, k, l, m;
+ long ymax,xmax;
+ double woc;
+ struct Categories cats, icats;
+ DCELL cmin, cmax;
+ Sresult_struct *result_row; /* one result_struct for each DST value */
+ BOOL **garbage;
+ int no_hyps;
+ char* val_names[NUMVALS]={"bel","pl","doubt","common","bint","woc","maxbpa","minbpa",
+ "maxsrc","minsrc"};
+ int error;
+ char **outhyps;
+ int no_sets;
+
+ /* for keeping min and max statistics */
+ Uint nsets;
+ double *min_backup, *max_backup;
+ int *minev_backup, *maxev_backup;
+
+ woc = 0;
+
+ /* check for output options */
+ if ( G_legal_filename(basename) != 1 ) {
+ G_fatal_error ("Please provide a legal filename as basename for output maps(s).\n");
+ }
+
+ if ( hypspec != NULL ) {
+ /* user specified hyps, let's see if they're valid */
+ /* create an outhyps array that has as each of its elements the name
+ of one of the hypotheses specified on the command line */
+ outhyps = parse_hyps (hypspec, &no_hyps);
+ check_hyps ( outhyps, no_hyps, doc );
+ } else {
+ /* just process all hypotheses */
+ outhyps = get_hyp_names_XML ( &no_hyps, doc );
+ }
+
+ if ( logfile != NULL ) {
+ fprintf (lp,"Writing output RASTER maps for: \n");
+ }
+
+ /* create raster rows to store results */
+ result_row = G_malloc ( NUMVALS * sizeof (Sresult_struct) );
+ for (i=0; i<NUMVALS; i++) {
+ result_row[i].use = NO;
+ strcpy (result_row[i].valname,val_names[i]);
+ /* individual raster rows will be alloc'd later */
+ result_row[i].row = (DCELL **) G_malloc ( no_hyps * sizeof (DCELL*) );
+ result_row[i].crow = (CELL **) G_malloc ( no_hyps * sizeof (CELL*) );
+ result_row[i].filename = NULL;
+ }
+
+ j = 0;
+ while ( outvals[j] != NULL ) {
+
+ if ( !strcmp (outvals[j],"bel") ) {
+ if ( logfile != NULL )
+ fprintf (lp,"\t'bel' (Believe) values\n");
+ make_result_row ( BEL, basename, outhyps, no_hyps, &result_row[BEL], doc );
+ }
+ if ( !strcmp (outvals[j],"pl") ) {
+ if ( logfile != NULL )
+ fprintf (lp,"\t'pl' (Plausibility) values\n");
+ make_result_row ( PL, basename, outhyps, no_hyps, &result_row[PL], doc );
+ }
+ if ( !strcmp (outvals[j],"doubt") ) {
+ if ( logfile != NULL )
+ fprintf (lp,"\t'doubt' (Doubt) values\n");
+ make_result_row ( DOUBT, basename, outhyps, no_hyps, &result_row[DOUBT], doc );
+ }
+ if ( !strcmp (outvals[j],"common") ) {
+ if ( logfile != NULL )
+ fprintf (lp,"\t'common' (Commonality) values\n");
+ make_result_row ( COMMON, basename, outhyps, no_hyps, &result_row[COMMON], doc );
+ }
+ if ( !strcmp (outvals[j],"bint") ) {
+ if ( logfile != NULL )
+ fprintf (lp,"\t'bint' (Believe interval) values\n");
+ make_result_row ( BINT, basename, outhyps, no_hyps, &result_row[BINT], doc );
+ }
+ if ( !strcmp (outvals[j],"woc") ) {
+ if ( logfile != NULL )
+ fprintf (lp,"\t'woc' (Weight of conflict) values\n");
+ make_result_row ( WOC, basename, outhyps, no_hyps,&result_row[WOC], doc );
+ }
+ if ( !strcmp (outvals[j],"maxbpa") ) {
+ if ( logfile != NULL )
+ fprintf (lp,"\t'maxbpa' (Maximum BPA) values\n");
+ make_result_row ( MAXBPA, basename, outhyps, no_hyps,&result_row[MAXBPA], doc );
+ }
+ if ( !strcmp (outvals[j],"minbpa") ) {
+ if ( logfile != NULL )
+ fprintf (lp,"\t'minbpa' (Minimum BPA) values\n");
+ make_result_row ( MINBPA, basename, outhyps, no_hyps,&result_row[MINBPA], doc );
+ }
+ if ( !strcmp (outvals[j],"maxsrc") ) {
+ if ( logfile != NULL )
+ fprintf (lp,"\t'maxsrc' (source of highest BPA) values\n");
+ make_result_row ( MAXSRC, basename, outhyps, no_hyps,&result_row[MAXSRC], doc );
+ }
+ if ( !strcmp (outvals[j],"minsrc") ) {
+ if ( logfile != NULL )
+ fprintf (lp,"\t'minsrc' (source of lowest BPA) values\n");
+ make_result_row ( MINSRC, basename, outhyps, no_hyps,&result_row[MINSRC], doc );
+ }
+ j ++;
+ }
+
+ /* open output maps to store results */
+ if ( logfile != NULL )
+ fprintf (lp,"Opening output maps:\n");
+ for (i=0; i<NUMVALS;i++) {
+ if (result_row[i].use == YES) {
+ if ( i == WOC ) {
+ if ( logfile != NULL )
+ fprintf (lp,"\t%s\n",result_row[i].filename[0]);
+ result_row[i].fd[0] = G_open_raster_new (result_row[i].filename[0],DCELL_TYPE);
+ } else {
+ for (j=0; j < no_hyps; j++) {
+ if ( logfile != NULL )
+ fprintf (lp,"\t%s\n",result_row[i].filename[j]);
+ if ((i == MAXSRC) || (i == MINSRC)) {
+ result_row[i].fd[j] = G_open_raster_new (result_row[i].filename[j],CELL_TYPE);
+ } else {
+ result_row[i].fd[j] = G_open_raster_new (result_row[i].filename[j],DCELL_TYPE);
+ }
+ /* check fd for errors */
+ if ( result_row[i].fd[j] < 0 ) {
+ G_fatal_error ("Could not create output map for %s\n",
+ result_row[i].filename[j]);
+ }
+ }
+ }
+ }
+ }
+
+ if ( logfile != NULL ) {
+ fprintf (lp, "Evidence will be combined for these groups:\n");
+ for ( i=0; i < N; i++) {
+ fprintf (lp,"\t%s\n",groups[i]);
+ }
+ fprintf (lp, "Output will be stored in mapset '%s'.\n", G_mapset());
+ fprintf (lp,"\nRead output below carefully to detect potential problems:\n");
+ }
+
+ /* set start coordinates for reading from raster maps */
+ ReadX = 0;
+ ReadY = 0;
+
+ ymax = G_window_rows ();
+ xmax = G_window_cols ();
+
+ if ( !quiet_flag ) {
+ fprintf (stdout,"Combining RAST evidence: \n");
+ fflush (stdout);
+ }
+
+ /* allocate all file pointers */
+ /* open raster maps for this group */
+ /* 0 is the NULL hypothesis, so we start at 1 */
+ no_sets = (Uint) pow((float) 2, (float) NO_SINGLETONS);
+ for (l=0; l<N; l++) {
+ for ( m = 1; m < no_sets; m ++ ) {
+ file_pointers[l].fp[m] = G_open_cell_old ( file_pointers[l].filename[m], G_find_cell ( file_pointers[l].filename[m],"") );
+ if ( file_pointers[l].fp[m] < 0 ) {
+ G_fatal_error ("Could not open raster map '%s' for reading.\n", file_pointers[l].filename[m] );
+ }
+ }
+ }
+
+ for (y=0; y<ymax; y++) {
+ for (x=0; x<xmax; x++) {
+ garbage = garbage_init ();
+ NULL_SIGNAL = 0;
+
+ for (i=0; i<N; i++) {
+ samples[i] = get_rast_samples_XML (groups[i],i, norm, &nsets, garbage, doc, file_pointers );
+ }
+
+ /* get min and max values */
+ for (i=0; i<N; i++) {
+ if (NULL_SIGNAL == 0) {
+ for (k=0; k < nsets; k++) {
+ samples[i][k].minbpn = samples[i][k].bpa;
+ samples[i][k].maxbpn = samples[i][k].bpa;
+ samples[i][k].minbpnev = i + 1;
+ samples[i][k].maxbpnev = i + 1;
+ }
+ }
+
+ }
+
+ for (i=0; i<N; i++) {
+ if (NULL_SIGNAL == 0) {
+ for (j=0; j < N; j++) {
+ for (k=0; k < nsets; k++) {
+ if (samples[i][k].bpa < samples[j][k].minbpn) {
+ samples[j][k].minbpn = samples[i][k].bpa;
+ samples[j][k].minbpnev = i + 1;
+ }
+ if (samples[i][k].bpa > samples[j][k].maxbpn) {
+ samples[j][k].maxbpn = samples[i][k].bpa;
+ samples[j][k].maxbpnev = i + 1;
+ }
+ }
+ }
+ }
+ }
+
+ /* initialise: */
+ /* set belief and plausibility before first combination of evidence */
+ for(i=0;i<N;i++)
+ {
+ if ( NULL_SIGNAL == 0 ) {
+ set_beliefs(samples[i]);
+ set_plausibilities(samples[i]);
+ }
+ }
+
+
+ /* combine evidence and set bel and pl again */
+ /* AFTER COMBINE_BPN(), VALUES IN SAMPLES[0] WILL ALL BE ALTERED */
+ /* so we must save min and max values for later use */
+ min_backup = G_malloc ((unsigned)(nsets * sizeof(double)));
+ max_backup = G_malloc ((unsigned)(nsets * sizeof(double)));
+ minev_backup = G_malloc ((unsigned)(nsets * sizeof(int)));
+ maxev_backup = G_malloc ((unsigned)(nsets * sizeof(int)));
+ for (k=0; k < nsets; k++) {
+ min_backup[k] = samples[0][k].minbpn;
+ max_backup[k] = samples[0][k].maxbpn;
+ minev_backup[k] = samples[0][k].minbpnev;
+ maxev_backup[k] = samples[0][k].maxbpnev;
+ }
+
+ /* now, do the combination! */
+ for(i=0;i<N-1;i++)
+ {
+ if ( NULL_SIGNAL == 0 ) {
+ woc = combine_bpn(samples[0], samples[i+1], garbage, RAST_MODE );
+ set_beliefs(samples[0]);
+ set_plausibilities(samples[0]);
+ }
+ }
+
+ /* restore min and max values */
+ for (k=0; k < nsets; k++) {
+ samples[0][k].minbpn = min_backup[k];
+ samples[0][k].maxbpn = max_backup[k];
+ samples[0][k].minbpnev = minev_backup[k];
+ samples[0][k].maxbpnev = maxev_backup[k];
+ }
+ G_free (min_backup);
+ G_free (max_backup);
+ G_free (minev_backup);
+ G_free (maxev_backup);
+
+ /* all other metrics can be derived from bel and pl, no need */
+ /* to combine evidence again! */
+ if ( NULL_SIGNAL == 0 ) {
+ set_commonalities(samples[0]);
+ set_doubts(samples[0]);
+ set_bint(samples[0]);
+ }
+
+
+ if ( NULL_SIGNAL == 1 ) {
+ for (i=0; i<NUMVALS;i++) {
+ if (result_row[i].use == YES) {
+ if ( i == WOC) {
+ write_row_null (result_row[i].row[0], ReadX);
+ } else {
+ if ((i == MAXSRC)||(i == MINSRC)) {
+ for (j=0; j < no_hyps; j++) {
+ write_crow_null (result_row[i].crow[j], ReadX);
+ }
+
+ } else {
+ for (j=0; j < no_hyps; j++) {
+ write_row_null (result_row[i].row[j], ReadX);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ for (i=0; i<NUMVALS;i++) {
+ if (result_row[i].use == YES) {
+ if ( i == WOC ) {
+ write_row_val (result_row[i].row[0], ReadX, samples[0], result_row[i].hyp_idx[0], i, woc);
+ } else {
+ if (( i == MAXSRC ) || ( i == MINSRC )) {
+ for (j=0; j < no_hyps; j++) {
+ write_crow_val (result_row[i].crow[j], ReadX, samples[0], result_row[i].hyp_idx[j], i);
+ }
+ } else {
+ for (j=0; j < no_hyps; j++) {
+ write_row_val (result_row[i].row[j], ReadX, samples[0], result_row[i].hyp_idx[j], i, woc);
+ }
+ }
+ }
+ }
+ }
+ }
+ ReadX ++;
+ garbage_free ( garbage );
+ for (i=0; i<N; i++) {
+ free_sample (samples[i]);
+ }
+ }
+ ReadY ++; /* go to next row */
+ ReadX = 0;
+ /* save this row to the result file */
+ for (i=0; i<NUMVALS;i++) {
+ if (result_row[i].use == YES) {
+ if ( i == WOC ) {
+ write_row_file ( result_row[i].row[0],result_row[i].fd[0]);
+ } else {
+ if ( ( i == MAXSRC ) || ( i == MINSRC ) ) {
+ for (j=0; j<no_hyps; j++) {
+ write_crow_file ( result_row[i].crow[j],result_row[i].fd[j]);
+ }
+ } else {
+ for (j=0; j<no_hyps; j++) {
+ write_row_file ( result_row[i].row[j],result_row[i].fd[j]);
+ }
+ }
+ }
+ }
+ }
+ if ( !quiet_flag ) {
+ G_percent (ReadY,ymax,1);
+ fflush (stdout);
+ }
+ }
+ if ( !quiet_flag ) {
+ fprintf (stdout,"\n");
+ fflush (stdout);
+ }
+ for (i=0; i<NUMVALS;i++) {
+ if (result_row[i].use == YES) {
+ if ( i == WOC ) {
+ G_close_cell (result_row[i].fd[0]);
+ } else {
+ for (j=0; j<no_hyps; j++) {
+ G_close_cell (result_row[i].fd[j]);
+ }
+ }
+ }
+ }
+
+
+ /* close raster maps */
+ /* 0 is the NULL hypothesis, so we start at 1 */
+ for (l=0; l<N; l++) {
+ for ( m = 1; m < no_sets; m ++ ) {
+ G_close_cell (file_pointers[l].fp[m]);
+ }
+ }
+
+ /* create a categories structure for output maps */
+ /* DCELL maps */
+ G_init_cats (3, "Value ranges", &cats);
+ cmin = 0;
+ cmax = 0.333333;
+ G_set_d_raster_cat (&cmin, &cmax, "low", &cats);
+ cmin = 0.333334;
+ cmax = 0.666666;
+ G_set_d_raster_cat (&cmin, &cmax, "medium", &cats);
+ cmin = 0.666667;
+ cmax = 1;
+ G_set_d_raster_cat (&cmin, &cmax, "high", &cats);
+
+ /* CELL maps */
+ G_init_cats (N+1, "Source of evidence", &icats);
+ G_set_cat (0,"no data",&icats);
+ for (i=1; i<=N; i++) {
+ G_set_cat (i,groups[i-1],&icats);
+ }
+
+ /* write all color tables, categories information and history metadata */
+ for (i=0; i<NUMVALS;i++) {
+ if (result_row[i].use == YES) {
+ if ( i == WOC ) {
+ error = G_write_colors (result_row[i].filename[0], G_mapset(), result_row[i].colors[0]);
+ if (error == -1) {
+ G_warning ("Could not create color table for map '%s'.\n",result_row[i].filename[j]);
+ }
+ } else {
+ if (( i == MAXSRC ) || ( i == MINSRC )) {
+ for (j=0; j<no_hyps; j++) {
+ G_write_cats (result_row[i].filename[j], &icats);
+ }
+ } else {
+ for (j=0; j<no_hyps; j++) {
+ error = G_write_colors (result_row[i].filename[j], G_mapset(), result_row[i].colors[j]);
+ if (error == -1) {
+ G_warning ("Could not create color table for map '%s'.\n",result_row[i].filename[j]);
+ }
+ G_write_raster_cats (result_row[i].filename[j], &cats);
+ }
+ }
+ }
+ }
+ }
+ G_free (samples);
+ for ( i=0; i < no_hyps; i ++ ) {
+ G_free ( outhyps[i]);
+ }
+ G_free (outhyps);
+}
+
+
+int main( int argc, char *argv[] )
+{
+ Shypothesis **samples; /* Data to be combined */
+ unsigned int i;
+ FILE *kb;
+ char **groups;
+ int norm = 1; /* turn on normalisation of evidence by default */
+ /* these are for time keeping in the logfile */
+ time_t systime;
+ clock_t proctime;
+ unsigned long timeused;
+ unsigned int days, hours, mins, secs;
+
+ xmlDocPtr dstXMLFile;
+ Sfp_struct* file_pointers;
+
+ G_gisinit ( argv[0] );
+
+ module = G_define_module ();
+ module->description = "Combines evidences from a DST knowledge base";
+
+ parm.file = G_define_option ();
+ parm.file->key = "file";
+ parm.file->type = TYPE_STRING;
+ parm.file->required = YES;
+ parm.file->description = "Name of the knowledge base that contains the evidence";
+
+ parm.groups = G_define_option ();
+ parm.groups->key = "sources";
+ parm.groups->type = TYPE_STRING;
+ parm.groups->required = NO;
+ parm.groups->multiple = YES;
+ parm.groups->description = "Evidences to be combined (default: all)";
+
+ parm.type = G_define_option ();
+ parm.type->key = "type";
+ parm.type->type = TYPE_STRING;
+ parm.type->required = NO;
+ parm.type->options = "const,rast,vect";
+ parm.type->answer = "rast";
+ parm.type->description = "Type(s) of evidences to combine";
+
+ parm.output = G_define_option ();
+ parm.output->key = "output";
+ parm.output->type = TYPE_STRING;
+ parm.output->required = NO;
+ parm.output->answer = G_location ();
+ parm.output->description = "Prefix for result maps (dflt: location name)";
+
+ parm.vals = G_define_option ();
+ parm.vals->key = "values";
+ parm.vals->type = TYPE_STRING;
+ parm.vals->required = NO;
+ parm.vals->multiple = YES;
+ parm.vals->options = "bel,pl,doubt,common,bint,woc,maxbpa,minbpa,maxsrc,minsrc";
+ parm.vals->answer = "bel";
+ parm.vals->description = "Dempster-Shafer values to map";
+
+ parm.hyps = G_define_option ();
+ parm.hyps->key = "hypotheses";
+ parm.hyps->type = TYPE_STRING;
+ parm.hyps->required = NO;
+ parm.hyps->multiple = NO;
+ parm.hyps->description = "Hypotheses to map (default: all)";
+
+ parm.logfile = G_define_option ();
+ parm.logfile->key = "logfile";
+ parm.logfile->type = TYPE_STRING;
+ parm.logfile->required = NO;
+ parm.logfile->description = "Name of logfile";
+
+ /* TODO: not implemented yet
+ parm.warnings = G_define_option ();
+ parm.warnings->key = "warnings";
+ parm.warnings->type = TYPE_STRING;
+ parm.warnings->required = NO;
+ parm.warnings->description = "Name of site list to store locations of warnings." ;
+ */
+
+ flag.norm = G_define_flag ();
+ flag.norm->key = 'n';
+ flag.norm->description = "Turn off normalisation";
+
+ flag.quiet = G_define_flag ();
+ flag.quiet->key = 'q';
+ flag.quiet->description = "Quiet operation: no progress diplay";
+
+ /* append output to existing logfile ? */
+ flag.append = G_define_flag ();
+ flag.append->key = 'a';
+ flag.append->description = "Append log output to existing file";
+
+ no_assigns = 0;
+
+ /* INIT GLOBAL VARS */
+ WOC_MIN = 0;
+ WOC_MAX = 0;
+
+ /* do not pause after a warning message was displayed */
+ G_sleep_on_error (0);
+
+ /* parse command line */
+ if (G_parser (argc, argv))
+ {
+ exit (-1);
+ }
+
+ /* check if given parameters are valid */
+ if (G_legal_filename (parm.file->answer) == -1) {
+ G_fatal_error ("Please provide the name of an existing DST knowledge base.\n");
+ }
+
+ if (G_find_file ("DST",parm.file->answer,G_mapset()) == NULL) {
+ G_fatal_error ("Knowledge base does not exist in user's MAPSET!\n");
+ }
+
+ /* check logfile */
+ if (parm.logfile->answer != NULL) {
+ if ( !G_legal_filename (parm.logfile->answer) ) {
+ G_fatal_error ("Please specify a legal filename for the logfile.\n");
+ }
+ /* attempt to write to logfile */
+ if (flag.append->answer) {
+ if (fopen (parm.logfile->answer, "r") == NULL) {
+ lp = fopen (parm.logfile->answer, "w+");
+ if (lp == NULL) {
+ G_fatal_error ("Logfile error: %s\n", strerror (errno));
+ }
+ } else {
+ lp = fopen (parm.logfile->answer, "a");
+ if (lp == NULL) {
+ G_fatal_error ("Logfile error: %s\n", strerror (errno));
+ }
+ fprintf (lp,"\n\n * * * * * \n\n");
+ }
+ } else {
+ if ( (lp = fopen ( parm.logfile->answer, "w+" ) ) == NULL ) {
+ G_fatal_error ("Logfile error: %s\n", strerror (errno));
+ }
+ }
+ /* we want unbuffered output for the logfile */
+ setvbuf (lp,NULL,_IONBF,0);
+ } else {
+ /* log output to stderr by default */
+ lp = stderr;
+ }
+
+ /* setup coordinate file storage, if desired */
+ /* try to create a sites file to store coordinates */
+ /* set 'warn' to point to the user-defined sites file */
+ /*
+ warn = NULL;
+ if ( parm.warnings != NULL ) {
+ }
+ */
+
+ /* check if we have read/write access to knowledge base */
+ kb = G_fopen_old ("DST",parm.file->answer,G_mapset());
+ if ( kb == NULL ) {
+ G_fatal_error ("Cannot open knowledge base file for reading and writing!\n");
+ }
+ fclose(kb);
+
+ /* start logfile */
+ if ( parm.logfile->answer != NULL) {
+ fprintf (lp,"This is %s, version %.2f\n",argv[0],PROGVERSION);
+ systime = time (NULL);
+ fprintf (lp,"Calculation started on %s\n",ctime(&systime));
+ }
+
+ /* open DST file and get basic evidence group information */
+ dstXMLFile = stat_XML ( parm.file->answer, &NO_SINGLETONS, &N );
+ groups = get_groups_XML ( N, dstXMLFile );
+
+ if ( NO_SINGLETONS == 1 ) {
+ G_fatal_error ("Knowledge base does not contain any user-supplied hypotheses.\n");
+ }
+
+ if ( parm.groups->answer != NULL ) {
+ /* user specified a subset of groups */
+ N = check_groups ( groups );
+ }
+
+ if ( N < 2 ) {
+ G_fatal_error ("At least two groups of evidences must be present in the knowledge base.\n");
+ }
+
+ /* allocate memory for all samples
+ a sample holds one double for bel, pl and bpn for each
+ piece of evidence. The number of pieces of evidence is
+ the number of possible subsets in Theta
+ = 2^NO_SINGLETONS !
+
+ The number of samples is = number of groups in the XML
+ knowledge base file (N) !
+ */
+ samples = (Shypothesis**) G_malloc ((N * sizeof(Shypothesis*)));
+ for ( i=0; i < N; i ++ ) {
+ samples[i] = (Shypothesis*) G_malloc (sizeof(Shypothesis));
+ }
+
+
+ /* turn off normalisation if user wants it so */
+ if ( flag.norm->answer == 1 ) {
+ norm = 0;
+ }
+
+ /* do some type-dependant checking */
+ /* and open file pointers for all the maps to read! */
+ file_pointers = NULL;
+ if ( !strcmp (parm.type->answer,"rast") ) {
+ if ( parm.groups->answer != NULL ) {
+ /* check only user-specified groups */
+ file_pointers = test_rast_XML ( parm.groups->answers, dstXMLFile );
+ } else {
+ /* check all groups */
+ file_pointers = test_rast_XML ( groups, dstXMLFile );
+ }
+ }
+
+ /* read in all samples in a type-dependant manner */
+ if ( parm.groups->answer != NULL ) {
+ /* read only user-specified groups */
+ if ( !strcmp (parm.type->answer,"const") ) {
+ if ( strcmp (parm.output->answer,G_location ()) != 0) {
+ G_warning ("Ignoring parameter 'output='.\n");
+ }
+ if ( strcmp (parm.vals->answer,"bel") !=0 ) {
+ G_warning ("Ignoring parameter 'values='.\n");
+ }
+ if ( parm.hyps->answer != NULL ) {
+ G_warning ("Ignoring parameter 'hypotheses='.\n");
+ }
+ do_calculations_const (samples,parm.groups->answers, norm, dstXMLFile);
+ }
+ if ( !strcmp (parm.type->answer,"rast") ) {
+ do_calculations_rast (samples,parm.groups->answers, norm,
+ parm.output->answer, parm.vals->answers,
+ parm.hyps->answer, flag.quiet->answer,
+ parm.logfile->answer, dstXMLFile, file_pointers );
+ }
+ } else {
+ /* read all groups */
+ if ( !strcmp (parm.type->answer,"const") ) {
+ if ( strcmp (parm.output->answer,G_location ()) != 0) {
+ G_warning ("Ignoring parameter 'output='.\n");
+ }
+ if ( strcmp (parm.vals->answer,"bel") !=0 ) {
+ G_warning ("Ignoring parameter 'values='.\n");
+ }
+ if ( parm.hyps->answer != NULL ) {
+ G_warning ("Ignoring parameter 'hypotheses='.\n");
+ }
+ do_calculations_const (samples,groups, norm, dstXMLFile);
+ }
+ if ( !strcmp (parm.type->answer,"rast") ) {
+ do_calculations_rast (samples,groups, norm,
+ parm.output->answer, parm.vals->answers,
+ parm.hyps->answer, flag.quiet->answer,
+ parm.logfile->answer, dstXMLFile, file_pointers );
+ }
+ }
+
+ /* close logfile */
+ /* write processing time to logfile */
+ proctime = clock ();
+ timeused = (unsigned long) proctime / CLOCKS_PER_SEC;
+ days = timeused / 86400;
+ hours = (timeused - (days * 86400)) / 3600;
+ mins = (timeused - (days * 86400) - (hours * 3600)) / 60;
+ secs = (timeused - (days * 86400) - (hours * 3600) - (mins * 60));
+ systime = time (NULL);
+
+ if ( parm.logfile->answer != NULL ) {
+ fprintf (lp,"\nCalculation finished on %s",ctime(&systime));
+ fprintf (lp,"Processing time: %id, %ih, %im, %is\n",
+ days, hours, mins, secs );
+ fflush (lp);
+ }
+
+ for (i=0; i<N; i++) {
+ G_free (groups[i]);
+ }
+ G_free (groups);
+
+ return (EXIT_SUCCESS);
+}
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/main.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/main.h
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/main.h (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/main.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,6 @@
+#ifdef macintosh
+ #include "mac.h"
+#endif
+
+#define LOCAL
+#include "structs.h"
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/main.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/print.c
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/print.c (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/print.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,74 @@
+#include <math.h>
+#include <stdio.h>
+
+#include "structs.h"
+#include "print.h"
+
+void print_sample (Shypothesis *sample)
+{
+ Uint no_sets, i, j;
+
+ no_sets = (Uint) pow((float) 2, (float)NO_SINGLETONS);
+ fprintf (stderr,"\n");
+ /* print entire sample */
+ for (i=0;i<no_sets;i++) {
+ fprintf (stderr,"\tSAMPLE NR %i:\n",i);
+ fprintf (stderr,"\t\tBPN: %1.2f\n",sample[i].bpn);
+ fprintf (stderr,"\t\tBEL: %1.2f\n",sample[i].bel);
+ fprintf (stderr,"\t\tPL: %1.2f\n",sample[i].pl);
+ for (j=0;j<NO_SINGLETONS;j++) {
+ fprintf (stderr," %i ",sample[i].type[j]);
+ }
+ fprintf (stderr,"\n");
+ }
+}
+
+/*=======================================================
+ print the values contained in a frame of discernment
+=======================================================*/
+/* *frame points to the first set in the frame of discernment */
+void print_frame(Shypothesis *frame, char **hyps)
+{
+ Uint set, type, no_of_sets;
+ BOOL comma;
+
+ comma = FALSE;
+ no_of_sets = (Uint) pow((float) 2, (float) NO_SINGLETONS);
+
+ /* now step through all subsets in the FOD, sequentially */
+ for(set=0;set<no_of_sets;set++)
+ {
+ fprintf(lp, "{");
+ /* there is one 'type' entry for every singleton */
+ /* that indicates whether a singleton is part */
+ /* of the current subset */
+ for(type=0;type<NO_SINGLETONS;type++) {
+ if((frame[set].type[type] == TRUE) && (type == 0)) {
+ fprintf (lp, "%s",hyps[type+1]);
+ comma = TRUE;
+ }
+ if((frame[set].type[type] == TRUE) && (type > 0) && (type < (NO_SINGLETONS-1))) {
+ if(comma == TRUE) {
+ fprintf(lp, ", %s",hyps[type+1]);
+ }
+ else {
+ fprintf(lp, "%s",hyps[type+1]);
+ comma = TRUE;
+ }
+ }
+ if((frame[set].type[type] == TRUE) && (type == (NO_SINGLETONS-1))) {
+ if(comma) {
+ fprintf(lp, ", %s",hyps[type+1]);
+ }
+ else {
+ fprintf(lp, "%s",hyps[type+1]);
+ }
+ }
+ }
+ fprintf(lp, "}\n");
+ fprintf(lp, "Bel %.3f Pl %.3f bpn %.3f common %.3f doubt %.3f BInt %.3f\n\n",
+ frame[set].bel, frame[set].pl, frame[set].bpn, frame[set].common,
+ frame[set].doubt, frame[set].bint);
+ comma = FALSE;
+ }
+}
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/print.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/print.h
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/print.h (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/print.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,5 @@
+/* print raw bpns in sample */
+void print_sample (Shypothesis *sample);
+/* print nicely formatted sample frame using actual */
+/* hypothesis names (must be present in **hyps) */
+void print_frame(Shypothesis *frame, char **hyps);
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/print.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/readme
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/readme (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/readme 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,93 @@
+/** DST COMBINATION C CODE **/
+/**
+ by Gavin Powell, 3D Vision and Geometry, Dept Compter Science, Cardiff University
+ g.r.powell at cs.cf.ac.uk
+**/
+/***
+
+This is a macintosh codewarrior project.
+It will work fine on other systems. It has compiled with strict ANSI etc...
+For non codewarrior users all your code is in src and headers.
+
+****/
+
+/** SETUP **/
+/*
+ In "defs.h"
+ NO_SINGLETONS -> How many singletons there are in Omega.
+ STORE1 -> This just defines the position within our data structure. Add or take away as necessary. Must agree with NO_SINGLETONS
+ NOTE:- print_frame() in "print.c" uses these defs so check it out and alter as necessary if you alter these!
+
+ N -> the number of sets to combine. (how many pieces of evidence)
+
+*/
+
+/**
+
+printc.c - print_frame
+This can be used to print any frame. So you can output values of frames before combining etc.
+
+
+file_io.c - get_sample
+Reads in data from file in this order....
+
+for Omega = {a, b, c}
+{0} (empty set)
+{a}
+{b}
+{a, b}
+{c}
+{a, c}
+{b, c}
+{a, b, c}
+
+this order is created in frame_discernment
+**/
+
+/***
+
+MEMORY - The "Shypothesis **samples" is not freed. Everything else should be ok, but I have not tested on a large data set
+so there may well be some leaks, please inform me if you find any.
+
+**/
+
+
+/** General DST Stuff **/
+/*
+a hypothesis is defined....
+type[x][y][z].
+where x, y, z can be 0,1
+and say
+x = Store1
+y = Store2
+z = Store3
+so type[0][1][1] would be a hypothesis for Store2 and Store3.
+x, y, and z are 'named' as singletons. So the more possible matches the more singletons
+they are also the original set, and we assign bpn's etc to all of the subsets of this power ste.
+
+The two frames are combined to calculate the bpa/bpn of the third 'fused' frame. Then the belief and plausability are calc'd.
+
+If we know nothing about any of the subsets probabilities then we can assign 1 to [1][1][1].
+
+Defn's
+BPN m(A) := Evidence supporting that hypothesis. DOES NOT have any relevance on sub-sets.
+Belief Bel(A) := Belief in that hypothesis, from the evidence supporting that hypothesis and all subsets of it.
+Plausability Pl = 1-Bel(`A) := Bel(`A) is the total evidence not supporting A. Remember {x} supports {x, y} and vice versa.
+ Shows how much evidence DOESN'T disrepute A.
+
+The length of Bel(A)->Pl(A) Is the belief interval and show ingnorance. The longer it is the more ignorant we are i.e.
+High plausability says that there is little evidnce against our hypothesis and a low belief says we have no evidence for, or know little about.
+Hence we are ignorant of evidnence supporting this hypothesis.
+==========
+BPA is the function saying that all (sum)BPN's = 1 and empty set =0;
+BPN is each m(A). It is how much belief we assign to that set given a piece of evidence (i.e the results from our ATR).
+==========
+The bel is adding the total belief's in A and any that A implies (i.e. subsets).
+This is done using the Belief function or Bel(A).
+When A is a singleton it become a Bayesian belief!
+Since the belief functions != 1 then Bel(A) + Bel(`A) != 1 so Pl = 1-Bel(`A) is how much we 'fail to doubt' A.
+The Belief function finds the TOTAL belief in that hypothesis as opposed to m(A) which is the sigular belief in that hypothesis, irrespective of supporting hypothesise.
+
+When we have a singleton, Bayesian probability, Bel = Pl.
+
+******/
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/readme
___________________________________________________________________
Added: svn:executable
+ *
Added: grass-addons/grass6/dst/raster/r.dst.combine/sets.c
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/sets.c (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/sets.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,88 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "structs.h"
+#include "sets.h"
+
+
+/** are 2 sets the same? **/
+
+BOOL set_equal(Shypothesis A, Shypothesis B)
+{
+ Uint type;
+
+ for(type=0;type<NO_SINGLETONS;type++)
+ if(A.type[type] != B.type[type])
+ return 0;
+ return 1;
+}
+
+
+/** return set index **/
+
+Uint set_index(Shypothesis A, Shypothesis *frame)
+{
+ Uint no_of_sets, set;
+
+ no_of_sets = (Uint) pow((float) 2, (float) NO_SINGLETONS);
+
+ for(set=0;set<no_of_sets;set++)
+ if(set_equal(A, frame[set]))
+ return set;
+
+ return 666;
+}
+
+
+/** A a subset of B? **/
+
+BOOL subset(Shypothesis A, Shypothesis B)
+{
+ Uint type;
+
+ for(type=0;type<NO_SINGLETONS;type++)
+ if((A.type[type] == TRUE) && (B.type[type] == FALSE))
+ return 0;
+
+ return 1;
+}
+
+
+/**union of two sets **/
+/* caller must free Shypothesis.type ! */
+
+Shypothesis set_union(Shypothesis A, Shypothesis B)
+{
+ Uint type;
+ Shypothesis union_set;
+
+ union_set.type = (BOOL*) G_malloc((signed) (NO_SINGLETONS * sizeof(BOOL)));
+
+ for(type=0;type<NO_SINGLETONS;type++)
+ if((A.type[type] == TRUE) || (B.type[type] == TRUE))
+ union_set.type[type] = TRUE;
+ else
+ union_set.type[type] = FALSE;
+
+ return union_set;
+}
+
+/** intersection of two sets **/
+/* caller must free Shypothesis.type ! */
+
+Shypothesis set_intersection(Shypothesis A, Shypothesis B)
+{
+ Uint type;
+ Shypothesis intersection_set;
+
+ intersection_set.type = (BOOL*) G_malloc((signed) (NO_SINGLETONS * sizeof(BOOL)));
+
+ for(type=0;type<NO_SINGLETONS;type++)
+ if((A.type[type] == TRUE) && (B.type[type] == TRUE))
+ intersection_set.type[type] = TRUE;
+ else
+ intersection_set.type[type] = FALSE;
+
+ return intersection_set;
+}
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/sets.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/sets.h
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/sets.h (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/sets.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,5 @@
+BOOL set_equal(Shypothesis A, Shypothesis B);
+Uint set_index(Shypothesis A, Shypothesis *frame);
+BOOL subset(Shypothesis A, Shypothesis B);
+Shypothesis set_union(Shypothesis A, Shypothesis B);
+Shypothesis set_intersection(Shypothesis A, Shypothesis B);
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/sets.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.combine/structs.h
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.combine/structs.h (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.combine/structs.h 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,85 @@
+#include <grass/gis.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+
+#include "defs.h"
+
+#ifndef _STRUCTS_H
+#define _STRUCTS_H
+
+/* put a
+#define LOCAL
+into main.c ! */
+
+#ifdef LOCAL
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+
+typedef struct vector
+{
+ double x;
+ double y;
+ double z;
+}Svector;
+
+typedef struct raster
+{
+ int x;
+ int y;
+}Sraster;
+
+typedef struct matrix4
+{
+ float m[4][4];
+}Smatrix4;
+
+typedef struct matrix3
+{
+ double m[3][3];
+}Smatrix3;
+
+typedef struct hypothesis
+{
+ BOOL *type; /** the ones set to TRUE are the ones in that hypothesis **/
+ double bel; /* belief */
+ double pl; /* plausability */
+ double bint; /* belief interval = |Pl-Bel| = measure of uncertainty */
+ double doubt; /* doubt */
+ double common; /* commonality */
+ double bpn; /* basic probability number assignment */
+ double bpa; /* the bpa as read from the original input map */
+ double minbpn;
+ double maxbpn;
+ int minbpnev;
+ int maxbpnev;
+ int isNull;
+} Shypothesis;
+
+/* global file pointers for access to evidence maps */
+typedef struct fp_struct
+{
+ int *fp; /* array of int file handles */
+ char **filename; /* array to store names of GRASS maps */
+} Sfp_struct;
+
+typedef struct result_struct
+{
+ char valname[6];
+ unsigned short use;
+ DCELL **row;
+ CELL **crow;
+ char **filename;
+ int *fd;
+ long *hyp_idx;
+ struct Colors **colors;
+} Sresult_struct;
+
+/* some global vars to keep track of min and max values */
+EXTERN double WOC_MIN;
+EXTERN double WOC_MAX;
+
+#endif /* _STRUCTS_H */
Property changes on: grass-addons/grass6/dst/raster/r.dst.combine/structs.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.predict.bpn/Makefile
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.predict.bpn/Makefile (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.predict.bpn/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,15 @@
+MODULE_TOPDIR = ../..
+
+PGM = r.dst.predict.bpn
+
+GT_LIB_RAST = -lgt_raster
+GT_LIB_STAT = -lgt_stats
+GSL_LIB = `gsl-config --libs`
+GSL_INC = `gsl-config --cflags`
+LIBES = $(GISLIB) $(DATETIMELIB) $(VECTLIB) $(GSL_LIB) $(GT_LIB_RAST) $(GT_LIB_STAT)
+EXTRA_CFLAGS = -I../../include $(GSL_INC)
+
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
Added: grass-addons/grass6/dst/raster/r.dst.predict.bpn/description.html
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.predict.bpn/description.html (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.predict.bpn/description.html 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,301 @@
+<TITLE>r.dst.bpn</TITLE>
+<body bgcolor="white">
+
+<H2>NAME</H2>
+<em><b>r.dst.bpn</b></em> - Calculates Basic Probability Numbers.
+<BR>
+<EM>(GRASS Raster Program)</EM>
+
+
+<h2>DESCRIPTION</h2>
+
+This program calculates <em>Basic Probability Numbers</em> (BPNs) for use in a Dempster-Shafer Theory (DST) predictive model.
+If you have need for a flexible spatial predictive modelling framework but do not know what DST is, please
+refer to the manual page of <EM><A HREF="dst.combine.html">dst.combine</A></EM> for an introduction.
+<p>
+This module and its manual page have been written with archaeological predictive modelling (APM) in mind,
+ but should be useful for other cases where presence or absence of objects of interest is to be predicted.
+In the following text, replace the term "site" with any other name of an object of interest.
+<p>
+A very simple way to calculate a predictive model is using the <EM><A HREF="dst.predict.html">dst.predict</A></EM>
+wrapper program.
+
+<h3>Introduction</h3>
+
+A BPN is the basic quantification of one (piece of) evidence in the DST. It expresses the strength of belief in the truth
+of a hypothesis in the light of that evidence and without consideration of any other evidence.
+A BPN is usually a value <i>m<sub>n</sub></i> in the range 0 to 1 for each hypothesis 1..<i>n</i> in the <em>Frame of
+Discernment</em> (FOD). The single restriction is that <i>m<sub>1..n</sub></i> must sum to 1 for one piece
+of evidence. By default, the <em><a href="dst.combine.html">dst.combine</a></em> module enforces this restriction by normalising
+all evidences, so that other BPN quantification schemes such as ratings can also be used.<br>
+
+<p>
+In APM, the FOD is taken to consist of two singleton hypotheses and the set of these two:
+<dl>
+<dt><i>H1</i>={"SITE"}</dt>
+ <dd>This proposes that an archaeological site is present.</dd>
+<dt><i>H2</i>={"NO SITE}"</dt>
+ <dd>This proposes that no archaeological site is present.</dd>
+<dt><i>H3</i>={"SITE","NO SITE}"</dt>
+ <dd>This proposes that no decision can be made about site presence or absence (uncertainty).</dd>
+</dl>
+
+<i>h1</i> and <i>h2</i> are mutually exclusive exclusive and cover all possible outcomes.
+The set of both represents uncertainty and we will refer to this as the "uncertainty hypothesis".
+To be precise, the complete set of hypotheses for this FOD also includes the empty set {NULL},
+which is of mere mathematical necessity and will be of no further concern.
+<p>
+The purpose of <em>r.dst.bpn</em> is to calculate a BPN for these three hypotheses by using only
+two <em>source of evidences</em> readily available in a GIS-based analysis: (a) a CELL format GRASS raster map that shows categories
+which are deemed to influence the probability of a site having been established in a location, such
+as soil type and quality, distance to water, slope etc. and (b) a GRASS vector map which contains
+the locations of already discovered sites as vector points. The latter are used to sample
+the raster map in a systematic way. The basic idea is to check for <em>differences in proportions</em>
+between the sample (cells with sites) and the population (all other cells in the region).
+These differences are used to quantify the strength of belief (BPN) in each of the FOD's three
+hypotheses.
+
+The output of this program consists of three raster maps, with basename given by the user
+(option <em>output=</em>) and suffixes ".SITE", ".NOSITE" and ".SITE.NOSITE", which encode
+the BPNs for the respective hypotheses.
+
+These maps can be combined with BPN maps generated from other sources of evidence
+by <EM><A HREF="dst.combine.html">dst.combine</A></EM> to calculate the overall belief
+in <i>H1</i> or <i>H2</i> as supported by the given evidence (as well as many other
+useful metrics derrived from this).
+
+<h3>Details of BPN quantification</h3>
+
+In this case of evidence represented as a GRASS raster map, a BPN has to be calculated
+for each cell within the current region.
+Thus, we need to know, what categories in the CELL evidence map supports or refutes
+<i>H1</i> ("SITE") or <i>H2</i> ("NO SITE") and to what degree.
+The relationship between cell values and degree of support/refutal is given by the
+BPN function.
+The latter can be linear and monotonous but in principle it can also be arbitrarily complex.
+To find an adequately exact BPN function, this program uses a simple approximation strategy.
+<p>
+Let us look at an archaeological example: we want to model belief in the presence or absence
+of a certain type of hillfort settlements at different altitudes (evidence "height") in a topographically varied region of interest.
+At first glance, the situation looks straight-forward: the higher the terrain, the higher we believe the
+chance to find that kind of settlement (i.e. <i>m(H1)</i> closer to "1"), as higher locations are better to defend.
+However, even in this simple case, an adequate
+BPN function would be more complex. Let us look at a plot of <i>m(H1)</i> vs. "height", as
+derrived from some archaeologist's subjective belief:
+<ol>
+<li>Starting at the lowest height, there would first be a flat section
+that represents the height range of the low lands in which no forts
+were built. </li>
+<li>This would be succeeded by a section with gradually steeper inclination as the height
+approaches a range which the prehistoric builders found optimal.</li>
+<li>Within this optimal range, the curve flattens out on a high level.</li>
+<li>Above a certain height however, logistic problems become too great and we do not believe
+that prehistoric people were able to cope with them beyond a certain point, thus <i>m(H1)</i>
+falls off towards "0" quickly.</li>
+</ol>
+
+<p align="center"><img src="r.dst.bpn.001.png" alt="BPN chart"></p>
+Instead of "professional intuition", <em>r.dst.bpn</em> models <i>m(H1)</i> using a statistical
+approach.
+For this, the user must supply only two things:
+<ol>
+ <li>a vector points map <i>S</i> with the locations of known sites;
+ </li>
+ <li>a raster map <i>M</i> that represents the evidence (e.g. height).
+ </li>
+</ol>
+Optionally, one or more raster maps can be supplied to represent "NO SITE" bias, such
+as unsurveyable land (for details see section on "Uncertainty handling").
+<p>
+Likewise, one or more vector point attributes can be chosen to represent "SITE" bias, such
+as unfounded trust in the location of a site.
+<p>
+The raster evidence map must be fully categorised, i.e. each cell must represent
+a category (e.g. 1='0 to 5 m', 2='5 to 10 m',...) or be NULL (no data).
+You can use the <EM><A HREF="../../html/r.categorize.html">r.categorize</A></EM> program to quickly
+create such a map from any GRASS raster map.
+<p>
+For each category <i>C</i> in the input evidence map <i>M</i>, <em>r.dst.bpn</em> compares
+the overall cell percentage of <i>C</i> in <i>M</i> (<i>Perc(M)</i>) with the percentage
+of category <i>C</i> cells that contain a site from <i>S</i> (<i>Perc(S)</i>).<br>
+The assumption is that if <i>Perc(M)</i> > <i>Perc(S)</i> <em>at a significant level</em>
+then the evidence in <i>M</i> and <i>S</i> supports the hypothesis "NO SITE" for <em>all</em>
+cells in <i>M</i> and if <i>Perc(M)</sub></i> < <i>Perc(S)</i> it supports "SITE".
+If the difference is found to be of very high signficance, the belief mass assigned
+to on of these two hypothesis tends towards "1", if it is low, it tends towards "0".
+<p>
+Just how signficant the difference in percentages is depends on (a) the magnitude of
+the difference (b) the size of the sample and (c) the
+number of cells in the entire region. This is catered for by calculating a z-statistic
+for each case. The z-statistic gives the probability of observing a difference in
+proportions as extreme as <i>Perc(M)-Perc(S)</i> under the assumption that
+there is <em>no</em> significant difference between <i>Perc(M)</i> and <i>Perc(S)</i>.
+In effect, this gives the probability of making an error when declaring it
+significant (see "Uncertainty handling" for details on how this affects BPN values).
+If the total number <i>n</i> of sites in <i>S</i> is greater
+than 30, this will be derrived from a standard normal distribution, otherwise from
+a t-distribution with <i>n</i> degrees of freedom.
+<p>
+
+In addition, if the probability of error exceeds a certain threshold (by default 0.05 or 5%),
+the belief mass to be shifted will be exponentially weighted, so that more belief mass is
+shifted increasingly rapidly to the uncertainty hypothesis as the probability of error drops further
+below the threshold. You can adjust the threshold by using the <i>perror</i> parameter.
+
+<p>
+
+Often, one will not be restricted as to what category ranges to choose (e.g. 1, 5 or 10 m intervals
+for evidence "height"?).
+If there are too many categories in <i>M</i>, <em>r.dst.bpn</em> will produce an overfitting
+function and a model based on such BPNs will not be able to generalise well, i.e.
+its predictions are very likely to be wrong when checked against new data.
+On the other hand, if there are extremely few categories, the program might not be able to find
+significant evidence that supports either hypothesis. As a safeguard, a chi-square test
+is run over all categories. This calculates the probability of making an error when
+declaring the overall set of percentage differences significant (see "Uncertainty
+handling" for details on how this affects BPN values).
+<p>
+Another option is to use categories with individual ranges.
+One could use a priori knowledge about the
+region's natural zones to create a more significant categorisation manually
+(using <EM><A HREF="../../html/r.support">r.support</A></EM>):
+<p>
+<PRE>
+ Cat. Range Label
+ 1 0-1000 plains and valleys
+ 2 1000-1500 hills
+ 3 1500-1700 mountain areas
+ 4 1700-2500 high mountain areas
+ 5 2500-5000 highest mountain areas
+</PRE>
+<p>
+In this way, one can approximate arbitrarily complex BPN functions.
+Once several sources of evidence have been turned into BPN maps,
+they can be registered in a DST knowledge base file using
+<EM><A HREF="dst.update.html">dst.update</A></EM> and combined to produce
+the final predictive map(s) using <EM><A HREF="dst.combine.html">dst.combine</A></EM>.
+Another option is to use the <EM><A HREF="dst.predict.html">dst.predict</A></EM> wrapper
+program for building predictive models in one go.
+<p>
+
+<h3>Handling uncertainty</h3>
+
+The greatest merit of DST-based predictive modelling is its capability to explicitly handle
+uncertainty. In predictive modelling uncertainty mainly arises because there is direct
+evidence for "SITE", but only indirect evidence for "NO SITE": e.g. the fact that no sites
+have been reported on terrain type "A" might mean that (a) prehistoric settlers actually
+avoided this type of terrain or (b) one of many possible source filters is in effect
+and prevented us from finding the sites present on this type of terrain. Maybe it
+is rough terrain and could not adequately be surveyed, or it is mostly covered by a
+type of land use that has a negative impact on site remains visibility. In cases
+like these, we might not be able to decide between "SITE" or
+"NO SITE". This inability to decide is the nature of uncertainty.
+<p>
+Consider the dilemma of this situation in classical probability theory: if one states
+that "SITE" has a low probability of e.g. 0.49 , then probability theory says that
+"NO SITE" = 1 - 0.49 = 0.51. Thus, we are forced to decide in favour of "NO SITE", even
+if we feel that we have no sufficient direct evidence to support it.
+Dempster-Shafer Theory, on the other hand, gives us the possibility to transfer a
+certain amount of this basic probability mass to the uncertainty hypothesis
+</i>H3={"SITE","NOSITE"}</i> and thus allows us to postpone decisions about "NO SITE"
+until e.g. better information is obtained.
+<p>
+The <em>r.dst.bpn</em> program transfers basic probability mass to the uncertainty hypothesis in one
+of three cases:
+
+<ol>
+ <li>The probability <i>P</i> that the oberserved difference in proportion between sample (sites)
+ and population (entire region) for evidence category <i>C</i> could also be
+ produced by chance, as calculated by
+ the z-statistic, is greater > 0. In this case, <i>P</i> is subtracted from the
+ BPN value for either "SITE" or "NOSITE" and transferred to "SITE or NOSITE"
+ for category <i>C</i>. This leaves <i>m(H1)</i> or <i>m(H2)</i>
+ as 1-<i>P</i>, respectively.
+ </li>
+ <li>The chi-square test shows that the overall frequencies of categories in the sample
+ could also have been produced by chance with probability <i>P</i>.
+ In this case, <i>P</i> is subtracted from the
+ BPN value for either "SITE" or "NOSITE" and transferred to "SITE or NOSIT"
+ for all categories.
+ </li>
+ <li>The user has supplied one ore more bias maps using the <em>nbias=</em> option.
+ These are GRASS floating point (FCELL or DCELL) type maps in which every cell
+ is assigned a value between 0 and 1. These values specify the degree to which
+ we believe that observed differences are biased towards the "NO SITE" hypothesis.
+ For each bias map, the following is done: (a) calculate the percentage of cells
+ <i>BP</i> of each category <i>C</i> that are covered by a bias value larger than
+ 0; (b) calculate the mean value <i>BM</i> of the bias in cells of category
+ <i>C</i>. For each category <i>C</i>, <i>BM</i> * <i>BP</i> is subtracted from
+ the belief mass assigned to "NO SITE".
+ </li>
+ <li>The user has specified one or more attributes of the site vector point map to
+ represent the degree to which these points (sites) are biased towards the "SITE" hypothesis using
+ the <em>sbias=</em> option. Again, these attributes must be floating point values in the
+ range 0 to 1. Calculations are similar to the "NO SITE" case: The more biased sites present
+ on a certain category of an evidence maps, the more basic belied mass will be subtracted
+ from the "SITE" hypothesis and shifted to "SITE or NOSITE".<br>
+ <strong>(Note: The <em>sbias=</em> option is currently broken. DO NOT USE!)</strong>
+ </li>
+</ol>
+In the first two cases, beliefs are expressed as mathematical probabilities. There is
+no obvious difference between the concepts of belief (mass) and probability (mass) here.
+In the case of bias maps, the more flexible DST concept of belief may be used to
+obtain a quantification in the range 0 to 1 in any way.
+Note that no hypothesis can ever achieve a basic probability assignment smaller than
+0.01 or larger than 0.98. There is always a tiny bit of doubt left in real life ...
+<p>
+The case of bias maps and attributes needs a bit more explanation:<br>
+"NO SITE" bias: e.g. in archaeological predictive modelling,
+certain factors can affect the chance to find sites. This may lead to a situation where
+the assumed absence of sites leads to a high belief in "NO SITE" even though there
+potentially is evidence for "SITE", but it cannot be included in the model.
+Common sources of "NO SITE" bias are:
+<ul>
+ <li>Geomorphological processes have hidden some sites and exposed others. Soil Erosion
+ and deposition can severly affect site detectability. In this case, one could
+ prepare a bias map which has "1" for cells with the highest amounts of deposited
+ material and "0" for eroded areas (other cells may lie anywhere in between these
+ extremes).
+ </li>
+ <li>Differences in survey density, intensity and systematics may leave some areas less well
+ covered than others. In this case, one could
+ prepare a bias map which has "1" for cells were no surveying has been done and
+ "0" for cells which have been covered by systematic and intrusive surveys.
+ </li>
+ <li>Land use can have a heavy impact on site visibility. Sites in dense
+ forests are much harder to spot than in open fields.
+ </li>
+</ul>
+"SITE" bias: sometimes, evidence supporting the presence of sites may also be biased if it rests on false assumptions.
+Again, archaeological examples might include:
+<ul>
+ <li>A too high degree of convidence in the correctness of the site data (location, dating).
+ </li>
+ <li>Inclusion of locations that do not actually qualify as "sites" in a strict sense.
+ </li>
+ <li>Modelling with sites that do not all depend on the encironmental evidence as heavily as it
+ is assumed.
+ </li>
+</ul>
+In summary, a high amount of basic probability mass is shifted to uncertainty for category <i>C</i>, if (a) many
+cells of category <i>C</i> fall into biased areas and (b) these cells have a high bias
+on average and/or many sites on category <i>C</i> are (strongly) biased.
+<p>
+If a logfile is generated by supplying the <em>log=</em> option, detailed information
+about the BPN quantifications and bias impacts are produced for the user to review.
+
+<h3>Notes</h3>
+This program was developed as part of the GRASS 5 DST Predictive Modelling Toolkit.<br>
+The <em>sbias=</em> option is currently broken. Do not use it!
+
+<h3>SEE ALSO</h3>
+<EM><A HREF="dst.combine.html">dst.combine</A></EM><br>
+<EM><A HREF="dst.predict.html">dst.predict</A></EM><br>
+<EM><A HREF="dst.update.html">dst.update</A></EM><br>
+<EM><A HREF="../../html/r.categorize.html">r.categorize</A></EM><br>
+<EM><A HREF="../../html/r.support.html">r.support</A></EM><br>
+<h3>AUTHOR</h3>
+Benjamin Ducke,<br>
+University of Kiel, Germany<br>
+<i>Last changed: $Date: 2006/01/03</i>
+</body>
Property changes on: grass-addons/grass6/dst/raster/r.dst.predict.bpn/description.html
___________________________________________________________________
Added: svn:mime-type
+ text/html
Added: svn:keywords
+ Author Date Id
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.predict.bpn/main.c
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.predict.bpn/main.c (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.predict.bpn/main.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,1252 @@
+/* r.dst.bpn */
+/* Part of the GRASS Dempster-Shafer Predictive Modelling Extension */
+
+/* Purpose: Automatically calculate statistic BPNs (Basic Probability Numbers)
+ for a predictive model of site locations using Dempster-Shafer's
+ theory of evidence.
+
+ Needs two files that constitute one source of evidence:
+ (a) a fully classified input raster map (integer format)
+ (b) a list of sites
+
+ The difference in relative class frequencies between the entire raster map
+ and the cells that lie under the sites is taken to be evidence for one of two
+ mutually exclusive hypotheses:
+ (a) h1 = a site is present in this cell
+ (b) h2 = no site is present
+ the probability masses of each source of evidence.
+
+ The output consists of three floating point raster maps,
+ encoding the BPNs for each of the three hypotheses in the
+ interval [0..1].
+ The output map names will be suffixed '.SITE', '.NOSITE' and
+ '.SITE.NOSITE', respectively.
+
+ This file is licensed under the GPL (version 2 or later at your option)
+ see: http://www.gnu.org/copyleft/gpl.html* /
+
+ (c) Benjamin Ducke 2006
+ benducke at compuserve.de
+
+*/
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+
+#include <grass/gis.h>
+#include <grass/Vect.h>
+#include <grass/dbmi.h>
+
+#include "gt/cat_engine.h"
+#include "gt/rowcache.h"
+#include "gt/gstats_tests.h"
+#include "gt/gstats_error.h"
+
+#define PROGVERSION 1.6
+
+#define BUF_SIZE 4096
+
+#define ANULL -1.1111111111
+
+/* program will issue a warning if sample points are fewer than MIN_SAMPLE_SIZE */
+#define MIN_SAMPLE_SIZE 50
+
+typedef struct
+{
+ float a;
+ float b;
+ float a_b;
+}
+bpn_struct;
+
+float MINBPN_H1 = 1.00;
+float MAXBPN_H1 = 0.00;
+float MINBPN_H2 = 1.00;
+float MAXBPN_H2 = 0.00;
+float MINBPN_H1_2 = 1.00;
+float MAXBPN_H1_2 = 0.00;
+
+unsigned int WARN_ON = 0;
+unsigned int WARN_N_TO_SMALL = 0;
+
+extern int errno;
+int cachesize;
+
+char tmp_file[BUF_SIZE];
+int debug_mode = 1; /* 1 to enable writing debug output to logfile */
+FILE *logfile;
+
+
+/* This calculates the actual BPN values */
+/* a = share_smp; b = share_nat */
+/* h1 = belief in "site", calculated from z-statistic */
+/* h2 = belief in "no site", calculated from z-statistic */
+/* h1_2 = "no site OR site" (uncertainty hypothesis) */
+/* int i and char *label are passed so that some information can be written
+ to the logfile */
+/* if the user has specified bias map(s), an amount proportionate to */
+/* the proportion of biased cells and the mean bias in those cells will */
+/* be transferred from the NO SITE hyp h2 to uncertainty h1_2 */
+void
+dst_calc (float *a, float *b, float *a_b, int sample_size,
+ int i, char *label, float **share_bias, float **mean_bias, int num_bias_maps,
+ float perror )
+{
+ float h1, h2, h1_2;
+ float transfer;
+ int j;
+ float p0;
+
+ h1 = 0.01;
+ h2 = 0.01;
+
+
+ /* calculate z-statistic */
+ p0 = (gstats_test_ZP2 (*a/100, *b/100, sample_size));
+
+ if (*a > *b) {
+ /* probability of error < significance level: */
+ /* directly transfer the other probability mass to h1 */
+ if ( p0 <= perror ) {
+ h1 = 1 - p0;
+ /* if error probability > significance level: */
+ } else {
+ h1 = 1 - powf ( p0, (1 - p0) - p0);
+ }
+ if (h1 > 0.98) {
+ h1 = 0.98;
+ }
+ }
+
+ if (*a < *b) {
+ if ( p0 <= perror ) {
+ h2 = 1 - p0;
+ } else {
+ h2 = 1 - powf ( p0, (1- p0) - p0);
+ }
+ if (h2 > 0.98) {
+ h2 = 0.98;
+ }
+ }
+
+ /* shift bias to uncertainty if bias map(s) present */
+ if (( h2 > 0.01 ) && (mean_bias != NULL)) {
+ transfer = 0;
+ /* j steps thru all bias maps, i is the current map category */
+ for (j = 0; j < num_bias_maps; j++) {
+ transfer = h2 * mean_bias[j][i] * (share_bias[j][i]/100);
+ h2 = h2 - transfer;
+ }
+ }
+
+ if (h1 < 0.01) { h1 = 0.01; }
+ if (h2 < 0.01) { h2 = 0.01; }
+
+ /* whatever is left gets shifted to the uncertainty hypothesis */
+ h1_2 = 1 - (h1 + h2);
+
+ /* return results */
+ *a = h1;
+ *b = h2;
+ *a_b = h1_2;
+
+ /* keep track of global min and max BPN values */
+ if ( h1 < MINBPN_H1 ) {
+ MINBPN_H1 = h1;
+ }
+ if ( h1 > MAXBPN_H1 ) {
+ MAXBPN_H1 = h1;
+ }
+ if ( h2 < MINBPN_H2 ) {
+ MINBPN_H2 = h2;
+ }
+ if ( h2 > MAXBPN_H2 ) {
+ MAXBPN_H2 = h2;
+ }
+ if ( h1_2 < MINBPN_H1_2 ) {
+ MINBPN_H1_2 = h1_2;
+ }
+ if ( h1_2 > MAXBPN_H1_2 ) {
+ MAXBPN_H1_2 = h1_2;
+ }
+}
+
+
+/* process input map and write BPN values to output map */
+void write_BPNs (char *coverage_answer, char* mapset, char *sites_answer, char **bias_maps,
+ char *result_answer, float perror, char *color_rules, int show_progress)
+{
+ CELL *cellbuf;
+ FCELL *fcellbuf;
+ struct Categories *cats;
+ struct Cell_head region;
+ struct Colors colors;
+ FCELL from, to; /* for color ramp */
+ GT_Row_cache_t *cache;
+ int nrows, ncols;
+ int row, col;
+ int fd, fd_out_a, fd_out_b, fd_out_a_b, fd_bias;
+ int n; /* number of classes */
+ int i,j, k, sample_size;
+ long total = 0; /* for cell statistics */
+ float *share_nat = NULL;
+ float *share_smp = NULL;
+ /* for chi-square test */
+ double chisq_result;
+ int *observed = NULL;
+ int *expected = NULL;
+ int chi_cats;
+ bpn_struct *bpn; /* stores BPN values */
+ /* temporary variables for DST quantification */
+ float a, b, a_b;
+ char result_map[255] = "";
+ char **cats_description; /* category labels */
+ long *cat_count; /* category counts */
+ int *site_count;
+ /* needed for analysing sites file */
+ int n_sites = 0;
+ long row_idx;
+ long col_idx;
+
+ int num_bias_maps;
+ float **share_bias;
+ float **mean_bias;
+ DCELL *bias_dcellbuf = NULL;
+ CELL *bias_cellbuf = NULL;
+
+ char errmsg[200];
+ struct Map_info vect_map;
+ struct line_pnts *vect_points;
+ int type;
+ double x,y,z;
+ int n_points;
+
+ cats = G_malloc (sizeof (struct Categories));
+ G_get_window (®ion);
+ nrows = G_window_rows ();
+ ncols = G_window_cols ();
+
+ cellbuf = NULL;
+
+
+ /* STEP 1: Calculate ranges and number of categories in input maps */
+
+ /* get number of categories */
+ G_read_cats (coverage_answer, G_find_cell (coverage_answer, ""), cats);
+
+ n = G_number_of_cats (coverage_answer, G_find_cell (coverage_answer, "")) + 1;
+ if (n < 2) {
+ G_fatal_error ("Could not find at least two categories in input map.");
+ }
+ if (debug_mode)
+ {
+ fprintf (logfile, "Found %i categories in input map.\n", n);
+ fflush (logfile);
+ }
+
+ /* get category labels and counts */
+ cats_description = GT_get_labels (coverage_answer,G_find_cell (coverage_answer, ""));
+ if (cats_description == NULL) {
+ G_fatal_error ("Could not read category labels from input map.");
+ }
+ cat_count = GT_get_c_counts (coverage_answer,G_find_cell (coverage_answer, ""), show_progress);
+ if (cat_count == NULL) {
+ G_fatal_error ("Could not count categories in input map.");
+ }
+
+ /* calculate percentual shares of coverage cats and store them */
+ share_nat = (float *) G_malloc ((signed) (n * sizeof (float)));
+ for (i = 0; i < n; i++) {
+ share_nat[i] = 0;
+ total = total + cat_count[i];
+ }
+
+ for (i = 0; i < n; i++) {
+ share_nat[i] = (float) cat_count[i] / total * 100;
+ }
+ if (debug_mode)
+ {
+ fprintf (logfile,"\nCategories in input map '%s@%s':\n", coverage_answer, G_find_cell (coverage_answer, ""));
+ fprintf (logfile,"Cat.\tCount\t(%%)\tDescription\n");
+ for (i = 0; i < n; i++) {
+ fprintf (logfile, "%i\t%li\t%5.2f\t%s\n", i, cat_count[i],share_nat[i],
+ cats_description[i]);
+ }
+ fflush (logfile);
+ }
+
+ /* open evidence raster map for reading */
+ fd = G_open_cell_old (coverage_answer, G_find_cell (coverage_answer, ""));
+ if (fd < 0) {
+ G_fatal_error ("Could not open input map for reading.\n");
+ }
+
+ /* open bias map(s) (if given), count percentage of categories under bias > 0 and store mean
+ bias for each category */
+ mean_bias = NULL;
+ share_bias = NULL;
+ num_bias_maps = 0;
+ if (bias_maps != NULL) {
+ while (bias_maps[num_bias_maps] != NULL) {
+ num_bias_maps ++;
+ }
+ }
+ if (num_bias_maps > 0) {
+ /* allocate memory for bias maps */
+ share_bias = (float **) G_malloc ((signed) (num_bias_maps * sizeof (float*)));
+ mean_bias = (float **) G_malloc ((signed) (num_bias_maps * sizeof (float*)));
+ bias_cellbuf = G_allocate_c_raster_buf ();
+ bias_dcellbuf = G_allocate_d_raster_buf ();
+
+ if (show_progress) {
+ fprintf (stdout, "Analysing bias map(s):\n");
+ }
+ for (i = 0; i < num_bias_maps; i++) {
+ fd_bias = G_open_cell_old (bias_maps[i], G_find_cell (bias_maps[i], ""));
+ if (fd_bias < 0) {
+ G_fatal_error ("Could not open bias map '%s' for reading.\n", bias_maps[i]);
+ }
+ if (debug_mode) {
+ fprintf (logfile, "\nImpact of NO SITE bias in '%s':\n", bias_maps[i]);
+ fprintf (logfile, "Cat.\tMean\tArea(%%)\tDescription\n");
+ }
+ share_bias [i] = (float *) G_malloc ((signed) (n * sizeof (float)));
+ mean_bias [i] = (float *) G_malloc ((signed) (n * sizeof (float)));
+ for (j = 0; j < n; j ++) {
+ share_bias [i][j] = 0;
+ mean_bias [i][j] = 0;
+ }
+ for (j = 0; j < nrows; j++) {
+ /* read one row from coverage and bias maps */
+ G_get_c_raster_row (fd, bias_cellbuf, j);
+ G_get_d_raster_row (fd_bias, bias_dcellbuf, j);
+ for (k = 0; k < ncols; k++) {
+ /* analyse row */
+ if (!G_is_c_null_value (&bias_cellbuf[k])) {
+ /* NULL values have no effect */
+ if (!G_is_d_null_value (&bias_dcellbuf[k])) {
+ if (bias_dcellbuf[k] > 0) {
+ share_bias [i][bias_cellbuf[k]] ++;
+ mean_bias [i][bias_cellbuf[k]] += bias_dcellbuf[k];
+ }
+ }
+ }
+ }
+ }
+ for (j=0; j<n; j++) {
+ /* calculate %area that is biased */
+ if ((mean_bias[i][j] != 0) && (share_bias[i][j] != 0) && (cat_count[j] != 0)) {
+ mean_bias [i][j] = mean_bias [i][j] / share_bias[i][j];
+ share_bias[i][j] = share_bias[i][j] / (((float) cat_count[j]) / 100);
+ } else {
+ mean_bias[i][j] = 0;
+ share_bias[i][j] = 0;
+ }
+ if (debug_mode) {
+ fprintf (logfile,"%i\t%.2f\t%.2f\t%s\n", j, mean_bias[i][j],
+ share_bias[i][j], cats_description[j]);
+ }
+
+ }
+ G_close_cell (fd_bias);
+
+ if (show_progress) {
+ G_percent (i + 1, num_bias_maps, 1);
+ fflush (stdout);
+ }
+ }
+ if (show_progress) {
+ fprintf (stdout,"\n");
+ fflush (stdout);
+ }
+ }
+
+ /* open vector points */
+ vect_points = Vect_new_line_struct ();
+ Vect_set_open_level (1);
+ if (1 > Vect_open_old (&vect_map, sites_answer, "") )
+ {
+ sprintf (errmsg, "Could not open vector map with sample points for reading.\n");
+ G_fatal_error ("%s",errmsg);
+ }
+ Vect_set_constraint_region (&vect_map, region.north, region.south,
+ region.east, region.west, 0.0, 0.0);
+
+ /* calculate total size of sites sample in current region */
+ while ( (type = Vect_read_next_line (&vect_map, vect_points, NULL)) > 0)
+ {
+ if ( type == GV_POINT ) {
+ n_sites ++;
+ }
+ }
+ if ( n_sites < 2 ) {
+ G_fatal_error ("Less than two vector points (sites) in current region.");
+ }
+
+ /* rewind sites file */
+ Vect_close (&vect_map);
+ Vect_open_old (&vect_map, sites_answer, "");
+ Vect_set_constraint_region (&vect_map, region.north, region.south,
+ region.east, region.west, 0.0, 0.0);
+
+ /* create array to store sites<->categories counts */
+ site_count = G_calloc (n, sizeof(int));
+ /* attach a cache to raster map */
+ cache = (GT_Row_cache_t *) G_malloc (sizeof (GT_Row_cache_t));
+ GT_RC_open (cache, cachesize, fd, CELL_TYPE);
+
+ total = 0; i = 0;
+ if (show_progress) {
+ fprintf (stdout, "Counting categories under sites:\n");
+ }
+
+ j = 0;
+ n_points = 1; /* since we are dealing with points, we only need to read one coord per object */
+ while ((type = Vect_read_next_line (&vect_map, vect_points, NULL)) > 0)
+ {
+ if (type == GV_POINT) {
+ /* check if site in current region */
+ Vect_copy_pnts_to_xyz (vect_points, &x, &y, &z, &n_points);
+ /*
+ if ( (x >= region.west) &&
+ (x <= region.east) &&
+ (y >= region.south) &&
+ (y <= region.north) )
+ {
+ */
+ /* get raster row with same northing as sample and perform
+ * quantification */
+ row_idx =
+ (long) G_northing_to_row (y, ®ion);
+ col_idx =
+ (long) G_easting_to_col (x, ®ion);
+ cellbuf = GT_RC_get (cache, row_idx);
+ /* now read the raster value under the current site */
+ if (G_is_c_null_value (&cellbuf[col_idx]) == 0)
+ {
+ site_count [cellbuf[col_idx]]++;
+ total++;
+ i ++; /* i keeps track of samples on non-null coverage inside the current region */
+ }
+ /*
+ }
+ */
+ /* update progress display */
+ j ++;
+ if (show_progress) {
+ G_percent (j, n_sites, 1);
+ fflush (stdout);
+ }
+ }
+ }
+ /* store size of sample for later use */
+ sample_size = i;
+
+ /* allocate an array to store percentages of cats under sites */
+ share_smp = (float *) G_malloc ((signed) (n * sizeof (float)));
+ /* calculate percentages */
+ for (j = 0; j < n; j++) {
+ share_smp[j] = (float) site_count[j] / total * 100;
+ }
+ if (show_progress) {
+ fprintf (stdout, "\n");
+ fflush (stdout);
+ }
+
+ if (debug_mode)
+ {
+ fprintf (logfile, "\nCategories under %i sites in '%s':\n", i, sites_answer);
+ fprintf (logfile,"Cat.\tCount\t(%%)\tDescription\n");
+ for (i=0; i < n; i ++) {
+ fprintf (logfile, "%i\t%i\t%5.2f\t%s\n", i, site_count[i], share_smp[i],
+ cats_description[i]);
+ }
+ fflush (logfile);
+ }
+
+ /* now do the DST quantification */
+ /* a = site; b = no site; a_b = could be both */
+ bpn = G_malloc ((signed) (n * sizeof (bpn_struct)));
+
+ if (debug_mode) {
+ fprintf (logfile,"\nBPN quantifications for categories; threshold p(NULL) = %.2f\n", perror);
+ fprintf (logfile,"Cat.\t{h1}\t{h2}\t{h1,h2}\tDescription*\n");
+ }
+
+ for (i = 0; i < n; i++)
+ {
+ a = share_smp[i];
+ b = share_nat[i];
+ a_b = 0;
+ /* calculate the actual BPN values */
+ dst_calc (&a, &b, &a_b, sample_size, i, cats_description[i],
+ share_bias, mean_bias, num_bias_maps, perror);
+ bpn[i].a = a;
+ bpn[i].b = b;
+ bpn[i].a_b = a_b;
+ }
+
+ /* shift some belief to uncertainty for ALL categories, if chi-square tests gives us reason */
+ /* to doubt the significance of the differences in *a and *b over ALL categories */
+ expected = G_malloc ((signed) (n * sizeof(int)));
+ observed = G_malloc ((signed) (n * sizeof(int)));
+ chi_cats = 0;
+ for (i = 0; i < n; i++) {
+ /* make sure categories not present in current region do not get included in test */
+ if ( share_nat[i] > 0 ) {
+ observed [chi_cats] = site_count [i];
+ /* the expected frequency is calculated from the population frequencies */
+ expected [chi_cats] = sample_size * share_nat[i]/100;
+ chi_cats ++;
+ }
+ }
+
+ /* run a relaxed chi-square test */
+ chisq_result = gstats_rtest_XF (observed, expected, chi_cats, chi_cats - 1);
+ G_free (expected);
+ G_free (observed);
+
+ /* subtract probability of Type I error from ALL BPNs */
+ /* exponentially more probability is subtracted if P(0) */
+ /* exceeds the user-setable threshold (0.05 by default) */
+ for (i = 0; i < n; i++) {
+ if ( chisq_result <= perror ) {
+ bpn[i].a = bpn[i].a - chisq_result;
+ } else {
+ bpn[i].a = bpn[i].a - powf (chisq_result, (1-chisq_result)-chisq_result);
+ }
+ if (bpn[i].a < 0.01) {
+ bpn[i].a = 0.01;
+ }
+ bpn[i].b = bpn[i].b - chisq_result;
+ if (bpn[i].b < 0.01) {
+ bpn[i].b = 0.01;
+ }
+ bpn[i].a_b = 1 - (bpn[i].a + bpn[i].b);
+ }
+
+ /* write information on BPN quantification to logfile */
+ if (debug_mode)
+ {
+ for (i = 0; i < n; i++) {
+ fprintf (logfile, "%i\t%4.2f\t%4.2f\t%4.2f\t%s\n",
+ i,bpn[i].a, bpn[i].b, bpn[i].a_b, cats_description[i]);
+ }
+ }
+ if (debug_mode) {
+ fprintf (logfile,"\n*h1 = 'site present', h2 = 'no site present'\nh1,h2 = 'site present' OR 'no site present' (uncertainty)\n");
+ fprintf (logfile,"\nChi-square test result: probability of type I error = %.6f\n", chisq_result);
+ }
+
+ /* open result maps */
+ sprintf (result_map, "%s.SITE", result_answer);
+ fd_out_a = G_open_raster_new (result_map, FCELL_TYPE);
+ sprintf (result_map, "%s.NOSITE", result_answer);
+ fd_out_b = G_open_raster_new (result_map, FCELL_TYPE);
+ sprintf (result_map, "%s.SITE.NOSITE", result_answer);
+ fd_out_a_b = G_open_raster_new (result_map, FCELL_TYPE);
+ if ((fd_out_a < 1) || (fd_out_b < 1) || (fd_out_a_b < 1))
+ {
+ G_fatal_error ("Could not open result map for writing.\n");
+ }
+
+ if (show_progress) {
+ fprintf (stdout, "Writing BPN quantifications: \n");
+ }
+ fcellbuf = G_allocate_raster_buf(FCELL_TYPE);
+ for (row = 0; row < nrows; row++) {
+ cellbuf = GT_RC_get (cache, row);
+ /* parse one row of raster data and write BPNs */
+ for (col = 0; col < ncols; col++) {
+ if (G_is_c_null_value (&cellbuf[col]) == 0) {
+ fcellbuf[col] = bpn[cellbuf[col]].a;
+ } else { /* copy null-value */
+ G_set_f_null_value (&fcellbuf[col], 1);
+ }
+ }
+ G_put_raster_row (fd_out_a, fcellbuf, FCELL_TYPE);
+
+ for (col = 0; col < ncols; col++) {
+ if (G_is_c_null_value (&cellbuf[col]) == 0) {
+ fcellbuf[col] = bpn[cellbuf[col]].b;
+ } else { /* copy null-value */
+ G_set_f_null_value (&fcellbuf[col], 1);
+ }
+ }
+ G_put_raster_row (fd_out_b, fcellbuf, FCELL_TYPE);
+
+ for (col = 0; col < ncols; col++) {
+ if (G_is_c_null_value (&cellbuf[col]) == 0) {
+ fcellbuf[col] = bpn[cellbuf[col]].a_b;
+ } else { /* copy null-value */
+ G_set_f_null_value (&fcellbuf[col], 1);
+ }
+ }
+ G_put_raster_row (fd_out_a_b, fcellbuf, FCELL_TYPE);
+
+ if (show_progress) {
+ G_percent (row, nrows-1, 1);
+ fflush (stdout);
+ }
+ }
+ if (show_progress) {
+ fprintf (stdout, "\n");
+ fflush (stdout);
+ }
+
+ /* we can now close the coverage map ... */
+ /* close cache first */
+ GT_RC_close (cache);
+ /* now close the maps */
+ G_close_cell (fd_out_a);
+ G_close_cell (fd_out_b);
+ G_close_cell (fd_out_a_b);
+
+
+ /*** WRITE COLOR SCHEMES FOR OUTPUT MAPS ***/
+
+ /*** H1 ***/
+ G_init_colors (&colors);
+ if ( !strcmp ( color_rules, "cont" ) ) {
+ from = 0.000;
+ to = 1.001;
+ G_add_f_raster_color_rule (&from, 0, 0, 0, &to, 255, 0, 0, &colors);
+ }
+ if ( !strcmp ( color_rules, "stct" ) ) {
+ from = MINBPN_H1;
+ to = MAXBPN_H1;
+ G_add_f_raster_color_rule (&from, 0, 0, 0, &to, 255, 0, 0, &colors);
+ }
+ if ( !strcmp ( color_rules, "bins" ) ) {
+ from = 0.000;
+ to = 0.333;
+ G_add_f_raster_color_rule (&from, 255, 0, 0, &to, 255, 0, 0, &colors);
+ from = 0.334;
+ to = 0.666;
+ G_add_f_raster_color_rule (&from, 255, 255, 0, &to, 255, 255, 0, &colors);
+ from = 0.667;
+ to = 1.001;
+ G_add_f_raster_color_rule (&from, 0, 255, 0, &to, 0, 255, 0, &colors);
+ }
+ if ( !strcmp ( color_rules, "stbs" ) ) {
+ from = MINBPN_H1;
+ to = MINBPN_H1 + ((MAXBPN_H1-MINBPN_H1) / 3);
+ G_add_f_raster_color_rule (&from, 255, 0, 0, &to, 255, 0, 0, &colors);
+ from = MINBPN_H1 + ((MAXBPN_H1-MINBPN_H1) / 3) + 0.001;
+ to = MINBPN_H1 + (((MAXBPN_H1-MINBPN_H1) / 3) * 2 );
+ G_add_f_raster_color_rule (&from, 255, 255, 0, &to, 255, 255, 0, &colors);
+ from = MINBPN_H1 + (((MAXBPN_H1-MINBPN_H1) / 3) * 2 ) + 0.001;
+ to = MAXBPN_H1 + 0.001;
+ G_add_f_raster_color_rule (&from, 0, 255, 0, &to, 0, 255, 0, &colors);
+ }
+ sprintf (result_map, "%s.SITE", result_answer);
+ G_write_colors (result_map, G_mapset(), &colors);
+ G_free_colors (&colors);
+
+ /*** H2 ***/
+ G_init_colors (&colors);
+ if ( !strcmp ( color_rules, "cont" ) ) {
+ from = 0.000;
+ to = 1.001;
+ G_add_f_raster_color_rule (&from, 0, 0, 0, &to, 0, 255, 0, &colors);
+ }
+ if ( !strcmp ( color_rules, "stct" ) ) {
+ from = MINBPN_H2;
+ to = MAXBPN_H2;
+ G_add_f_raster_color_rule (&from, 0, 0, 0, &to, 0, 255, 0, &colors);
+ }
+ if ( !strcmp ( color_rules, "bins" ) ) {
+ from = 0.000;
+ to = 0.333;
+ G_add_f_raster_color_rule (&from, 255, 0, 0, &to, 255, 0, 0, &colors);
+ from = 0.334;
+ to = 0.666;
+ G_add_f_raster_color_rule (&from, 255, 255, 0, &to, 255, 255, 0, &colors);
+ from = 0.667;
+ to = 1.001;
+ G_add_f_raster_color_rule (&from, 0, 255, 0, &to, 0, 255, 0, &colors);
+ }
+ if ( !strcmp ( color_rules, "stbs" ) ) {
+ from = MINBPN_H2;
+ to = MINBPN_H2 + ((MAXBPN_H2-MINBPN_H2) / 3);
+ G_add_f_raster_color_rule (&from, 255, 0, 0, &to, 255, 0, 0, &colors);
+ from = MINBPN_H2 + ((MAXBPN_H2-MINBPN_H2) / 3) + 0.001;
+ to = MINBPN_H2 + (((MAXBPN_H2-MINBPN_H2) / 3) * 2 );
+ G_add_f_raster_color_rule (&from, 255, 255, 0, &to, 255, 255, 0, &colors);
+ from = MINBPN_H2 + (((MAXBPN_H2-MINBPN_H2) / 3) * 2 ) + 0.001;
+ to = MAXBPN_H2 + 0.001;
+ G_add_f_raster_color_rule (&from, 0, 255, 0, &to, 0, 255, 0, &colors);
+ }
+ sprintf (result_map, "%s.NOSITE", result_answer);
+ G_write_colors (result_map, G_mapset(), &colors);
+ G_free_colors (&colors);
+
+ /*** H1 OR H2 ***/
+ G_init_colors (&colors);
+ if ( !strcmp ( color_rules, "cont" ) ) {
+ from = 0.000;
+ to = 1.001;
+ G_add_f_raster_color_rule (&from, 0, 0, 0, &to, 255, 255, 0, &colors);
+ }
+ if ( !strcmp ( color_rules, "stct" ) ) {
+ from = MINBPN_H1_2;
+ to = MAXBPN_H1_2;
+ G_add_f_raster_color_rule (&from, 0, 0, 0, &to, 255, 255, 0, &colors);
+ }
+ if ( !strcmp ( color_rules, "bins" ) ) {
+ from = 0.000;
+ to = 0.333;
+ G_add_f_raster_color_rule (&from, 255, 0, 0, &to, 255, 0, 0, &colors);
+ from = 0.334;
+ to = 0.666;
+ G_add_f_raster_color_rule (&from, 255, 255, 0, &to, 255, 255, 0, &colors);
+ from = 0.667;
+ to = 1.001;
+ G_add_f_raster_color_rule (&from, 0, 255, 0, &to, 0, 255, 0, &colors);
+ }
+ if ( !strcmp ( color_rules, "stbs" ) ) {
+ from = MINBPN_H1_2;
+ to = MINBPN_H1_2 + ((MAXBPN_H1_2-MINBPN_H1_2) / 3);
+ G_add_f_raster_color_rule (&from, 255, 0, 0, &to, 255, 0, 0, &colors);
+ from = MINBPN_H1_2 + ((MAXBPN_H1_2-MINBPN_H1_2) / 3) + 0.001;
+ to = MINBPN_H1_2 + (((MAXBPN_H1_2-MINBPN_H1_2) / 3) * 2 );
+ G_add_f_raster_color_rule (&from, 255, 255, 0, &to, 255, 255, 0, &colors);
+ from = MINBPN_H1_2 + (((MAXBPN_H1_2-MINBPN_H1_2) / 3) * 2 ) + 0.001;
+ to = MAXBPN_H1_2 + 0.001;
+ G_add_f_raster_color_rule (&from, 0, 255, 0, &to, 0, 255, 0, &colors);
+ }
+ sprintf (result_map, "%s.SITE.NOSITE", result_answer);
+ G_write_colors (result_map, G_mapset(), &colors);
+ G_free_colors (&colors);
+
+ /* clean up fp map stuff */
+ G_free (cellbuf);
+ G_free (fcellbuf);
+ G_free (share_nat);
+ G_free (share_smp);
+ G_free (cat_count);
+ if ( share_bias != NULL ) {
+ for (i = 0; i < num_bias_maps; i ++) {
+ G_free (share_bias[i]);
+ G_free (mean_bias[i]);
+ }
+ G_free (share_bias);
+ G_free (mean_bias);
+ G_free (bias_cellbuf);
+ G_free (bias_dcellbuf);
+ }
+ G_free (site_count);
+ for (i = 0; i< n; i++) {
+ G_free (cats_description[i]);
+ }
+ G_free (cats_description);
+}
+
+
+/* this checks if all bias maps are valid FP maps with cell value 0.0 to 1.0 */
+/* terminates the program if there are any problems */
+void check_bias_maps (char **answers, int quiet) {
+
+ int i;
+ char *mapset;
+ double min, max;
+
+ if (answers != NULL) {
+ i = 0;
+ while (answers[i] != NULL) {
+ mapset = G_calloc (BUF_SIZE, sizeof (char));
+ /* check if input map is a floating point map with min and max [0..1] */
+ mapset = G_find_cell (answers[i],"");
+ if ( mapset == NULL) {
+ G_fatal_error ("Bias map '%s' does not exist in current location.",answers[i]);
+ }
+ if (!G_raster_map_is_fp (answers[i], mapset)) {
+ G_fatal_error ("Bias map '%s' is not a floating point map.", answers[i]);
+ }
+ if (GT_get_f_range (answers[i],mapset,&min,&max,1-quiet) < 0) {
+ G_fatal_error ("Bias map '%s' is not readable.",answers[i]);
+ }
+ if ((min < 0) || (max > 1)) {
+ G_fatal_error ("Bias map '%s' has cells with values outside the range 0.0 to 1.0",answers[i]);
+ }
+ i ++;
+ }
+ }
+}
+
+
+/* checks if all SITE bias attributes specified by user
+ exist, are type DOUBLE and [0..1]
+*/
+double **check_bias_atts ( char *site_file, char **atts, int quiet) {
+
+ struct Cell_head region;
+ char *site_mapset;
+ struct Map_info in_vect_map;
+ struct line_pnts *vect_points;
+ struct line_cats *vect_cats;
+ int cur_type;
+ char errmsg [200];
+ int nrows, ncols;
+ int num_sites;
+ int num_atts;
+ int *num_vals;
+ int i,j,k;
+
+ double **bias;
+
+ /* site attribute management */
+ struct field_info *field;
+ char buf[5000], *colname;
+ int dbcol, dbncols, ctype, sqltype, more;
+ dbString sql, str;
+ dbDriver *driver;
+ dbHandle handle;
+ dbCursor cursor;
+ dbTable *table;
+ dbColumn *column;
+ dbValue *dbvalue;
+
+ G_get_window (®ion);
+ nrows = G_window_rows ();
+ ncols = G_window_cols ();
+
+ vect_points = Vect_new_line_struct ();
+ vect_cats = Vect_new_cats_struct ();
+
+ if ((site_mapset = G_find_vector2 (site_file, "")) == NULL) {
+ sprintf (errmsg, "Could not find input vector map %s\n", site_file);
+ G_fatal_error ("%s",errmsg);
+ }
+
+ Vect_set_open_level (1);
+ if (1 > Vect_open_old (&in_vect_map, site_file, site_mapset)) {
+ sprintf (errmsg, "Could not open input vector points.\n");
+ G_fatal_error ("%s",errmsg);
+ }
+
+ /* filter vector objects to current region and point types only */
+ Vect_set_constraint_region (&in_vect_map, region.north, region.south,
+ region.east, region.west, 0.0, 0.0);
+ Vect_set_constraint_type (&in_vect_map, GV_POINT);
+
+ /* get number of site bias attributes */
+ num_atts = 0;
+ if (atts != NULL) {
+ while (atts[num_atts] != NULL) {
+ num_atts ++;
+ }
+ }
+
+ /* calculate number of vector points in map and current region */
+ num_sites = 0;
+ while ((cur_type = Vect_read_next_line (&in_vect_map, vect_points, NULL)) > 0) {
+ num_sites ++;
+ }
+
+ /* create double arrays large enough to store all bias values */
+ bias = G_malloc ( (signed) ( num_atts * sizeof ( double* )) );
+ if ( bias == NULL ) {
+ G_fatal_error ("Out of memory.\n");
+ }
+ for ( i = 0; i < num_atts; i ++ ) {
+ bias[i] = G_malloc ( (signed) (num_sites * sizeof ( double )) );
+ if ( bias [i] == NULL ) {
+ G_fatal_error ("Out of memory.\n");
+ }
+ /* initialise all atts to ANULL (-1.11111...) */
+ for ( j = 0; j < num_sites; j ++ ) {
+ bias[i][j] = ANULL;
+ }
+ }
+
+ /* this records the number of values read for each attribute */
+ num_vals = G_malloc ( (signed) (num_atts * sizeof ( int )) );
+ if ( num_vals == NULL ) {
+ G_fatal_error ("Out of memory.\n");
+ }
+ for ( i = 0; i < num_atts; i ++ ) {
+ num_vals [i] = 0;
+ }
+
+ /* rewind vector points file: close and re-open */
+ Vect_close (&in_vect_map);
+ Vect_open_old(&in_vect_map, site_file, site_mapset);
+ Vect_set_constraint_type (&in_vect_map, GV_POINT);
+ Vect_set_constraint_region (&in_vect_map, region.north, region.south,
+ region.east, region.west, 0.0, 0.0);
+
+ k = 0;
+ while ((cur_type = Vect_read_next_line (&in_vect_map, vect_points, vect_cats)) > 0) {
+ /* check for site attributes */
+ for (i = 0; i < vect_cats->n_cats; i++) {
+ field = Vect_get_field( &in_vect_map, vect_cats->field[i]);
+ if ( field != NULL ) {
+ db_init_string (&sql);
+ driver = db_start_driver(field->driver);
+ db_init_handle (&handle);
+ db_set_handle (&handle, field->database, NULL);
+ if (db_open_database(driver, &handle) == DB_OK){
+ /* sql query */
+ sprintf (buf, "select * from %s where %s = %d", field->table,
+ field->key,
+ vect_cats->cat[i]);
+ db_set_string (&sql, buf);
+
+ db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL);
+ table = db_get_cursor_table (&cursor);
+ db_fetch (&cursor, DB_NEXT, &more );
+ dbncols = db_get_table_number_of_columns (table);
+ for( dbcol = 0; dbcol < dbncols; dbcol++) {
+ column = db_get_table_column(table, dbcol);
+ sqltype = db_get_column_sqltype (column);
+ ctype = db_sqltype_to_Ctype(sqltype);
+ dbvalue = db_get_column_value(column);
+ db_convert_value_to_string( dbvalue, sqltype, &str);
+ colname = (char*) db_get_column_name (column);
+ /* check if this is one of the bias atts */
+ for ( j = 0; j < num_atts; j ++ ) {
+ if (!strcmp (colname, atts[j])){
+ if (ctype == DB_C_TYPE_DOUBLE) {
+ /* store value */
+ bias [j][k] = atof (db_get_string (&str));
+ } else {
+ G_warning ("Attribute '%s' found but not of type DOUBLE. Ignored.\n", atts[j]);
+ }
+ }
+ }
+ k ++; /* increment array position for attribute storage */
+ }
+ db_close_cursor(&cursor);
+ db_close_database(driver);
+ db_shutdown_driver(driver);
+ } else {
+ db_shutdown_driver(driver);
+ }
+ }
+ }
+
+ } /* END (loop through sites list) */
+ Vect_close (&in_vect_map);
+
+ fprintf ( stderr, "\nCHECK DONE.\n");
+
+ return ( bias );
+}
+
+
+/* MAIN */
+int
+main (int argc, char *argv[])
+{
+ struct GModule *module;
+ struct
+ {
+ struct Option *input;
+ struct Option *sites;
+ struct Option *n_bias_maps;
+ struct Option *s_bias_atts;
+ struct Option *p0_threshold;
+ struct Option *colormap;
+ struct Option *output;
+ struct Option *logfile;
+ struct Option *cachesize;
+ }
+ parm;
+
+ struct
+ {
+ struct Flag *quiet;
+ struct Flag *append;
+ }
+ flag;
+
+ char result_str[BUF_SIZE] = "bpn.";
+ char *mapset;
+ int show_progress = 1; /* enable progress display by default */
+ time_t systime;
+ clock_t proctime;
+ unsigned long timeused;
+ unsigned int days, hours, mins, secs;
+ struct History hist;
+ /* these vars are used to store information about the input map */
+ int cats; /* number of categories in input map */
+ long null_count; /* number of NULL cells */
+ long nocat_count; /* number of cells that do not fall into the category range [0 .. n] */
+
+ double **bias_atts;
+
+ /* setup some basic GIS stuff */
+ G_gisinit (argv[0]);
+ module = G_define_module ();
+ module->description = "Calculates Basic Probability Numbers (BPN) for DST predictive models.";
+ /* do not pause after a warning message was displayed */
+ G_sleep_on_error (0);
+
+ /* Parameters: */
+ /* input = a map that shows the natural (complete) distribution */
+ /* of a feature. */
+ parm.input = G_define_standard_option (G_OPT_R_INPUT);
+ parm.input->key = "raster";
+ parm.input->type = TYPE_STRING;
+ parm.input->required = YES;
+ parm.input->gisprompt = "old,cell,raster";
+ parm.input->description = "Raster evidence map";
+
+ /* site map with known sites */
+ parm.sites = G_define_standard_option (G_OPT_V_INPUT);
+ parm.sites->key = "sites";
+ parm.sites->type = TYPE_STRING;
+ parm.sites->required = YES;
+ parm.sites->description = "Vector map with sample points";
+
+ parm.n_bias_maps = G_define_standard_option (G_OPT_R_INPUT);
+ parm.n_bias_maps->key = "nbias";
+ parm.n_bias_maps->required = NO;
+ parm.n_bias_maps->multiple = YES;
+ parm.n_bias_maps->gisprompt = "old,fcell,raster";
+ parm.n_bias_maps->description = "Raster map(s) with 'NO SITE' bias [0..1]";
+
+ /*
+ parm.s_bias_atts = G_define_option ();
+ parm.s_bias_atts->key = "sbias";
+ parm.s_bias_atts->required = NO;
+ parm.s_bias_atts->multiple = YES;
+ parm.s_bias_atts->description = "Vector attribute(s) with 'SITE' bias [0..1]";
+ */
+
+ parm.p0_threshold = G_define_option ();
+ parm.p0_threshold->key = "perror";
+ parm.p0_threshold->required = NO;
+ parm.p0_threshold->type = TYPE_DOUBLE;
+ parm.p0_threshold->answer = "0.05";
+ parm.p0_threshold->options = "0.0-1.0";
+ parm.p0_threshold->description = "Significance level for statistical tests";
+
+ /* base name for output maps */
+ parm.output = G_define_option ();
+ parm.output->key = "output";
+ parm.output->type = TYPE_STRING;
+ parm.output->required = NO;
+ parm.output->description = "Output raster maps base name (overwrites existing)";
+
+ /* type of colormap for output raster map(s) */
+ parm.colormap = G_define_option ();
+ parm.colormap->key = "color";
+ parm.colormap->type = TYPE_STRING;
+ parm.colormap->required = NO;
+ parm.colormap->description = "Output maps color scheme";
+ parm.colormap->options = "cont,bins,stct,stbs";
+ parm.colormap->answer = "cont";
+
+ /* Name of logfile. If given, operations will be verbosely logged */
+ /* to this file. */
+ parm.logfile = G_define_option ();
+ parm.logfile->key = "logfile";
+ parm.logfile->type = TYPE_STRING;
+ parm.logfile->required = NO;
+ parm.logfile->description = "Name of file to log operations to";
+
+ /* number of lines to store in cache */
+ parm.cachesize = G_define_option ();
+ parm.cachesize->key = "cachesize";
+ parm.cachesize->type = TYPE_INTEGER;
+ parm.cachesize->answer = "-1";
+ parm.cachesize->required = NO;
+ parm.cachesize->description = "Raster rows to store in cache (-1 for auto)";
+
+ /* append output to existing logfile ? */
+ flag.append = G_define_flag ();
+ flag.append->key = 'a';
+ flag.append->description = "Append log output to existing ASCII file";
+
+ /* quiet operation ? */
+ flag.quiet = G_define_flag ();
+ flag.quiet->key = 'q';
+ flag.quiet->description = "Quiet operation: display minimal information";
+
+ /* parse command line */
+ if (G_parser (argc, argv))
+ {
+ exit (-1);
+ }
+
+ /* check for 'quiet' flag */
+ if ( flag.quiet->answer ) {
+ show_progress = 0;
+ }
+
+ /* write log output to a file? */
+ if ( parm.logfile->answer == NULL ) {
+ debug_mode = 0;
+ }
+
+ mapset = G_calloc (BUF_SIZE, sizeof (char));
+ /* check if input map is a fully categorized raster map */
+ mapset = G_find_cell (parm.input->answer,"");
+ if ( mapset == NULL) {
+ G_fatal_error ("Input map does not exist in the current location.");
+ }
+ if (G_raster_map_is_fp (parm.input->answer, mapset)) {
+ G_fatal_error ("Input map is a floating point raster.\nOnly integer rasters are allowed as input.");
+ }
+
+ /* check if sample sites file exists */
+ if (G_find_file ("vector", parm.sites->answer, "") == NULL)
+ {
+ G_fatal_error
+ ("Vector map with samples does not exist.");
+ }
+
+ /* construct default output filename if none given */
+ if (parm.output->answer == NULL)
+ {
+ sprintf (result_str, "bpn.%s", parm.input->answer);
+ parm.output->answer = result_str;
+ G_warning ("Using default base name '%s'\n", result_str);
+ }
+
+ /* check if a legal file name was given for output map */
+ /* this overwrites existing maps! */
+ if (G_legal_filename (parm.output->answer) == -1)
+ {
+ G_fatal_error
+ ("Base name for result maps invalid (contains special chars, whitespace or other).");
+ }
+
+
+ /* check if logfile is wanted and ... */
+ if (parm.logfile->answer != NULL)
+ {
+ /* ... check if a legal file name was given for logfile */
+ if (G_legal_filename (parm.logfile->answer) == -1)
+ {
+ G_fatal_error
+ ("Logfile name invalid (contains special chars, whitespace or other).");
+ }
+ }
+
+ /* set cachesize */
+ cachesize = atoi (parm.cachesize->answer);
+ if ( (cachesize<-1) || (cachesize > G_window_rows ()) ) {
+ /* if cache size is invalid, just set to auto-mode (-1) */
+ G_warning ("Invalid cache size requested. Must be between 0 and %i or -1 (auto).", G_window_rows());
+ cachesize = -1;
+ }
+
+ cats = GT_get_stats (parm.input->answer,mapset,&null_count, &nocat_count, show_progress);
+ if ( cats < 0 ) {
+ G_fatal_error ("Could not stat input map. Do you have read access?");
+ }
+ if ( cats == 0 ) {
+ G_fatal_error ("No categories defined in input map.");
+ }
+ if ( nocat_count > 0 ) {
+ G_fatal_error ("Input map contains cells that do not map to categories.\nUse 'r.categorize' to produce a fully categorized input map.");
+ }
+
+
+ /* check all sources of BIAS supplied by the user */
+ check_bias_maps (parm.n_bias_maps->answers, flag.quiet->answer);
+
+ /*
+ if ( parm.s_bias_atts->answers != NULL ) {
+ bias_atts = check_bias_atts (parm.sites->answer,parm.s_bias_atts->answers, flag.quiet->answer);
+ }
+ */
+
+ /* open logfile */
+ if (parm.logfile->answer != NULL)
+ {
+ if (flag.append->answer) {
+ if (fopen (parm.logfile->answer, "r") == NULL) {
+ logfile = fopen (parm.logfile->answer, "w+");
+ } else {
+ logfile = fopen (parm.logfile->answer, "a");
+ if (logfile == NULL) {
+ G_fatal_error ("Logfile error: '%s'.", strerror (errno));
+ }
+ fprintf (logfile,"\n\n * * * * * \n\n");
+ }
+ } else {
+ logfile = fopen (parm.logfile->answer, "w+");
+ }
+ if (logfile == NULL) {
+ G_fatal_error ("Logfile error: '%s'.", strerror (errno));
+ }
+ else
+ {
+ debug_mode = 1;
+ fprintf (logfile,"This is %s version %.2f\n",argv[0],PROGVERSION);
+ systime = time (NULL);
+ fprintf (logfile,"Calculation started on %s",ctime(&systime));
+ fprintf (logfile,"\tlocation = %s\n",G_location());
+ fprintf (logfile,"\tmapset = %s\n",G_mapset());
+ fprintf (logfile,"\tinput map = %s\n",parm.input->answer);
+ fprintf (logfile,"\tsites file = %s\n",parm.sites->answer);
+ fprintf (logfile,"Results will be stored in '%s.<SITE|NOSITE|SITE.NOSITE>'\n\n",parm.output->answer);
+ fflush (logfile);
+ }
+ }
+
+
+ /* do the actual calculations */
+ write_BPNs (parm.input->answer, mapset, parm.sites->answer, parm.n_bias_maps->answers, parm.output->answer,
+ (float) atof (parm.p0_threshold->answer), parm.colormap->answer, show_progress);
+
+ /* write all that remains to be written to logfile */
+ if (parm.logfile->answer != NULL) {
+ /* write advisory if necessary */
+ if ( WARN_ON ) {
+ fprintf (logfile,"\nAdvice on this calculation:\n");
+ if ( WARN_N_TO_SMALL ) {
+ fprintf (logfile,"\tIncrease sample size to at least %i\n",MIN_SAMPLE_SIZE);
+ }
+ }
+ /* write processing time to logfile */
+ proctime = clock ();
+ timeused = (unsigned long) proctime / CLOCKS_PER_SEC;
+ days = timeused / 86400;
+ hours = (timeused - (days * 86400)) / 3600;
+ mins = (timeused - (days * 86400) - (hours * 3600)) / 60;
+ secs = (timeused - (days * 86400) - (hours * 3600) - (mins * 60));
+ systime = time (NULL);
+ fprintf (logfile,"\nCalculation finished on %s",ctime(&systime));
+ fprintf (logfile,"Processing time: %id, %ih, %im, %is\n",
+ days, hours, mins, secs );
+ fflush (logfile);
+ }
+
+ /* write some metadata to the output files' histories */
+ G_short_history (parm.input->answer,"raster",&hist);
+
+ strcpy (hist.datsrc_1, parm.input->answer);
+ strcpy (hist.keywrd, "Generated by r.dst.bpn.");
+ hist.edlinecnt = 2;
+
+ strcpy (hist.edhist[0], "BPN values for hypothesis {h1}='site present'.");
+ sprintf (result_str,"Significance threshold = %.3f",atof (parm.p0_threshold->answer));
+ strcpy (hist.edhist[1], result_str);
+ sprintf (result_str,"%s.SITE", parm.output->answer);
+ G_write_history (result_str, &hist);
+
+ strcpy (hist.edhist[0], "BPN values for hypothesis {h2}='no site present'.");
+ sprintf (result_str,"Significance threshold = %.3f",atof (parm.p0_threshold->answer));
+ strcpy (hist.edhist[1], result_str);
+ sprintf (result_str,"%s.NOSITE", parm.output->answer);
+ G_write_history (result_str, &hist);
+
+ strcpy (hist.edhist[0], "BPN values for hypothesis {h1,h2}='site present OR no site present'.");
+ sprintf (result_str,"Significance threshold = %.3f",atof (parm.p0_threshold->answer));
+ strcpy (hist.edhist[1], result_str);
+ sprintf (result_str,"%s.SITE.NOSITE", parm.output->answer);
+ G_write_history (result_str, &hist);
+
+ return (EXIT_SUCCESS);
+}
Property changes on: grass-addons/grass6/dst/raster/r.dst.predict.bpn/main.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.predict.bpn/r.dst.bpn.001.png
===================================================================
(Binary files differ)
Property changes on: grass-addons/grass6/dst/raster/r.dst.predict.bpn/r.dst.bpn.001.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Added: grass-addons/grass6/dst/raster/r.dst.predict.run/Makefile
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.predict.run/Makefile (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.predict.run/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,11 @@
+MODULE_TOPDIR = ../..
+
+PGM = dst.predict.run
+
+LIBES = $(GISLIB) $(DATETIMELIB)
+EXTRA_CFLAGS = -I../../include
+
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
Added: grass-addons/grass6/dst/raster/r.dst.predict.run/description.html
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.predict.run/description.html (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.predict.run/description.html 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<TITLE>dst.predict</TITLE>
+
+<body bgcolor="white">
+
+
+<h2>DESCRIPTION</h2>
+
+This program calculates a Dempster-Shafer Theory (DST) predictive model.
+If you have need for a flexible spatial predictive modelling framework but do not know what DST is, please
+refer to the manual page of <EM><A HREF="dst.combine.html">dst.combine</A></EM> for an introduction.
+<p>
+Simply specify your raster evidence maps, sample points and a prefix for your result maps and a basic
+DST predictive model will be calculated. For this, <em>dst.predict</em> will invoke the commands
+<EM><A HREF="r.dst.bpa.html">r.dst.bpa</A></EM>,
+<EM><A HREF="dst.create.html">dst.create</A></EM>,
+<EM><A HREF="dst.source.html">dst.source</A></EM>,
+<EM><A HREF="dst.update.html">dst.update</EM></A> and
+<EM><A HREF="dst.combine.html">dst.combine</EM></A><br> automatically with appropriate arguments.
+<p>
+You can choose to calculate further DST metrics by using the <em>value=</em> option. Refer to the
+mannual page of <EM><A HREF="dst.combine.html">dst.combine</A></EM> for their meanings.
+<p>
+You can also specify one or more maps that encode bias for the "NO SITE" hypothesis. See the manual
+page of <EM><A HREF="r.dst.bpa.html">r.dst.bpa</A></EM> for an explanation of how this works.
+<p>
+You can also specify attributes that encode bias for the "SITE" hypothesis. Again, see the manual
+page of <EM><A HREF="r.dst.bpa.html">r.dst.bpa</A></EM> for an explanation of how this works.
+<strong>(Note: The <em>sbias=</em> option is currently broken. Do not use it!)</strong>
+<p>
+If you wish, the program will create an ASCII log file with the combined log output of all invoked
+commands.
+<p>
+You can specify the <em>-r</em> flage to remove all output maps pertaining to the NULL hypothesis.
+These are usually only of mathematical interest and can safely be deleted.
+<p>
+If you want to use this frontend for exploratory modelling, you might find it more convenient to
+dump model parameters to a shell script which can be used to re-run the model at any time and
+adjust parameters more efficiently. Use the <em>script=</em> option to specify a filename
+for the script.
+
+<h3>Notes</h3>
+This program was developed as part of the GRASS 5 DST Predictive Modelling Toolkit.<br>
+The <em>sbias=</em> option is currently broken. Do not use it!
+
+<h3>SEE ALSO</h3>
+<EM><A HREF="dst.combine.html">dst.update</EM></A><br>
+<EM><A HREF="dst.create.html">dst.create</A></EM><br>
+<EM><A HREF="dst.source.html">dst.source</A></EM><br>
+<EM><A HREF="dst.update.html">dst.update</EM></A><br>
+<EM><A HREF="r.dst.bpa.html">r.dst.bpa</A></EM>
+<h3>AUTHOR</h3>
+Benjamin Ducke,<br>
+University of Kiel, Germany<br>
+<i>Last changed: 2005/07/21</i>
+</body>
+</html>
Property changes on: grass-addons/grass6/dst/raster/r.dst.predict.run/description.html
___________________________________________________________________
Added: svn:mime-type
+ text/html
Added: svn:keywords
+ Author Date Id
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/raster/r.dst.predict.run/main.c
===================================================================
--- grass-addons/grass6/dst/raster/r.dst.predict.run/main.c (rev 0)
+++ grass-addons/grass6/dst/raster/r.dst.predict.run/main.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,420 @@
+/* dst.predict */
+/* Part of the GRASS Dempster-Shafer Predictive Modelling Toolkit (DST-PMT) */
+
+/* Purpose: A wrapper program to provide a straight-forward GUI for predictive
+ modelling using r.dst.bpa and dst.combine modules.
+
+ This file is licensed under the GPL (version 2 or later at your option)
+ see: http://www.gnu.org/copyleft/gpl.html* /
+
+ (c) Benjamin Ducke 2006
+ benducke at compuserve.de
+
+*/
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include <grass/gis.h>
+
+#define PROGVERSION 1.5
+
+char *PROG_BPA = "r.dst.bpn";
+char *PROG_CREATE = "m.dst.create";
+char *PROG_UPDATE = "m.dst.update";
+char *PROG_SOURCE = "m.dst.source";
+char *PROG_COMBINE = "m.dst.combine";
+char *PROG_REMOVE = "g.remove";
+
+int SCRIPTING = 0;
+FILE *SCRIPT;
+
+/* executes a GRASS module */
+void exec_module (char* module, char *arguments) {
+
+ int error = 0;
+ char sysstr [2048];
+
+ if ( getenv("GISBASE") == NULL ) {
+ G_fatal_error ("GISBASE not set. Unable to call GRASS modules.");
+ }
+
+ G_strcpy (sysstr, getenv("GISBASE"));
+ G_strcat (sysstr, "/bin/");
+ G_strcat (sysstr, module);
+ G_strcat (sysstr, " ");
+ G_strcat (sysstr, arguments);
+
+ if ( SCRIPTING ) {
+ fprintf ( SCRIPT, "%s\n", sysstr );
+ } else {
+ error = system (sysstr);
+ if ( error != 0 ) {
+ G_fatal_error ("Module '%s' terminated with an error.", module);
+ }
+ }
+
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ struct GModule *module;
+ struct
+ {
+ struct Option *input;
+ struct Option *sites;
+ struct Option *vals;
+ struct Option *s_bias_atts;
+ struct Option *n_bias_maps;
+ struct Option *output;
+ struct Option *logfile;
+ struct Option *script;
+ struct Option *cachesize;
+ }
+ parm;
+
+ struct
+ {
+ struct Flag *quiet;
+ struct Flag *remove;
+ }
+ flag;
+
+ char *sysstr;
+ char *biasmaps;
+ int i, num_evidences;
+
+ /* setup some basic GIS stuff */
+ G_gisinit (argv[0]);
+ module = G_define_module ();
+ module->description = "Dempster-Shafer Theory predictive modelling";
+ /* do not pause after a warning message was displayed */
+ G_sleep_on_error (0);
+
+ /* Parameters: */
+ /* input = a map that shows the natural (complete) distribution */
+ /* of a feature. */
+ parm.input = G_define_standard_option (G_OPT_R_INPUT);
+ parm.input->key = "raster";
+ parm.input->type = TYPE_STRING;
+ parm.input->required = YES;
+ parm.input->multiple = YES;
+ parm.input->gisprompt = "old,cell,raster";
+ parm.input->description = "Raster evidence map(s)";
+
+ /* site map with known sites */
+ parm.sites = G_define_standard_option (G_OPT_V_INPUT);
+ parm.sites->key = "sites";
+ parm.sites->type = TYPE_STRING;
+ parm.sites->required = YES;
+ parm.sites->description = "Vector map with site points";
+
+ parm.vals = G_define_option ();
+ parm.vals->key = "values";
+ parm.vals->type = TYPE_STRING;
+ parm.vals->required = NO;
+ parm.vals->multiple = YES;
+ parm.vals->options = "bel,pl,doubt,common,bint,woc,maxbpa,minbpa,maxsrc,minsrc";
+ parm.vals->answer = "bel";
+ parm.vals->description = "Dempster-Shafer values to map";
+
+ parm.n_bias_maps = G_define_standard_option (G_OPT_R_INPUT);
+ parm.n_bias_maps->key = "nbias";
+ parm.n_bias_maps->required = NO;
+ parm.n_bias_maps->multiple = YES;
+ parm.n_bias_maps->gisprompt = "old,fcell,raster";
+ parm.n_bias_maps->description = "Raster map(s) with 'NO SITE' bias [0..1]";
+
+ /*
+ parm.s_bias_atts = G_define_option ();
+ parm.s_bias_atts->key = "sbias";
+ parm.s_bias_atts->required = NO;
+ parm.s_bias_atts->multiple = YES;
+ parm.s_bias_atts->description = "Vector attributes with 'SITE' bias [0..1]";
+ */
+
+ /* name of output maps/files */
+ parm.output = G_define_option ();
+ parm.output->key = "output";
+ parm.output->type = TYPE_STRING;
+ parm.output->required = YES;
+ parm.output->description = "Prefix for result maps and logfiles";
+
+ /* Name of logfile. If given, output will be logged */
+ /* to this file. */
+ parm.logfile = G_define_option ();
+ parm.logfile->key = "logfile";
+ parm.logfile->type = TYPE_STRING;
+ parm.logfile->required = NO;
+ parm.logfile->description = "ASCII file for log";
+
+ /* if this filename is given, dump model building command lines
+ to a script instead of executing directly */
+ parm.script = G_define_option ();
+ parm.script->key = "script";
+ parm.script->type = TYPE_STRING;
+ parm.script->required = NO;
+ parm.script->description = "Dump model commands to shell script";
+
+ /* quiet operation? */
+ flag.quiet = G_define_flag ();
+ flag.quiet->key = 'q';
+ flag.quiet->description = "Disable on-screen progress display";
+
+ /* append output to existing logfile ? */
+ flag.remove = G_define_flag ();
+ flag.remove->key = 'r';
+ flag.remove->description = "Remove NULL hypothesis maps";
+
+ /* parse command line */
+ if (G_parser (argc, argv))
+ {
+ exit (-1);
+ }
+
+ /* see if user wants to create a script instead of executing directly */
+ if ( parm.script->answer != NULL ) {
+ SCRIPT = fopen ( parm.script->answer, "w+" );
+ if ( SCRIPT == NULL ) {
+ G_fatal_error ("Unable to create script file: %s.", strerror (errno));
+ }
+ SCRIPTING = 1;
+ fprintf ( SCRIPT, "#!/bin/sh\n" );
+ }
+
+ /* check how many evidence maps the user has supplied */
+ num_evidences = 0;
+ while (parm.input->answers[num_evidences] != NULL) {
+ num_evidences ++;
+ }
+
+ /* now call external programs to do the job! */
+ sysstr = G_calloc (2048, sizeof(char));
+ biasmaps = G_calloc (2048, sizeof(char));
+
+ /* create BPA maps */
+ if (parm.n_bias_maps->answers != NULL) {
+ i = 0;
+ while (parm.n_bias_maps->answers[i] != NULL) {
+ if (i>0) {
+ G_strcat (biasmaps,",");
+ }
+ G_strcat (biasmaps,parm.n_bias_maps->answers[i]);
+ i ++;
+ }
+ }
+
+ for (i=0; i<num_evidences; i++) {
+ fprintf ( stderr, "Generating BPNs for evidence %i\n", i );
+ sprintf (sysstr,"raster=%s sites=%s output=%s.bpa.%s", parm.input->answers[i],
+ parm.sites->answer,
+ parm.output->answer,
+ strtok(parm.input->answers[i],"@"));
+ if (parm.n_bias_maps->answers != NULL) {
+ G_strcat (sysstr, " nbias=");
+ G_strcat (sysstr, biasmaps);
+ }
+ if (parm.logfile->answer != NULL) {
+ if (i == 0) {
+ G_strcat (sysstr, " log=");
+ } else {
+ G_strcat (sysstr, " -a log=");
+ }
+ G_strcat (sysstr, parm.logfile->answer);
+ }
+
+ if (flag.quiet->answer) {
+ G_strcat (sysstr, " -q");
+ }
+ exec_module (PROG_BPA,sysstr);
+ }
+ /* END (create BPA mapse) */
+
+
+ /* create DST knowledge base file and add entries */
+ sprintf (sysstr,"%s", parm.output->answer);
+ exec_module (PROG_CREATE,sysstr);
+ sprintf (sysstr,"%s add=SITE",parm.output->answer);
+ exec_module (PROG_UPDATE,sysstr);
+ sprintf (sysstr,"%s add=NOSITE",parm.output->answer);
+ exec_module (PROG_UPDATE,sysstr);
+ for (i=0; i<num_evidences; i++) {
+ sprintf (sysstr,"%s rast=%s.bpa.%s.SITE hyp=SITE",
+ parm.output->answer,
+ parm.output->answer,
+ strtok(parm.input->answers[i],"@"));
+ exec_module (PROG_UPDATE,sysstr);
+
+ sprintf (sysstr,"%s rast=%s.bpa.%s.NOSITE hyp=NOSITE",
+ parm.output->answer,
+ parm.output->answer,
+ strtok(parm.input->answers[i],"@"));
+ exec_module (PROG_UPDATE,sysstr);
+
+ sprintf (sysstr,"%s rast=%s.bpa.%s.SITE.NOSITE hyp=SITE,NOSITE",
+ parm.output->answer,
+ parm.output->answer,
+ strtok(parm.input->answers[i],"@"));
+ exec_module (PROG_UPDATE,sysstr);
+
+ sprintf (sysstr,"%s add=%s",
+ parm.output->answer,
+ strtok(parm.input->answers[i],"@"));
+ exec_module (PROG_SOURCE,sysstr);
+
+ sprintf (sysstr,"%s source=%s rast=%s.bpa.%s.SITE hyp=SITE",
+ parm.output->answer,
+ strtok(parm.input->answers[i],"@"),
+ parm.output->answer,
+ strtok(parm.input->answers[i],"@"));
+ exec_module (PROG_SOURCE,sysstr);
+
+ sprintf (sysstr,"%s source=%s rast=%s.bpa.%s.NOSITE hyp=NOSITE",
+ parm.output->answer,
+ strtok(parm.input->answers[i],"@"),
+ parm.output->answer,
+ strtok(parm.input->answers[i],"@"));
+ exec_module (PROG_SOURCE,sysstr);
+
+ sprintf (sysstr,"%s source=%s rast=%s.bpa.%s.SITE.NOSITE hyp=SITE,NOSITE",
+ parm.output->answer,
+ strtok(parm.input->answers[i],"@"),
+ parm.output->answer,
+ strtok(parm.input->answers[i],"@"));
+ exec_module (PROG_SOURCE,sysstr);
+ }
+ /* END (build knowledge base file) */
+
+
+ /* now combine evidences into result maps */
+ sprintf (sysstr,"%s output=%s.dst",
+ parm.output->answer,
+ parm.output->answer);
+
+ if (parm.vals->answers != NULL) {
+ G_strcat (sysstr," values=");
+ i=0;
+ while (parm.vals->answers[i] != NULL) {
+ if (i>0) {
+ G_strcat (sysstr, ",");
+ }
+ G_strcat (sysstr, parm.vals->answers[i]);
+ i++;
+ }
+ }
+
+ if (parm.logfile->answer != NULL) {
+ G_strcat (sysstr, " -a log=");
+ G_strcat (sysstr, parm.logfile->answer);
+ }
+ exec_module (PROG_COMBINE,sysstr);
+ /* END (DST combination) */
+
+ /* get rid of NULL hypothesis maps */
+ if (flag.remove->answer) {
+ sprintf (sysstr,"%s.dst.NULL.bel",parm.output->answer);
+ G_remove ("fcell",sysstr);
+ G_remove ("cell",sysstr);
+ G_remove ("cats",sysstr);
+ G_remove ("cellhd",sysstr);
+ G_remove ("cell_misc",sysstr);
+ G_remove ("colr",sysstr);
+ G_remove ("colr2",sysstr);
+ G_remove ("hist",sysstr);
+
+ sprintf (sysstr,"%s.dst.NULL.pl",parm.output->answer);
+ G_remove ("fcell",sysstr);
+ G_remove ("cell",sysstr);
+ G_remove ("cats",sysstr);
+ G_remove ("cellhd",sysstr);
+ G_remove ("cell_misc",sysstr);
+ G_remove ("colr",sysstr);
+ G_remove ("colr2",sysstr);
+ G_remove ("hist",sysstr);
+
+ sprintf (sysstr,"%s.dst.NULL.doubt",parm.output->answer);
+ G_remove ("fcell",sysstr);
+ G_remove ("cell",sysstr);
+ G_remove ("cats",sysstr);
+ G_remove ("cellhd",sysstr);
+ G_remove ("cell_misc",sysstr);
+ G_remove ("colr",sysstr);
+ G_remove ("colr2",sysstr);
+ G_remove ("hist",sysstr);
+
+ sprintf (sysstr,"%s.dst.NULL.common",parm.output->answer);
+ G_remove ("fcell",sysstr);
+ G_remove ("cell",sysstr);
+ G_remove ("cats",sysstr);
+ G_remove ("cellhd",sysstr);
+ G_remove ("cell_misc",sysstr);
+ G_remove ("colr",sysstr);
+ G_remove ("colr2",sysstr);
+ G_remove ("hist",sysstr);
+
+ sprintf (sysstr,"%s.dst.NULL.bint",parm.output->answer);
+ G_remove ("fcell",sysstr);
+ G_remove ("cell",sysstr);
+ G_remove ("cats",sysstr);
+ G_remove ("cellhd",sysstr);
+ G_remove ("cell_misc",sysstr);
+ G_remove ("colr",sysstr);
+ G_remove ("colr2",sysstr);
+ G_remove ("hist",sysstr);
+
+ sprintf (sysstr,"%s.dst.NULL.maxbpa",parm.output->answer);
+ G_remove ("fcell",sysstr);
+ G_remove ("cell",sysstr);
+ G_remove ("cats",sysstr);
+ G_remove ("cellhd",sysstr);
+ G_remove ("cell_misc",sysstr);
+ G_remove ("colr",sysstr);
+ G_remove ("colr2",sysstr);
+ G_remove ("hist",sysstr);
+
+ sprintf (sysstr,"%s.dst.NULL.minbpa",parm.output->answer);
+ G_remove ("fcell",sysstr);
+ G_remove ("cell",sysstr);
+ G_remove ("cats",sysstr);
+ G_remove ("cellhd",sysstr);
+ G_remove ("cell_misc",sysstr);
+ G_remove ("colr",sysstr);
+ G_remove ("colr2",sysstr);
+ G_remove ("hist",sysstr);
+
+ sprintf (sysstr,"%s.dst.NULL.maxsrc",parm.output->answer);
+ G_remove ("fcell",sysstr);
+ G_remove ("cell",sysstr);
+ G_remove ("cats",sysstr);
+ G_remove ("cellhd",sysstr);
+ G_remove ("cell_misc",sysstr);
+ G_remove ("colr",sysstr);
+ G_remove ("colr2",sysstr);
+ G_remove ("hist",sysstr);
+
+ sprintf (sysstr,"%s.dst.NULL.minsrc",parm.output->answer);
+ G_remove ("fcell",sysstr);
+ G_remove ("cell",sysstr);
+ G_remove ("cats",sysstr);
+ G_remove ("cellhd",sysstr);
+ G_remove ("cell_misc",sysstr);
+ G_remove ("colr",sysstr);
+ G_remove ("colr2",sysstr);
+ G_remove ("hist",sysstr);
+ }
+ /* END (delete NULL hypothesis maps) */
+
+ G_free (sysstr);
+
+ if ( SCRIPTING ) {
+ fclose ( SCRIPT );
+ }
+
+ return (EXIT_SUCCESS);
+}
Property changes on: grass-addons/grass6/dst/raster/r.dst.predict.run/main.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/vector/Makefile
===================================================================
--- grass-addons/grass6/dst/vector/Makefile (rev 0)
+++ grass-addons/grass6/dst/vector/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,13 @@
+MODULE_TOPDIR = ..
+
+SUBDIRS = \
+ v.random.sample \
+ v.report.dist
+
+include $(MODULE_TOPDIR)/include/Make/Dir.make
+
+default: htmldir
+
+htmldir: subdirs
+
+clean: cleansubdirs
Added: grass-addons/grass6/dst/vector/v.random.sample/Makefile
===================================================================
--- grass-addons/grass6/dst/vector/v.random.sample/Makefile (rev 0)
+++ grass-addons/grass6/dst/vector/v.random.sample/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,11 @@
+MODULE_TOPDIR = ../..
+
+PGM = v.random.sample
+
+GT_LIB_RAST = -lgt_raster
+LIBES = $(GISLIB) $(DATETIMELIB) $(VECTLIB) $(GT_LIB_RAST)
+EXTRA_CFLAGS = -I../../include
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
Property changes on: grass-addons/grass6/dst/vector/v.random.sample/Makefile
___________________________________________________________________
Added: svn:executable
+ *
Added: grass-addons/grass6/dst/vector/v.random.sample/description.html
===================================================================
--- grass-addons/grass6/dst/vector/v.random.sample/description.html (rev 0)
+++ grass-addons/grass6/dst/vector/v.random.sample/description.html 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<TITLE>v.random.sample</TITLE>
+
+<body bgcolor="white">
+
+
+<h2>DESCRIPTION</h2>
+
+This command creates a random sample of n% of the sites in a GRASS sites map. The current
+process id (pid) and system time are used as seed for the random number generator.
+If a raster map is specified, then only sites falling on non-NULL cells of that raster map
+will be included in the sample.
+The program will abort with an error message, if the number of valid sites is too small for
+generating the sample.
+<p></p>
+
+<h3>Flags</h3>
+<dl>
+<dt><strong>-a</strong></dt>
+ <dd>Also draw sites from outside the current region's limits. this option does not
+ make much sense, if you also specify a raster mask with <em>raster=[name]</em>.</dd>
+<dt><strong>-q</strong></dt>
+ <dd>Quiet operation: do not display progress on screen.</dd>
+</dl>
+
+<h3>Parameters</h3>
+<dl>
+<dt><B>input=</B><EM>name</EM></dt>
+ <dd>Sites map to draw sample from.</dd>
+<dt><B>output=</B><EM>name</EM></dt>
+ <dd>Sites map to store random sample in.</dd>
+<dt><B>size=</B><EM>value</EM></dt>
+ <dd>Size of the sample to generate in percent of input sites.</dd>
+<dt><B>raster=</B><EM>name</EM></dt>
+ <dd>Specify a raster to act as a mask: only sites that fall into non-NULL cells of this
+ raster have a chance to end up in the random sample.
+ </dd>
+<dt><B>cachesize=</B><EM>value</EM></dt>
+ <dd>On systems with lots of memory, setting cachesize to the number of rows in the current region
+ can speed up operations, because the input raster map can be kept in memory.
+ The default of '-1' lets the program figure out a good size for the cache itself.
+ This option is only useful if you also specify a raster mask with <em>raster=[name]</em>.
+ </dd>
+</dl>
+
+<h3>Notes</h3>
+This program was originally developed as part of the GRASS 5 DST Predictive Modelling Toolkit
+
+<h3>AUTHOR</h3>
+Benjamin Ducke,<br>
+University of Kiel, Germany<br>
+<i>Last changed: 2005/21/07</i>
+</body>
+</html>
Property changes on: grass-addons/grass6/dst/vector/v.random.sample/description.html
___________________________________________________________________
Added: svn:mime-type
+ text/html
Added: svn:keywords
+ Author Date Id
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/vector/v.random.sample/main.c
===================================================================
--- grass-addons/grass6/dst/vector/v.random.sample/main.c (rev 0)
+++ grass-addons/grass6/dst/vector/v.random.sample/main.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,391 @@
+/* s.random.sample */
+/* Generate a random subset of vector points. */
+
+/* TODO
+ - specifying -a automatically disregards the map as well.
+ Is that good behaviour?
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <grass/gis.h>
+#include <grass/Vect.h>
+
+#include "gt/rowcache.h"
+
+#define PROGVERSION 1.1
+
+extern int errno;
+int cachesize;
+
+int debug_mode = 0; /* 1 to enable writing debug output to logfile */
+
+/* checks if user-supplied parameters are valid */
+int
+check_parms (char *map_answer, char *input_answer, char *output_answer, int all )
+{
+
+ if ( map_answer != NULL ) {
+ if ((G_find_file ("fcell", map_answer, "") == NULL)
+ && (G_find_file ("dcell", map_answer, "") == NULL)
+ && (G_find_file ("cell", map_answer, "") == NULL))
+ {
+ /* no coverage map found */
+ G_fatal_error
+ ("No raster map exists with the given name.");
+ }
+
+ /* specifying all means to disregard the map! */
+ if ( all == 1 ) {
+ G_warning ("Map was specified, but the -a flag disregards map values!\n Your results might not be what you expect.");
+ }
+ }
+
+ /* check if sample sites exist */
+ if (G_find_file ("vector", input_answer, "") == NULL)
+ {
+ G_fatal_error
+ ("No sample/sites list exists with the given name!");
+ }
+
+ /* check if a legal file name was given for output map
+ this just overwrites existing sites */
+ if (G_legal_filename (output_answer) == -1)
+ {
+ G_fatal_error
+ ("Name chosen for result map is not a valid file name!");
+ }
+
+ /* return raster mode to caller */
+ if ( map_answer != NULL ) {
+ return (G_raster_map_type (map_answer,""));
+ }
+ else return (-1);
+}
+
+
+/* creates a vector site file in the user's mapset that contains */
+/* 'percentage' objects randomly picked from input map */
+/* useful to create randomised samples for statistical tests */
+void do_split_sample ( char *input, char *output, int in_types, double percentage, char *map,
+ int all, int processing_mode, int quiet) {
+ CELL *cellbuf;
+ DCELL *dcellbuf;
+ GT_Row_cache_t *cache;
+ int fd;
+ int i,j,k,l;
+ int no_sites;
+ int sites_tried = 0;
+ struct Cell_head region;
+ int error;
+ char *mapset, errmsg [200];
+ unsigned int *taken; /* this is an array of 0/1 which signals, if
+ a certain site has already been 'drawn' */
+ long row_idx, col_idx;
+ struct Map_info in_vect_map;
+ struct Map_info out_vect_map;
+ struct line_pnts *vect_points;
+ struct line_cats *vect_cats;
+ double x,y,z;
+ int n_points = 1;
+ int cur_type;
+
+
+ cellbuf = NULL;
+ dcellbuf = NULL;
+ cache = NULL;
+
+ /* get current region */
+ G_get_window (®ion);
+
+
+ /* attempt to create new file for output */
+ Vect_set_open_level (2);
+ if (0 > Vect_open_new (&out_vect_map, output, 0) ) {
+ G_fatal_error ("Could not open output vector map.\n");
+ }
+
+ /* open input vector map */
+ if ((mapset = G_find_vector2 (input, "")) == NULL) {
+ sprintf (errmsg, "Could not find input %s\n", input);
+ G_fatal_error ("%s",errmsg);
+ }
+
+ if (1 > Vect_open_old (&in_vect_map, input, "")) {
+ sprintf (errmsg, "Could not open input map %s.\n", input);
+ G_fatal_error ("%s",errmsg);
+ }
+
+ vect_points = Vect_new_line_struct ();
+ vect_cats = Vect_new_cats_struct ();
+
+ /* set constraints specified */
+ if (in_types != 0) {
+ Vect_set_constraint_type (&in_vect_map, in_types);
+ }
+ if (all != 1) {
+ Vect_set_constraint_region (&in_vect_map, region.north, region.south,
+ region.east, region.west, 0.0, 0.0);
+ }
+
+
+ /* get total number of objects with constraints */
+ i = 0;
+ while ((cur_type = Vect_read_next_line (&in_vect_map, vect_points, vect_cats) > 0)) {
+ i ++;
+ }
+
+ k = ( ((float) i/100)) * percentage; /* k now has the number of objects wanted */
+
+ if ( quiet != 1 ) {
+ fprintf (stderr,"Creating randomised sample of size n = %i.\n",k);
+ }
+
+ /* now, we need to acquire exactly 'k' random objects that fall in NON-NULL */
+ /* coverage raster cells. */
+ taken = G_calloc (i, sizeof (unsigned int));
+ for ( l = 0; l < k; l ++ ) {
+ taken[l] = 0;
+ }
+ no_sites = i; /* store this for later use */
+
+ /* does user want to filter objects through a raster map? */
+ if ( map != NULL) {
+ /* open raster map */
+ fd = G_open_cell_old (map, G_find_cell (map, ""));
+ if (fd < 0)
+ {
+ G_fatal_error ("Could not open raster map for reading!\n");
+ }
+ /* allocate cache and buffer, according to type of coverage */
+ if ( processing_mode == CELL_TYPE) {
+ /* INT coverage */
+ cache = (GT_Row_cache_t *) G_malloc (sizeof (GT_Row_cache_t));
+ /* TODO: check error value */
+ error = GT_RC_open (cache, cachesize, fd, CELL_TYPE);
+ cellbuf = G_allocate_raster_buf (CELL_TYPE);
+ }
+ if ( (processing_mode == FCELL_TYPE) || (processing_mode == DCELL_TYPE) ) {
+ /* FP coverage */
+ cache = (GT_Row_cache_t *) G_malloc (sizeof (GT_Row_cache_t));
+ /* TODO: check error value */
+ error = GT_RC_open (cache, cachesize, fd, DCELL_TYPE);
+ dcellbuf = G_allocate_raster_buf (DCELL_TYPE);
+ }
+ }
+
+ srand ( ((unsigned int) time (NULL)) + getpid()); /* set seed for random number generator from system time and process ID*/
+ i = 0;
+
+ /* MAIN LOOP */
+ while ( i < k ) {
+ /* get a random index, but one that was not taken already */
+ l = 0;
+ while ( l == 0 ) {
+ j = rand () % ( no_sites - 1 + 1) + 1; /* j now has the random position to try */
+ if ( taken[j-1] == 0 ) {
+ l = 1; /* exit loop */
+ }
+ }
+ taken [j-1] = 1; /* mark this index as 'taken' */
+ sites_tried ++; /* keep track of this so we do not enter an infinite loop */
+ if ( sites_tried > no_sites ) {
+ /* could not create a large enough sample */
+ G_fatal_error ("Could not find enough objects for split sampling.\nDecrease split sample size.\n");
+ }
+ /* get next vector object */
+ cur_type = Vect_read_line (&in_vect_map, vect_points, vect_cats, j);
+ if (cur_type < 0 ) {
+ G_fatal_error ("Error reading vector map: premature EOF.\n");
+ }
+ /* now, check if coverage under site is NON-NULL and within region */
+ /* convert site northing to row! */
+ /* for this check, we use only the first pair of coordinates! */
+ Vect_copy_pnts_to_xyz (vect_points, &x, &y, &z, &n_points);
+ row_idx =
+ (long) G_northing_to_row (y,
+ ®ion);
+
+ col_idx =
+ (long) G_easting_to_col (x,
+ ®ion);
+ /* do region check, first... OBSOLETE */
+ /* read row from cache and check for NULL */
+ /* if required */
+ if ( map != NULL ) {
+ if ( processing_mode == CELL_TYPE ) {
+ cellbuf = GT_RC_get (cache, row_idx);
+ if (!G_is_c_null_value(&cellbuf[col_idx])) {
+ i ++;
+ Vect_write_line (&out_vect_map, cur_type,
+ vect_points, vect_cats );
+ fflush (stdout);
+ }
+ }
+ if ( (processing_mode == FCELL_TYPE) || (processing_mode == DCELL_TYPE) ) {
+ dcellbuf = GT_RC_get (cache, row_idx);
+ if (!G_is_d_null_value(&dcellbuf[col_idx])) {
+ i ++;
+ Vect_write_line (&out_vect_map, cur_type,
+ vect_points, vect_cats );
+ fflush (stdout);
+ }
+ }
+ } else {
+ i ++;
+ Vect_write_line (&out_vect_map, GV_POINT,
+ vect_points, vect_cats );
+ fflush (stdout);
+ }
+ /* disregard region setting and map, if -a flag is given */
+ if ( all == 1 ) {
+ i ++;
+ Vect_write_line (&out_vect_map, cur_type,
+ vect_points, vect_cats );
+ fflush (stdout);
+ }
+
+ if ( quiet != 1 ) {
+ G_percent(i,k,1);
+ }
+ }
+ /* END OF MAIN LOOP */
+ Vect_copy_head_data (&in_vect_map, &out_vect_map);
+ fprintf (stdout, "Building topology information for output map.\n");
+ Vect_build (&out_vect_map);
+ Vect_close (&in_vect_map);
+ Vect_close (&out_vect_map);
+
+ if ( map != NULL ) {
+ /* close cache, free buffers! */
+ GT_RC_close (cache);
+ if ( processing_mode == CELL_TYPE ) {
+ G_free (cellbuf);
+ }
+ if ( (processing_mode == FCELL_TYPE) || (processing_mode == DCELL_TYPE) ) {
+ G_free (dcellbuf);
+ }
+ G_free (cache);
+ }
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ struct GModule *module;
+ struct
+ {
+ struct Option *input; /* name of input site map */
+ struct Option *output; /* name of output site map */
+ struct Option *type;
+ struct Option *where;
+ struct Option *size; /* size of sample (%input) */
+ struct Option *map; /* optional raster to check for NULL */
+ struct Option *cachesize;
+ }
+ parm;
+ struct
+ {
+ struct Flag *quiet;
+ struct Flag *all; /* disregard region settings */
+ }
+ flag;
+ int processing_mode = 0;
+ int vect_types;
+
+ /* setup some basic GIS stuff */
+ G_gisinit (argv[0]);
+ module = G_define_module ();
+ module->description = "Generates a random sample from a map of vector objects";
+ /* do not pause after a warning message was displayed */
+ G_sleep_on_error (0);
+
+
+ /* Module Parameters: */
+
+ parm.input = G_define_standard_option (G_OPT_V_INPUT);
+ parm.input->key = "input";
+ parm.input->type = TYPE_STRING;
+ parm.input->required = YES;
+ parm.input->description = "Vector map to draw sample from";
+
+ /* name of output map */
+ parm.output = G_define_standard_option (G_OPT_V_OUTPUT);
+ parm.output->key = "output";
+ parm.output->type = TYPE_STRING;
+ parm.output->required = YES;
+ parm.output->description = "Vector map to store random sample in";
+
+ /* type of objects */
+ parm.type = G_define_standard_option (G_OPT_V_TYPE);
+
+ /* filter objects by sql statement */
+ parm.where = G_define_standard_option (G_OPT_WHERE);
+
+ /* percentage of input objects to include for random sample */
+ parm.size = G_define_option ();
+ parm.size->key = "size";
+ parm.size->type = TYPE_DOUBLE;
+ parm.size->required = YES;
+ parm.size->description = "Size of the sample (% of input vector objects)";
+ parm.size->options = "0-100";
+
+ /* map = an optional raster map. Samples will not be generated */
+ /* in cells where this map fprintf (stderr, "HI\n");is NULL */
+ parm.map = G_define_standard_option (G_OPT_R_INPUT);
+ parm.map->key = "raster";
+ parm.map->type = TYPE_STRING;
+ parm.map->required = NO;
+ parm.map->description = "Sampling cannot be done on NULL cells in this raster map";
+
+ /* number of lines to store in cache */
+ parm.cachesize = G_define_option ();
+ parm.cachesize->key = "cachesize";
+ parm.cachesize->type = TYPE_INTEGER;
+ parm.cachesize->answer = "-1";
+ parm.cachesize->required = NO;
+ parm.cachesize->description = "Number of raster rows to store in cache (-1 for auto)";
+
+ flag.all = G_define_flag ();
+ flag.all->key = 'a';
+ flag.all->description = "Sample outside the current region's limits";
+
+ flag.quiet = G_define_flag ();
+ flag.quiet->key = 'q';
+ flag.quiet->description = "Quiet operation: no progress display";
+
+ /* parse command line */
+ if (G_parser (argc, argv))
+ {
+ exit (-1);
+ }
+
+ vect_types = Vect_option_to_types (parm.type);
+
+ /* check if given parameters are valid */
+ processing_mode =
+ check_parms (parm.map->answer, parm.input->answer, parm.output->answer, flag.all->answer);
+
+ if ( parm.map->answer != NULL ) {
+ /* set cachesize */
+ cachesize = atoi (parm.cachesize->answer);
+ if ( (cachesize<-1) || (cachesize > G_window_rows ()) ) {
+ /* if cache size is invalid, just set to auto-mode (-1) */
+ G_warning ("Invalid cache size requested (must be between 0 and %i or -1).\n", G_window_rows());
+ cachesize = -1;
+ }
+ }
+
+ do_split_sample ( parm.input->answer, parm.output->answer, vect_types, atof (parm.size->answer),
+ parm.map->answer, flag.all->answer, processing_mode, flag.quiet->answer );
+
+ return (EXIT_SUCCESS);
+}
Property changes on: grass-addons/grass6/dst/vector/v.random.sample/main.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/vector/v.report.dist/Makefile
===================================================================
--- grass-addons/grass6/dst/vector/v.report.dist/Makefile (rev 0)
+++ grass-addons/grass6/dst/vector/v.report.dist/Makefile 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,14 @@
+MODULE_TOPDIR = ../..
+
+PGM = v.report.dist
+
+GT_LIB_RAST = -lgt_raster
+GT_LIB_STAT = -lgt_stats
+GSL_LIB = `gsl-config --libs`
+GSL_INC = `gsl-config --cflags`
+LIBES = $(GISLIB) $(DATETIMELIB) $(VECTLIB) $(GSL_LIB) $(GT_LIB_RAST) $(GT_LIB_STAT)
+EXTRA_CFLAGS = -I../../include $(GSL_INC)
+
+include $(MODULE_TOPDIR)/include/Make/Module.make
+
+default: cmd
Property changes on: grass-addons/grass6/dst/vector/v.report.dist/Makefile
___________________________________________________________________
Added: svn:executable
+ *
Added: grass-addons/grass6/dst/vector/v.report.dist/description.html
===================================================================
--- grass-addons/grass6/dst/vector/v.report.dist/description.html (rev 0)
+++ grass-addons/grass6/dst/vector/v.report.dist/description.html 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<TITLE>v.report</TITLE>
+
+<body bgcolor="white">
+
+<H2>NAME</H2>
+
+<h2>DESCRIPTION</h2>
+
+This program prints a report of cell counts in the current region and under
+a sample of cells with positions specified by vector objects. It can also
+calculate Kvamme's gain factor which is a popular index in archaeological
+predictive modelling.
+
+<h3>Notes</h3>
+This program was originally developed as part of the GRASS 5 DST Predictive Modelling Toolkit.
+
+<h3>AUTHOR</h3>
+Benjamin Ducke,<p>
+University of Kiel, Germany<p>
+<p><i>Last changed: $Date$</i>
+</body>
+</html>
Property changes on: grass-addons/grass6/dst/vector/v.report.dist/description.html
___________________________________________________________________
Added: svn:mime-type
+ text/html
Added: svn:keywords
+ Author Date Id
Added: svn:eol-style
+ native
Added: grass-addons/grass6/dst/vector/v.report.dist/main.c
===================================================================
--- grass-addons/grass6/dst/vector/v.report.dist/main.c (rev 0)
+++ grass-addons/grass6/dst/vector/v.report.dist/main.c 2012-03-05 21:58:34 UTC (rev 50997)
@@ -0,0 +1,844 @@
+/* s.report */
+/* Show histogram of vector object distribution over raster map values. */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+
+#include <grass/gis.h>
+#include <grass/Vect.h>
+
+#include "gt/rowcache.h"
+#include "gt/cat_engine.h"
+#include "gt/gstats_gain.h"
+
+#define PROGVERSION 1.1
+
+extern int errno;
+int CACHESIZE;
+
+char *PROGNAME;
+
+void delete_tmpfile ( char *tmpfile ) {
+
+ int error;
+
+ error = G_remove ("cell",tmpfile);
+ if ( error < 1 ) {
+ G_warning ("Could not delete cell element of temporary file (%s).", tmpfile);
+ }
+ error = G_remove ("cellhd",tmpfile);
+ if ( error < 1 ) {
+ G_warning ("Could not delete cellhd element of temporary file (%s).", tmpfile);
+ }
+ error = G_remove ("cats",tmpfile);
+ if ( error < 1 ) {
+ G_warning ("Could not delete cats element of temporary file (%s).", tmpfile);
+ }
+ error = G_remove ("hist",tmpfile);
+ if ( error < 1 ) {
+ G_warning ("Could not delete hist element of temporary file (%s).", tmpfile);
+ }
+ error = G_remove ("cell_misc",tmpfile);
+ if ( error < 1 ) {
+ G_warning ("Could not delete cell_misc element of temporary file (%s).", tmpfile);
+ }
+}
+/* create the actual report */
+void do_report_CELL ( char *map, char *mapset, char *sites,
+ int precision, int null_flag, int uncat_flag,
+ int all_flag, int quiet_flag, int skip_flag,
+ char *logfile, int background, int gain, int show_progress) {
+ CELL *cellbuf;
+ struct Cell_head region;
+ GT_Row_cache_t *cache;
+ unsigned long row_idx, col_idx;
+ int fd;
+ unsigned long i,j,k;
+ unsigned long no_sites;
+ FILE *lp;
+ unsigned long nrows, ncols;
+ unsigned long *share_smp = NULL; /* array that keeps percentage of sites */
+ double total = 0;
+ double map_total = 0;
+ double kvamme_gain;
+ long null_count = 0; /* keeps count of sites on NULL cells */
+ long nocat_count = 0;
+ /* category counts and descriptions */
+ int cats;
+ char **cats_description; /* category labels */
+ long *cat_count; /* category counts */
+ long null_count_map; /* number of NULL cells in input map */
+ long nocat_count_map; /* number of cells that do not fall into the category range [0 .. n] */
+ int debug_mode = 0; /* 1 to enable writing additional output to logfile */
+ time_t systime;
+
+ char errmsg [200];
+ struct Map_info in_vect_map;
+ struct line_pnts *vect_points;
+ double x,y,z;
+ int n_points = 1;
+ int cur_type;
+
+
+ /* get current region */
+ G_get_window (®ion);
+ nrows = G_window_rows ();
+ ncols = G_window_cols ();
+
+ /* check logfile */
+ if (logfile != NULL) {
+ debug_mode = 1;
+ if ( !G_legal_filename (logfile) ) {
+ delete_tmpfile (map);
+ G_fatal_error ("Please specify a legal filename for the logfile.\n");
+ }
+ /* attempt to write to logfile */
+ if ( (lp = fopen ( logfile, "w+" ) ) == NULL ) {
+ delete_tmpfile (map);
+ G_fatal_error ("Could not create logfile.\n");
+ }
+ /* we want unbuffered output for the logfile */
+ setvbuf (lp,NULL,_IONBF,0);
+ fprintf (lp,"This is %s, version %.2f\n",PROGNAME, PROGVERSION);
+ systime = time (NULL);
+ fprintf (lp,"Started on %s",ctime(&systime));
+ fprintf (lp,"\tlocation = %s\n",G_location());
+ fprintf (lp,"\tmapset = %s\n",G_mapset());
+ fprintf (lp,"\tinput map = %s\n",map);
+ fprintf (lp,"\tsample file = %s\n",sites);
+ } else {
+ /* log output to stderr by default */
+ lp = stderr;
+ }
+
+ if (1 > Vect_open_old (&in_vect_map, sites, "")) {
+ delete_tmpfile (map);
+ sprintf (errmsg, "Could not open input map %s.\n", sites);
+ G_fatal_error (errmsg);
+ }
+
+ vect_points = Vect_new_line_struct ();
+
+ if (all_flag != 1) {
+ Vect_set_constraint_region (&in_vect_map, region.north, region.south,
+ region.east, region.west, 0.0, 0.0);
+ }
+
+ /* get total number of sampling points */
+ i = 0;
+ while ((cur_type = Vect_read_next_line (&in_vect_map, vect_points, NULL) > 0)) {
+ i ++;
+ }
+
+ no_sites = i; /* store this for later use */
+
+ /* open raster map */
+ fd = G_open_cell_old (map, G_find_cell (map, ""));
+ if (fd < 0)
+ {
+ delete_tmpfile (map);
+ G_fatal_error ("Could not open raster map for reading!\n");
+ }
+ /* allocate a cache and a raster buffer */
+ cache = (GT_Row_cache_t *) G_malloc (sizeof (GT_Row_cache_t));
+ GT_RC_open (cache, CACHESIZE, fd, CELL_TYPE);
+ cellbuf = G_allocate_raster_buf (CELL_TYPE);
+
+ cats = GT_get_stats (map,mapset,&null_count_map, &nocat_count_map, show_progress);
+ if ( cats < 2 ) {
+ delete_tmpfile (map);
+ G_fatal_error ("Input map must have at least two categories.");
+ }
+
+ /* get category labels and counts */
+ cats_description = GT_get_labels (map,mapset);
+ if (cats_description == NULL) {
+ delete_tmpfile (map);
+ G_fatal_error ("Could not read category labels from input map.");
+ }
+ cat_count = GT_get_c_counts (map,mapset, show_progress);
+ if (cat_count == NULL) {
+ delete_tmpfile (map);
+ G_fatal_error ("Could not count categories in input map.");
+ }
+
+ /* allocate a double array to hold statistics */
+ share_smp = (unsigned long *) G_malloc ((signed)(cats * sizeof (unsigned long)));
+ for (i = 0; i < cats; i++)
+ {
+ share_smp[i] = 0;
+
+ }
+
+ /* count raster values under sampling points */
+ i = 0;
+ k = 0; /* progress counter for status display */
+
+ Vect_rewind (&in_vect_map);
+
+ if ( !quiet_flag ) {
+ fprintf (stdout, "Counting sample: \n");
+ fflush (stdout);
+ }
+
+ /* we MUST not set constraints so that no raster values outside the current region are
+ accessed, which would give an "illegal cache request" error */
+ Vect_set_constraint_region (&in_vect_map, region.north, region.south,
+ region.east, region.west, 0.0, 0.0);
+
+ while ((cur_type = Vect_read_next_line (&in_vect_map, vect_points, NULL) > 0)) {
+ Vect_copy_pnts_to_xyz (vect_points, &x, &y, &z, &n_points);
+ k ++;
+ if ( !quiet_flag ) {
+ G_percent ((signed) k, (signed) no_sites, 1);
+ }
+ /* get raster row with same northing as sample and perform
+ quantification */
+ row_idx = (long) G_northing_to_row (y, ®ion);
+ col_idx = (long) G_easting_to_col (x, ®ion);
+
+ cellbuf = GT_RC_get (cache, (signed) row_idx);
+ /* now read the raster value under the current site */
+ if (G_is_c_null_value (&cellbuf[col_idx]) == 0) {
+ /* site on cell within category range [0..cats] ? */
+ if ( (cellbuf[col_idx] > -1) && (cellbuf[col_idx] <= cats) ) {
+ share_smp [cellbuf[col_idx] ] ++;
+ /* i keeps track of samples on non-null coverage only */
+ /* inside the current region */
+ i ++;
+ } else {
+ if ( uncat_flag ) {
+ /* also keep count of sites on uncategorised cells? */
+ i ++;
+ nocat_count++;
+ }
+ }
+ }
+ if (G_is_c_null_value (&cellbuf[col_idx]) == 1) {
+ /* got a NULL value under this site */
+ if (null_flag) { /* only count this, if null flag is set */
+ null_count ++;
+ i ++;
+ }
+ }
+ }
+
+ Vect_close (&in_vect_map);
+
+ fprintf (lp,"\n");
+ if ( background ) {
+ fprintf (lp,"Distribution of categories under %lu points (%lu in region) and in input map:\n",i,no_sites);
+ } else {
+ fprintf (lp,"Distribution of categories under %lu points (%lu in region):\n",i,no_sites);
+ }
+ /* determine starting value for total of sites analysed */
+ total = 0;
+ for ( j=0; j < cats; j ++) {
+ total = total + share_smp[j];
+ map_total = map_total + cat_count[j];
+ }
+ if (null_flag) { /* add NULL values to total */
+ total = total + null_count;
+ map_total = map_total + null_count_map;
+ }
+ if (uncat_flag) { /* add uncategorised cells to total */
+ total = total + nocat_count;
+ map_total = map_total + nocat_count_map;
+
+ }
+
+ /* Now display those values which the user has chosen */
+ if ( (background) && (gain) ) {
+ fprintf (lp,"Cat.\tPts.\t(%%)\tMap\t(%%)\tGain\tDescription\n");
+ }
+ if ( (background) && (!gain) ) {
+ fprintf (lp,"Cat.\tPts.\t(%%)\tMap\t(%%)\tDescription\n");
+ }
+ if ( (!background) && (gain) ) {
+ fprintf (lp,"Cat.\tPts.\t(%%)\tGain\tDescription\n");
+ }
+ if ( (!background) && (!gain) ) {
+ fprintf (lp,"Cat.\tPts.\t(%%)\tDescription\n");
+ }
+ for ( j = 0; j < cats; j ++) {
+ /* if skip_flag is not set: only show categories that have count > 0 */
+ if ((skip_flag == 1) || ((skip_flag == 0) && (share_smp[j] > 0))) {
+ if ( (background) && (gain) ) {
+ /* Kvamme's Gain = 1 - (%area/%sites) */
+ kvamme_gain = gstats_gain_K(((double) share_smp[j]*(100/total)),
+ ((double) cat_count[j]*(100/map_total)));
+ fprintf (lp, "%lu\t%6lu\t%6.2f\t%8lu %6.2f\t%6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total),
+ cat_count[j], (float) cat_count[j]*(100/map_total),
+ kvamme_gain, cats_description[j]);
+ }
+ if ( (background) && (!gain) ) {
+ fprintf (lp, "%lu\t%6lu\t%6.2f\t%8lu %6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total),
+ cat_count[j], (float) cat_count[j]*(100/map_total),
+ cats_description[j]);
+
+ }
+ if ( (!background) && (gain) ) {
+ kvamme_gain = 1-( (float) cat_count[j]*(100/map_total) / (float) share_smp[j]*(100/total) );
+ fprintf (lp, "%lu\t%6lu\t%6.2f\t%6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total),
+ kvamme_gain, cats_description[j]);
+ }
+ if ( (!background) && (!gain) ) {
+ fprintf (lp, "%lu\t%6lu\t%6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total),
+ cats_description[j]);
+ }
+ }
+ }
+ if (null_flag) {
+ if ( background ) {
+ fprintf (lp,"NULL\t%6lu\t%6.2f\t%8lu %6.2f\n",null_count, (float) null_count * 100 / total
+ ,null_count_map, (float) null_count_map * 100 / map_total);
+ } else {
+ fprintf (lp,"NULL\t%6lu\t%6.2f\n",null_count, (float) null_count * 100 / total);
+ }
+ }
+ if (uncat_flag) {
+ if ( background ) {
+ fprintf (lp,"NOCAT\t%6lu\t%6.2f\t%8lu %6.2f\n",nocat_count, (float) nocat_count * 100 / total
+ ,nocat_count_map, (float) nocat_count_map * 100 / map_total);
+ } else {
+ fprintf (lp,"NOCAT\t%6lu\t%6.2f\n",nocat_count, (float) nocat_count * 100 / total);
+ }
+ }
+ if ( background) {
+ fprintf (lp,"TOTAL\t%6lu\t%6.2f\t%8lu %6.2f\n",(long) total, (float) 100, (long) map_total, (float) 100);
+ } else {
+ fprintf (lp,"TOTAL\t%6lu\t%6.2f\n",(long) total, (float) 100);
+ }
+
+ /* close cache and sites file; free buffers. */
+ GT_RC_close (cache);
+ G_free (cellbuf);
+ G_free (cache);
+}
+
+
+/* create the actual report */
+/* This function is for floating point maps */
+void do_report_DCELL ( char *map, char *mapset, char *sites,
+ int precision, int null_flag, int uncat_flag,
+ int all_flag, int quiet_flag, int skip_flag,
+ char *logfile, int background, int gain, int show_progress) {
+ DCELL *dcellbuf;
+ DCELL dvalue;
+ CELL value;
+ struct Cell_head region;
+ struct Categories categories;
+ GT_Row_cache_t *cache;
+ unsigned long row_idx, col_idx;
+ short error;
+ int fd;
+ unsigned long i,j,k;
+ unsigned long no_sites;
+ FILE *lp;
+ unsigned long nrows, ncols;
+ unsigned long *share_smp = NULL; /* array that keeps percentage of sites */
+ double total = 0;
+ double map_total = 0;
+ double kvamme_gain;
+ long null_count = 0; /* keeps count of sites on NULL cells */
+ long nocat_count = 0; /* sites on cells outside category range */
+ /* category counts and descriptions */
+ int cats;
+ char **cats_description; /* category labels */
+ long *cat_count; /* category counts */
+ long null_count_map; /* number of NULL cells in input map */
+ long nocat_count_map; /* number of cells that do not fall into the category range [0 .. n] */
+
+ int debug_mode = 0; /* 1 to enable writing additional output to logfile */
+ time_t systime;
+
+ char errmsg [200];
+ struct Map_info in_vect_map;
+ struct line_pnts *vect_points;
+ double x,y,z;
+ int n_points = 1;
+ int cur_type;
+
+
+ /* get current region */
+ G_get_window (®ion);
+ nrows = G_window_rows ();
+ ncols = G_window_cols ();
+
+ /* check logfile */
+ if (logfile != NULL) {
+ debug_mode = 1;
+ if ( !G_legal_filename (logfile) ) {
+ delete_tmpfile (map);
+ G_fatal_error ("Please specify a legal filename for the logfile.\n");
+ }
+ /* attempt to write to logfile */
+ if ( (lp = fopen ( logfile, "w+" ) ) == NULL ) {
+ delete_tmpfile (map);
+ G_fatal_error ("Could not create logfile.\n");
+ }
+ /* we want unbuffered output for the logfile */
+ setvbuf (lp,NULL,_IONBF,0);
+ fprintf (lp,"This is s.report, version %.2f\n",PROGVERSION);
+ systime = time (NULL);
+ fprintf (lp,"Started on %s",ctime(&systime));
+ fprintf (lp,"\tlocation = %s\n",G_location());
+ fprintf (lp,"\tmapset = %s\n",G_mapset());
+ fprintf (lp,"\tinput map = %s\n",map);
+ fprintf (lp,"\tsample file = %s\n",sites);
+ } else {
+ /* log output to stderr by default */
+ lp = stderr;
+ }
+
+ if (1 > Vect_open_old (&in_vect_map, sites, "")) {
+ sprintf (errmsg, "Could not open input map %s.\n", sites);
+ delete_tmpfile (map);
+ G_fatal_error (errmsg);
+ }
+
+ vect_points = Vect_new_line_struct ();
+
+ if (all_flag != 1) {
+ Vect_set_constraint_region (&in_vect_map, region.north, region.south,
+ region.east, region.west, 0.0, 0.0);
+ }
+
+ /* get total number of sampling points */
+ i = 0;
+ while ((cur_type = Vect_read_next_line (&in_vect_map, vect_points, NULL) > 0)) {
+ i ++;
+ }
+ no_sites = i; /* store this for later use */
+
+ /* open raster map */
+ fd = G_open_cell_old (map, G_find_cell (map, ""));
+ if (fd < 0)
+ {
+ delete_tmpfile (map);
+ G_fatal_error ("Could not open raster map for reading!\n");
+ }
+ /* allocate a cache and a raster buffer */
+ cache = (GT_Row_cache_t *) G_malloc (sizeof (GT_Row_cache_t));
+ GT_RC_open (cache, CACHESIZE, fd, DCELL_TYPE);
+ dcellbuf = G_allocate_raster_buf (DCELL_TYPE);
+
+ cats = GT_get_stats (map,mapset,&null_count_map, &nocat_count_map, show_progress);
+ if ( cats < 2 ) {
+ delete_tmpfile (map);
+ G_fatal_error ("Input map must have at least two categories.");
+ }
+
+ /* get category labels and counts */
+ cats_description = GT_get_labels (map,mapset);
+ if (cats_description == NULL) {
+ delete_tmpfile (map);
+ G_fatal_error ("Could not read category labels from input map.");
+ }
+ cat_count = GT_get_f_counts (map,mapset, show_progress);
+ if (cat_count == NULL) {
+ delete_tmpfile (map);
+ G_fatal_error ("Could not count categories in input map.");
+ }
+
+ /* now read category structure of input map*/
+ G_init_cats (0, "", &categories);
+ error = G_read_cats (map, mapset, &categories);
+ if (error != 0) { /* no categories found */
+ delete_tmpfile (map);
+ G_fatal_error ("Could not read category information of input map.");
+ }
+
+ /* allocate a double array to hold statistics */
+ share_smp = (unsigned long *) G_malloc ((signed) (cats * sizeof (unsigned long)));
+ for (i = 0; i < cats; i++)
+ {
+ share_smp[i] = 0;
+ }
+
+ /* count raster values under sites */
+ /* re-open sites file with samples */
+ i = 0;
+ k = 0; /* progress counter for status display */
+
+ Vect_rewind (&in_vect_map);
+
+ if ( !quiet_flag ) {
+ fprintf (stdout, "Counting sample: \n");
+ fflush (stdout);
+ }
+
+ /* we MUST not set constraints so that no raster values outside the current region are
+ accessed, which would give an "illegal cache request" error */
+ Vect_set_constraint_region (&in_vect_map, region.north, region.south,
+ region.east, region.west, 0.0, 0.0);
+
+ while ((cur_type = Vect_read_next_line (&in_vect_map, vect_points, NULL) > 0)) {
+ Vect_copy_pnts_to_xyz (vect_points, &x, &y, &z, &n_points);
+ k ++;
+ if ( !quiet_flag ) {
+ G_percent ((signed) k, (signed) no_sites, 1);
+ }
+ /* get raster row with same northing as sample and perform
+ * quantification */
+ row_idx = (long) G_northing_to_row (y, ®ion);
+ col_idx = (long) G_easting_to_col (x, ®ion);
+
+ dcellbuf = GT_RC_get (cache, (signed) row_idx);
+ /* now read the raster value under the current site */
+ if (G_is_d_null_value (&dcellbuf[col_idx]) == 0) {
+ dvalue = dcellbuf[col_idx];
+ value = G_quant_get_cell_value (&categories.q, dvalue);
+ if ( ! (( value < 0 ) || ( value > cats -1)) ) {
+ share_smp [value] ++;
+ i ++;
+ } else {
+ if ( uncat_flag ) {
+ /* also keep count of sites on uncategorised cells? */
+ i ++;
+ nocat_count++;
+ }
+ }
+ }
+ if (G_is_d_null_value (&dcellbuf[col_idx]) == 1) {
+ /* got a NULL value under this site */
+ if (null_flag) { /* only count this, if null flag is set */
+ null_count ++;
+ i ++;
+ }
+ }
+ }
+
+ Vect_close (&in_vect_map);
+
+ fprintf (lp,"\n");
+ if ( background ) {
+ fprintf (lp,"Distribution of categories under %lu points (%lu in region) and in input map:\n",i,no_sites);
+ } else {
+ fprintf (lp,"Distribution of categories under %lu points (%lu in region):\n",i,no_sites);
+ }
+ /* determine starting value for total of sites analysed */
+ total = 0;
+ for ( j=0; j < cats; j ++) {
+ total = total + share_smp[j];
+ map_total = map_total + cat_count[j];
+ }
+ if (null_flag) { /* add NULL values to total */
+ total = total + null_count;
+ map_total = map_total + null_count_map;
+ }
+ if (uncat_flag) { /* add uncategorised cells to total */
+ total = total + nocat_count;
+ map_total = map_total + nocat_count_map;
+
+ }
+ /* Now display those values which the user has chosen */
+ if ( (background) && (gain) ) {
+ fprintf (lp,"Cat.\tPts.\t(%%)\tMap\t(%%)\tGain\tDescription\n");
+ }
+ if ( (background) && (!gain) ) {
+ fprintf (lp,"Cat.\tPts.\t(%%)\tMap\t(%%)\tDescription\n");
+ }
+ if ( (!background) && (gain) ) {
+ fprintf (lp,"Cat.\tPts.\t(%%)\tGain\tDescription\n");
+ }
+ if ( (!background) && (!gain) ) {
+ fprintf (lp,"Cat.\tPts.\t(%%)\tDescription\n");
+ }
+ for ( j = 0; j < cats; j ++) {
+ /* if skip_flag is not set: only show categories that have count > 0 */
+ if ((skip_flag == 1) || ((skip_flag == 0) && (share_smp[j] > 0))) {
+ if ( (background) && (gain) ) {
+ /* Kvamme's Gain = 1 - (%area/%sites) */
+ kvamme_gain = gstats_gain_K(((double) share_smp[j]*(100/total)),
+ ((double) cat_count[j]*(100/map_total)));
+ fprintf (lp, "%lu\t%6lu\t%6.2f\t%8lu %6.2f\t%6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total),
+ cat_count[j], (float) cat_count[j]*(100/map_total),
+ kvamme_gain, cats_description[j]);
+ }
+ if ( (background) && (!gain) ) {
+ fprintf (lp, "%lu\t%6lu\t%6.2f\t%8lu %6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total),
+ cat_count[j], (float) cat_count[j]*(100/map_total),
+ cats_description[j]);
+
+ }
+ if ( (!background) && (gain) ) {
+ kvamme_gain = 1 - ( ((float) cat_count[j]*(100/map_total)) / ((float) share_smp[j]*(100/total)) );
+ fprintf (lp, "%lu\t%6lu\t%6.2f\t%6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total),
+ kvamme_gain, cats_description[j]);
+ }
+ if ( (!background) && (!gain) ) {
+ fprintf (lp, "%lu\t%6lu\t%6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total),
+ cats_description[j]);
+ }
+ }
+ }
+ if (null_flag) {
+ if ( background ) {
+ fprintf (lp,"NULL\t%6lu\t%6.2f\t%8lu %6.2f\n",null_count, (float) null_count * 100 / total
+ ,null_count_map, (float) null_count_map * 100 / map_total);
+ } else {
+ fprintf (lp,"NULL\t%6lu\t%6.2f\n",null_count, (float) null_count * 100 / total);
+ }
+ }
+ if (uncat_flag) {
+ if ( background ) {
+ fprintf (lp,"NOCAT\t%6lu\t%6.2f\t%8lu %6.2f\n",nocat_count, (float) nocat_count * 100 / total
+ ,nocat_count_map, (float) nocat_count_map * 100 / map_total);
+ } else {
+ fprintf (lp,"NOCAT\t%6lu\t%6.2f\n",nocat_count, (float) nocat_count * 100 / total);
+ }
+ }
+ if ( background) {
+ fprintf (lp,"TOTAL\t%6lu\t%6.2f\t%8lu %6.2f\n",(long) total, (float) 100, (long) map_total, (float) 100);
+ } else {
+ fprintf (lp,"TOTAL\t%6lu\t%6.2f\n",(long) total, (float) 100);
+ }
+
+ /* close cache and sites file; free buffers. */
+ GT_RC_close (cache);
+ G_free (dcellbuf);
+ G_free (cache);
+}
+
+
+int
+main (int argc, char *argv[]) {
+ struct GModule *module;
+ struct Option *map; /* raster map to work on */
+ struct Option *sites; /* output map to write */
+ struct Option *mode; /* Categorisation mode */
+ struct Option *min; /* range of values to categorise ... */
+ struct Option *max; /* .. anything outside will be NULL in output */
+ struct Option *logfile; /* log output to this file instead of stdout */
+ struct Option *precision; /* decimal digits precision for log file */
+ struct Option *cachesize;
+ struct Flag *null; /* also count NULL values? */
+ struct Flag *all; /* disregard region when reporting total percentages */
+ struct Flag *zeroskip; /* also show categories with 0 count? */
+ struct Flag *uncat; /* also show cells outside category range? */
+ struct Flag *background; /* show background distribution? */
+ struct Flag *gain; /* calculate Kvamme's gain for each category? */
+ struct Flag *quiet; /* no status display on screen */
+
+ char *mapset;
+ int show_progress = 1; /* enable progress display by default */
+ /* these vars are used to store information about the input map */
+ int cats; /* number of categories in input map */
+ long null_count; /* number of NULL cells */
+ long nocat_count; /* number of cells that do not fall into the category range [0 .. n] */
+ /* use to create command line for r.categorize call */
+ char *sysstr, *tmpfile, *input_map;
+ int error;
+
+ sysstr = NULL;
+ tmpfile = NULL;
+
+ /* setup some basic GIS stuff */
+ G_gisinit (argv[0]);
+ module = G_define_module ();
+ module->description = "Analyses distribution of vector sample over a raster map";
+ /* do not pause after a warning message was displayed */
+ G_sleep_on_error (0);
+
+ /* DEFINE OPTIONS AND FLAGS */
+ /* raster map to sample */
+ map = G_define_standard_option (G_OPT_R_INPUT);
+ map->key = "raster";
+ map->type = TYPE_STRING;
+ map->required = YES;
+ map->description = "Raster map to sample";
+
+ /* site map for sampling positions */
+ sites = G_define_standard_option (G_OPT_V_INPUT);
+ sites->key = "positions";
+ sites->type = TYPE_STRING;
+ sites->required = YES;
+ sites->description = "Vector map with sampling positions";
+
+ /* Categorisation mode */
+ mode = G_define_option ();
+ mode->key = "mode";
+ mode->type = TYPE_STRING;
+ mode->required = NO;
+ mode->description = "Categorisation mode (see manual)";
+
+ /* min raster value to categorise */
+ min = G_define_option ();
+ min->key = "min";
+ min->type = TYPE_DOUBLE;
+ min->required = NO;
+ min->description = "Minimum value to include in categorisation";
+
+ /* max raster value to categorise */
+ max = G_define_option ();
+ max->key = "max";
+ max->type = TYPE_DOUBLE;
+ max->required = NO;
+ max->description = "Maximum value to include in categorisation.";
+
+ /* optional name of logfile */
+ logfile = G_define_option ();
+ logfile->key = "logfile";
+ logfile->type = TYPE_DOUBLE;
+ logfile->required = NO;
+ logfile->description = "Name of ASCII logfile, if desired.";
+
+ /* optional number of decimal digitis to store in logfile/show on screen */
+ precision = G_define_option ();
+ precision->key = "precision";
+ precision->type = TYPE_DOUBLE;
+ precision->required = NO;
+ precision->answer = "2";
+ precision->description = "Number of decimal digits for statistics/logfile";
+
+ /* number of lines to store in cache */
+ cachesize = G_define_option ();
+ cachesize->key = "cachesize";
+ cachesize->type = TYPE_INTEGER;
+ cachesize->answer = "-1";
+ cachesize->required = NO;
+ cachesize->description = "Number of raster rows to store in cache (-1 for auto)";
+
+ null = G_define_flag ();
+ null->key = 'n';
+ null->description = "Include NULL cells in report.";
+
+ uncat = G_define_flag ();
+ uncat->key = 'u';
+ uncat->description = "Include uncategorised cells in statistics.";
+
+ all = G_define_flag ();
+ all->key = 'a';
+ all->description = "Disregard region setting for counts.";
+
+ zeroskip = G_define_flag ();
+ zeroskip->key = 'z';
+ zeroskip->description = "Also show categories with zero count/percentage.";
+
+ background = G_define_flag ();
+ background->key = 'b';
+ background->description = "Show background distribution of categories in raster input map.";
+
+ gain = G_define_flag ();
+ gain->key = 'g';
+ gain->description = "Calculate Kvamme's Gain Factor for each category.";
+
+ quiet = G_define_flag ();
+ quiet->key = 'q';
+ quiet->description = "Quiet operation: do not show progress display.";
+
+
+ /* parse command line */
+ if (G_parser (argc, argv))
+ {
+ exit (-1);
+ }
+
+ /* check for 'quiet' flag */
+ if ( quiet->answer ) {
+ show_progress = 0;
+ }
+
+ PROGNAME = argv[0];
+
+ /* copy the 'map' option string to another buffer and use that */
+ /* from now on. We do this because we might want to manipulate */
+ /* that string and that is dangerous with GRASS Option->answer strings! */
+ input_map = G_calloc (255, sizeof (char));
+ G_strcpy (input_map, map->answer);
+
+ mapset = G_calloc (255, sizeof (char));
+ /* check if input map is a fully categorised raster map */
+ mapset = G_find_cell (input_map,"");
+ if ( mapset == NULL) {
+ G_fatal_error ("The input map does not exist in the current database.");
+ }
+
+ if ( mode->answer == NULL ) {
+ cats = GT_get_stats (input_map,mapset,&null_count, &nocat_count, show_progress);
+ if ( cats < 0 ) {
+ G_fatal_error ("Could not stat input map. Do you have read access?");
+ }
+ if ( ((cats == 0) && (mode->answer==NULL)) ) {
+ G_fatal_error ("No categories defined in input map.\nPlease specify a mode to create a fully classified map.");
+ }
+ }
+
+ /* a classification mode was given: call r.categorize and save output
+ in a tmp file */
+ if ( mode->answer != NULL ) {
+ srand ((unsigned long) time(NULL));
+ tmpfile = G_calloc (255, sizeof(char));
+ sysstr = G_calloc (255, sizeof(char));
+ /* create tmp file name from current PID and system time */
+ sprintf (tmpfile,"tmp.%i.%i", getpid(),(rand())/10000);
+ if ( getenv("GISBASE") == NULL ) {
+ G_fatal_error ("GISBASE not set. Unable to call GRASS module 'r.categorise'.");
+ }
+ if ( quiet->answer ) {
+ sprintf (sysstr,"%s/bin/r.categorize input=%s@%s output=%s mode=%s min=%s max=%s -q", getenv("GISBASE"), map->answer,
+ mapset, tmpfile, mode->answer, min->answer, max->answer);
+ } else {
+ sprintf (sysstr,"%s/bin/r.categorize input=%s@%s output=%s mode=%s min=%s max=%s", getenv("GISBASE"), map->answer,
+ mapset, tmpfile, mode->answer, min->answer, max->answer);
+ }
+ /* now create fully classified map using r.categorize and store */
+ /* it in a temporary raster map */
+ error = system (sysstr);
+ if ( error < 0 ) {
+ G_fatal_error ("Calling r.categorize has failed. Check your installation.");
+ }
+
+ /* store name of temporary file as new input map */
+ G_strcpy (input_map, tmpfile);
+
+ /* check categories of tmpfile */
+ cats = GT_get_stats (input_map,mapset,&null_count, &nocat_count, show_progress);
+ if (cats < 1) {
+ G_fatal_error ("Could not create a fully categorised temporary file.\nTry another categorisation mode.");
+ }
+ }
+
+ /* initialise cache structure */
+ if ( input_map != NULL ) {
+ /* set cachesize */
+ CACHESIZE = atoi (cachesize->answer);
+ if ( (CACHESIZE<-1) || (CACHESIZE > G_window_rows ()) ) {
+ /* if cache size is invalid, just set to auto-mode (-1) */
+ G_warning ("Invalid cache size requested (must be between 0 and %i or -1).\n", G_window_rows());
+ CACHESIZE = -1;
+ }
+ }
+
+ if ( G_raster_map_is_fp (input_map, mapset)) {
+ do_report_DCELL (input_map, mapset, sites->answer,
+ atoi (precision->answer),null->answer, uncat->answer,
+ all->answer, quiet->answer, zeroskip->answer,
+ logfile->answer, background->answer, gain->answer, show_progress);
+ } else {
+ do_report_CELL (input_map, mapset, sites->answer,
+ atoi (precision->answer),null->answer, uncat->answer,
+ all->answer, quiet->answer, zeroskip->answer,
+ logfile->answer, background->answer, gain->answer, show_progress);
+ }
+
+
+ /* delete temporary file, if needed */
+ if ( mode->answer != NULL ) {
+ delete_tmpfile (tmpfile);
+ G_free (tmpfile);
+ }
+
+ if ( sysstr != NULL ) {
+ G_free (sysstr);
+ }
+ G_free (input_map);
+
+ return (EXIT_SUCCESS);
+}
Property changes on: grass-addons/grass6/dst/vector/v.report.dist/main.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
More information about the grass-commit
mailing list