[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 (&region);			  
+			 	G_fatal_error ("Cache failure: could not read CELL raster row at %.2f.\n",
+			  					G_row_to_northing((float) i,&region));
+			}
+			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 (&region);			  
+			 	G_fatal_error ("Cache failure: could not read CELL raster row at %.2f.\n",
+			  					G_row_to_northing((float) i,&region));
+			}
+			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 (&region);			  
+			 	G_fatal_error ("Cache failure: could not read CELL raster row at %.2f.\n",
+			  					G_row_to_northing((float) i,&region));
+			}
+			return (FCELL*) (cache->f_cache_area[0]);			
+		}		
+	}
+	
+	if ((i < 0) || (i >= cache->region_rows)) {
+		G_get_window (&region);
+		sprintf (tmp,"Illegal cache request: row %i at Northing %.2f.\n",(int)i, 
+			G_row_to_northing((float)i,&region));
+		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 (&region);
+			  
+			  G_fatal_error ("Cache failure: could not read CELL raster row at %.2f.\n",
+			  				G_row_to_northing((float)i,&region));
+		  }
+		  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 (&region);
+			  G_fatal_error ("Cache failure: could not read CELL raster row at %.2f.\n",
+			  				G_row_to_northing((float)i,&region));
+		  }			
+		  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 (&region);
+			  G_fatal_error ("Cache failure: could not read DCELL raster row at %.2f.\n",
+			  				G_row_to_northing((float)i,&region));
+		  }			
+		  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 (&region);
+			  G_fatal_error ("Cache failure: could not read DCELL raster row at %.2f.\n",
+			  				G_row_to_northing((float)i,&region));
+		  }			
+		  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 (&region);
+			  G_fatal_error ("Cache failure: could not read FCELL raster row at %.2f.\n",
+			  				G_row_to_northing((float)i,&region));
+		  }			
+		  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 (&region);
+			  G_fatal_error ("Cache failure: could not read FCELL raster row at %.2f.\n",
+			  				G_row_to_northing((float)i,&region));
+		  }			
+		  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 (&region);			
+	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,&region),
+						G_row_to_northing ((double) ReadY,&region));
+			fprintf (lp,"%.2f\t%.2f\tWARNING %i: Sets do not combine to < 1 (%.5f)\n",												
+						G_col_to_easting ((double) ReadX,&region),
+						G_row_to_northing ((double) ReadY,&region),
+						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 (&region);
+	
+	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,&region),
+						G_row_to_northing ((double) ReadY,&region));
+			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,&region),
+						G_row_to_northing ((double) ReadY,&region));
+			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,&region),
+						G_row_to_northing ((double) ReadY,&region));
+			
+						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 (&region);
+	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, &region);
+				col_idx =
+					(long) G_easting_to_col (x, &region);
+				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 (&region);
+	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 (&region);
+	
+	
+	/* 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,
+				  &region);
+				
+		col_idx =
+			(long) G_easting_to_col (x,
+				 &region);
+		/* 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 (&region);
+	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, &region);
+		col_idx = (long) G_easting_to_col (x, &region);				
+				
+		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 (&region);
+	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, &region);
+		col_idx = (long) G_easting_to_col (x, &region);				
+				
+		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