/* useful to create randomised samples for statistical tests */ void do_split_sample ( char *input, char *output, int in_types, double percentage, char *map, int all, int processing_mode, int quiet) { CELL *cellbuf; DCELL *dcellbuf; GT_Row_cache_t *cache; int fd; int i,j,k,l; int no_sites; int sites_tried = 0; struct Cell_head region; int error; char *mapset, errmsg [200]; unsigned int *taken; /* this is an array of 0/1 which signals, if a certain site has already been 'drawn' */ long row_idx, col_idx; struct Map_info in_vect_map; struct Map_info out_vect_map; struct line_pnts *vect_points; struct line_cats *vect_cats; double x,y,z; int n_points = 1; int cur_type; cellbuf = NULL; dcellbuf = NULL; cache = NULL; /* get current region */ G_get_window (®ion); /* attempt to create new file for output */ Vect_set_open_level (2); if (0 > Vect_open_new (&out_vect_map, output, 0) ) { G_fatal_error ("Could not open output vector map.\n"); } /* open input vector map */ if ((mapset = G_find_vector2 (input, "")) == NULL) { sprintf (errmsg, "Could not find input %s\n", input); G_fatal_error ("%s",errmsg); } if (1 > Vect_open_old (&in_vect_map, input, "")) { sprintf (errmsg, "Could not open input map %s.\n", input); G_fatal_error ("%s",errmsg); } vect_points = Vect_new_line_struct (); vect_cats = Vect_new_cats_struct (); /* set constraints specified */ if (in_types != 0) { Vect_set_constraint_type (&in_vect_map, in_types); } if (all != 1) { Vect_set_constraint_region (&in_vect_map, region.north, region.south, region.east, region.west, 0.0, 0.0); } /* get total number of objects with constraints */ i = 0; while ((cur_type = Vect_read_next_line (&in_vect_map, vect_points, vect_cats) > 0)) { i ++; } k = ( ((float) i/100)) * percentage; /* k now has the number of objects wanted */ if ( quiet != 1 ) { fprintf (stderr,"Creating randomised sample of size n = %i.\n",k); } /* now, we need to acquire exactly 'k' random objects that fall in NON-NULL */ /* coverage raster cells. */ taken = G_calloc (i, sizeof (unsigned int)); for ( l = 0; l < k; l ++ ) { taken[l] = 0; } no_sites = i; /* store this for later use */ /* does user want to filter objects through a raster map? */ if ( map != NULL) { /* open raster map */ fd = G_open_cell_old (map, G_find_cell (map, "")); if (fd < 0) { G_fatal_error ("Could not open raster map for reading!\n"); } /* allocate cache and buffer, according to type of coverage */ if ( processing_mode == CELL_TYPE) { /* INT coverage */ cache = (GT_Row_cache_t *) G_malloc (sizeof (GT_Row_cache_t)); /* TODO: check error value */ error = GT_RC_open (cache, cachesize, fd, CELL_TYPE); cellbuf = G_allocate_raster_buf (CELL_TYPE); } if ( (processing_mode == FCELL_TYPE) || (processing_mode == DCELL_TYPE) ) { /* FP coverage */ cache = (GT_Row_cache_t *) G_malloc (sizeof (GT_Row_cache_t)); /* TODO: check error value */ error = GT_RC_open (cache, cachesize, fd, DCELL_TYPE); dcellbuf = G_allocate_raster_buf (DCELL_TYPE); } } srand ( ((unsigned int) time (NULL)) + getpid()); /* set seed for random number generator from system time and process ID*/ i = 0; /* MAIN LOOP */ while ( i < k ) { /* get a random index, but one that was not taken already */ l = 0; while ( l == 0 ) { j = rand () % ( no_sites - 1 + 1) + 1; /* j now has the random position to try */ if ( taken[j-1] == 0 ) { l = 1; /* exit loop */ } } taken [j-1] = 1; /* mark this index as 'taken' */ sites_tried ++; /* keep track of this so we do not enter an infinite loop */ if ( sites_tried > no_sites ) { /* could not create a large enough sample */ G_fatal_error ("Could not find enough objects for split sampling.\nDecrease split sample size.\n"); } /* get next vector object */ cur_type = Vect_read_line (&in_vect_map, vect_points, vect_cats, j); if (cur_type < 0 ) { G_fatal_error ("Error reading vector map: premature EOF.\n"); } /* now, check if coverage under site is NON-NULL and within region */ /* convert site northing to row! */ /* for this check, we use only the first pair of coordinates! */ Vect_copy_pnts_to_xyz (vect_points, &x, &y, &z, &n_points); row_idx = (long) G_northing_to_row (y, ®ion); col_idx = (long) G_easting_to_col (x, ®ion); /* do region check, first... OBSOLETE */ /* read row from cache and check for NULL */ /* if required */ if ( map != NULL ) { if ( processing_mode == CELL_TYPE ) { cellbuf = GT_RC_get (cache, row_idx); if (!G_is_c_null_value(&cellbuf[col_idx])) { i ++; Vect_write_line (&out_vect_map, cur_type, vect_points, vect_cats ); fflush (stdout); } } if ( (processing_mode == FCELL_TYPE) || (processing_mode == DCELL_TYPE) ) { dcellbuf = GT_RC_get (cache, row_idx); if (!G_is_d_null_value(&dcellbuf[col_idx])) { i ++; Vect_write_line (&out_vect_map, cur_type, vect_points, vect_cats ); fflush (stdout); } } } else { i ++; Vect_write_line (&out_vect_map, GV_POINT, vect_points, vect_cats ); fflush (stdout); } /* disregard region setting and map, if -a flag is given */ if ( all == 1 ) { i ++; Vect_write_line (&out_vect_map, cur_type, vect_points, vect_cats ); fflush (stdout); } if ( quiet != 1 ) { G_percent(i,k,1); } } /* END OF MAIN LOOP */ Vect_copy_head_data (&in_vect_map, &out_vect_map); fprintf (stdout, "Building topology information for output map.\n"); Vect_build (&out_vect_map); Vect_close (&in_vect_map); Vect_close (&out_vect_map); if ( map != NULL ) { /* close cache, free buffers! */ GT_RC_close (cache); if ( processing_mode == CELL_TYPE ) { G_free (cellbuf); } if ( (processing_mode == FCELL_TYPE) || (processing_mode == DCELL_TYPE) ) { G_free (dcellbuf); } G_free (cache); } }
/* create the actual report */ void do_report_CELL ( char *map, char *mapset, char *sites, int precision, int null_flag, int uncat_flag, int all_flag, int quiet_flag, int skip_flag, char *logfile, int background, int gain, int show_progress) { CELL *cellbuf; struct Cell_head region; GT_Row_cache_t *cache; unsigned long row_idx, col_idx; int fd; unsigned long i,j,k; unsigned long no_sites; FILE *lp; unsigned long nrows, ncols; unsigned long *share_smp = NULL; /* array that keeps percentage of sites */ double total = 0; double map_total = 0; double kvamme_gain; long null_count = 0; /* keeps count of sites on NULL cells */ long nocat_count = 0; /* category counts and descriptions */ int cats; char **cats_description; /* category labels */ long *cat_count; /* category counts */ long null_count_map; /* number of NULL cells in input map */ long nocat_count_map; /* number of cells that do not fall into the category range [0 .. n] */ int debug_mode = 0; /* 1 to enable writing additional output to logfile */ time_t systime; char errmsg [200]; struct Map_info in_vect_map; struct line_pnts *vect_points; double x,y,z; int n_points = 1; int cur_type; /* get current region */ G_get_window (®ion); nrows = G_window_rows (); ncols = G_window_cols (); /* check logfile */ if (logfile != NULL) { debug_mode = 1; if ( !G_legal_filename (logfile) ) { delete_tmpfile (map); G_fatal_error ("Please specify a legal filename for the logfile.\n"); } /* attempt to write to logfile */ if ( (lp = fopen ( logfile, "w+" ) ) == NULL ) { delete_tmpfile (map); G_fatal_error ("Could not create logfile.\n"); } /* we want unbuffered output for the logfile */ setvbuf (lp,NULL,_IONBF,0); fprintf (lp,"This is %s, version %.2f\n",PROGNAME, PROGVERSION); systime = time (NULL); fprintf (lp,"Started on %s",ctime(&systime)); fprintf (lp,"\tlocation = %s\n",G_location()); fprintf (lp,"\tmapset = %s\n",G_mapset()); fprintf (lp,"\tinput map = %s\n",map); fprintf (lp,"\tsample file = %s\n",sites); } else { /* log output to stderr by default */ lp = stderr; } if (1 > Vect_open_old (&in_vect_map, sites, "")) { delete_tmpfile (map); sprintf (errmsg, "Could not open input map %s.\n", sites); G_fatal_error (errmsg); } vect_points = Vect_new_line_struct (); if (all_flag != 1) { Vect_set_constraint_region (&in_vect_map, region.north, region.south, region.east, region.west, 0.0, 0.0); } /* get total number of sampling points */ i = 0; while ((cur_type = Vect_read_next_line (&in_vect_map, vect_points, NULL) > 0)) { i ++; } no_sites = i; /* store this for later use */ /* open raster map */ fd = G_open_cell_old (map, G_find_cell (map, "")); if (fd < 0) { delete_tmpfile (map); G_fatal_error ("Could not open raster map for reading!\n"); } /* allocate a cache and a raster buffer */ cache = (GT_Row_cache_t *) G_malloc (sizeof (GT_Row_cache_t)); GT_RC_open (cache, CACHESIZE, fd, CELL_TYPE); cellbuf = G_allocate_raster_buf (CELL_TYPE); cats = GT_get_stats (map,mapset,&null_count_map, &nocat_count_map, show_progress); if ( cats < 2 ) { delete_tmpfile (map); G_fatal_error ("Input map must have at least two categories."); } /* get category labels and counts */ cats_description = GT_get_labels (map,mapset); if (cats_description == NULL) { delete_tmpfile (map); G_fatal_error ("Could not read category labels from input map."); } cat_count = GT_get_c_counts (map,mapset, show_progress); if (cat_count == NULL) { delete_tmpfile (map); G_fatal_error ("Could not count categories in input map."); } /* allocate a double array to hold statistics */ share_smp = (unsigned long *) G_malloc ((signed)(cats * sizeof (unsigned long))); for (i = 0; i < cats; i++) { share_smp[i] = 0; } /* count raster values under sampling points */ i = 0; k = 0; /* progress counter for status display */ Vect_rewind (&in_vect_map); if ( !quiet_flag ) { fprintf (stdout, "Counting sample: \n"); fflush (stdout); } /* we MUST not set constraints so that no raster values outside the current region are accessed, which would give an "illegal cache request" error */ Vect_set_constraint_region (&in_vect_map, region.north, region.south, region.east, region.west, 0.0, 0.0); while ((cur_type = Vect_read_next_line (&in_vect_map, vect_points, NULL) > 0)) { Vect_copy_pnts_to_xyz (vect_points, &x, &y, &z, &n_points); k ++; if ( !quiet_flag ) { G_percent ((signed) k, (signed) no_sites, 1); } /* get raster row with same northing as sample and perform quantification */ row_idx = (long) G_northing_to_row (y, ®ion); col_idx = (long) G_easting_to_col (x, ®ion); cellbuf = GT_RC_get (cache, (signed) row_idx); /* now read the raster value under the current site */ if (G_is_c_null_value (&cellbuf[col_idx]) == 0) { /* site on cell within category range [0..cats] ? */ if ( (cellbuf[col_idx] > -1) && (cellbuf[col_idx] <= cats) ) { share_smp [cellbuf[col_idx] ] ++; /* i keeps track of samples on non-null coverage only */ /* inside the current region */ i ++; } else { if ( uncat_flag ) { /* also keep count of sites on uncategorised cells? */ i ++; nocat_count++; } } } if (G_is_c_null_value (&cellbuf[col_idx]) == 1) { /* got a NULL value under this site */ if (null_flag) { /* only count this, if null flag is set */ null_count ++; i ++; } } } Vect_close (&in_vect_map); fprintf (lp,"\n"); if ( background ) { fprintf (lp,"Distribution of categories under %lu points (%lu in region) and in input map:\n",i,no_sites); } else { fprintf (lp,"Distribution of categories under %lu points (%lu in region):\n",i,no_sites); } /* determine starting value for total of sites analysed */ total = 0; for ( j=0; j < cats; j ++) { total = total + share_smp[j]; map_total = map_total + cat_count[j]; } if (null_flag) { /* add NULL values to total */ total = total + null_count; map_total = map_total + null_count_map; } if (uncat_flag) { /* add uncategorised cells to total */ total = total + nocat_count; map_total = map_total + nocat_count_map; } /* Now display those values which the user has chosen */ if ( (background) && (gain) ) { fprintf (lp,"Cat.\tPts.\t(%%)\tMap\t(%%)\tGain\tDescription\n"); } if ( (background) && (!gain) ) { fprintf (lp,"Cat.\tPts.\t(%%)\tMap\t(%%)\tDescription\n"); } if ( (!background) && (gain) ) { fprintf (lp,"Cat.\tPts.\t(%%)\tGain\tDescription\n"); } if ( (!background) && (!gain) ) { fprintf (lp,"Cat.\tPts.\t(%%)\tDescription\n"); } for ( j = 0; j < cats; j ++) { /* if skip_flag is not set: only show categories that have count > 0 */ if ((skip_flag == 1) || ((skip_flag == 0) && (share_smp[j] > 0))) { if ( (background) && (gain) ) { /* Kvamme's Gain = 1 - (%area/%sites) */ kvamme_gain = gstats_gain_K(((double) share_smp[j]*(100/total)), ((double) cat_count[j]*(100/map_total))); fprintf (lp, "%lu\t%6lu\t%6.2f\t%8lu %6.2f\t%6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total), cat_count[j], (float) cat_count[j]*(100/map_total), kvamme_gain, cats_description[j]); } if ( (background) && (!gain) ) { fprintf (lp, "%lu\t%6lu\t%6.2f\t%8lu %6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total), cat_count[j], (float) cat_count[j]*(100/map_total), cats_description[j]); } if ( (!background) && (gain) ) { kvamme_gain = 1-( (float) cat_count[j]*(100/map_total) / (float) share_smp[j]*(100/total) ); fprintf (lp, "%lu\t%6lu\t%6.2f\t%6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total), kvamme_gain, cats_description[j]); } if ( (!background) && (!gain) ) { fprintf (lp, "%lu\t%6lu\t%6.2f\t%s\n", j, share_smp[j], (float) share_smp[j]*(100/total), cats_description[j]); } } } if (null_flag) { if ( background ) { fprintf (lp,"NULL\t%6lu\t%6.2f\t%8lu %6.2f\n",null_count, (float) null_count * 100 / total ,null_count_map, (float) null_count_map * 100 / map_total); } else { fprintf (lp,"NULL\t%6lu\t%6.2f\n",null_count, (float) null_count * 100 / total); } } if (uncat_flag) { if ( background ) { fprintf (lp,"NOCAT\t%6lu\t%6.2f\t%8lu %6.2f\n",nocat_count, (float) nocat_count * 100 / total ,nocat_count_map, (float) nocat_count_map * 100 / map_total); } else { fprintf (lp,"NOCAT\t%6lu\t%6.2f\n",nocat_count, (float) nocat_count * 100 / total); } } if ( background) { fprintf (lp,"TOTAL\t%6lu\t%6.2f\t%8lu %6.2f\n",(long) total, (float) 100, (long) map_total, (float) 100); } else { fprintf (lp,"TOTAL\t%6lu\t%6.2f\n",(long) total, (float) 100); } /* close cache and sites file; free buffers. */ GT_RC_close (cache); G_free (cellbuf); G_free (cache); }