Ejemplo n.º 1
0
int main(int argc, char *argv[])
{
    int *fd;
    char **names;
    char **ptr;
    char *name;

    /* flags */
    int raw_data;
    int with_coordinates;
    int with_xy;
    int with_percents;
    int with_counts;
    int with_areas;
    int with_labels;

    /* printf format */
    char fmt[20];
    int dp;
    struct Range range;
    struct FPRange fp_range;
    struct Quant q;
    CELL min, max, null_set = 0;
    DCELL dmin, dmax;
    struct GModule *module;
    struct
    {
	struct Flag *A;		/* print averaged values instead of intervals */
	struct Flag *a;		/* area */
	struct Flag *c;		/* cell counts */
	struct Flag *p;		/* percents */
	struct Flag *l;		/* with labels */
	struct Flag *q;		/* quiet */
	struct Flag *n;		/* Suppress reporting of any NULLs */
	struct Flag *N;		/* Suppress reporting of NULLs when 
				   all values are NULL */
	struct Flag *one;	/* one cell per line */
	struct Flag *x;		/*    with row/col */
	struct Flag *g;		/*    with east/north */
	struct Flag *i;		/* use quant rules for fp map, i.e. read it as int */
	struct Flag *r;		/*    raw output: when nsteps option is used,
				   report indexes of ranges instead of ranges
				   themselves; when -C (cats) option is used
				   reports indexes of fp ranges = ind. of labels */
	struct Flag *C;		/* report stats for labeled ranges in cats files */
    } flag;
    struct
    {
	struct Option *cell;
	struct Option *fs;
	struct Option *nv;
	struct Option *output;
	struct Option *nsteps;	/* divide data range into nsteps and report stats
				   for these ranges: only for fp maps
				   NOTE: when -C flag is used, and there are 
				   explicit fp ranges in cats or when the map 
				   is int, nsteps is ignored */
    } option;

    G_gisinit(argv[0]);

    module = G_define_module();
    G_add_keyword(_("raster"));
    G_add_keyword(_("statistics"));
    module->description =
	_("Generates area statistics for raster map layers.");

    /* Define the different options */

    option.cell = G_define_standard_option(G_OPT_R_INPUTS);

    option.output = G_define_standard_option(G_OPT_F_OUTPUT);
    option.output->required = NO;
    option.output->description =
	_("Name for output file (if omitted or \"-\" output to stdout)");

    option.fs = G_define_standard_option(G_OPT_F_SEP);
    option.fs->key_desc = "character|space|tab";
    option.fs->answer = "space";
    option.fs->description = _("Output field separator");

    option.nv = G_define_option();
    option.nv->key = "nv";
    option.nv->type = TYPE_STRING;
    option.nv->required = NO;
    option.nv->multiple = NO;
    option.nv->answer = "*";
    option.nv->description = _("String representing no data cell value");

    option.nsteps = G_define_option();
    option.nsteps->key = "nsteps";
    option.nsteps->type = TYPE_INTEGER;
    option.nsteps->required = NO;
    option.nsteps->multiple = NO;
    option.nsteps->answer = "255";
    option.nsteps->description =
	_("Number of fp subranges to collect stats from");

    /* Define the different flags */

    flag.one = G_define_flag();
    flag.one->key = '1';
    flag.one->description = _("One cell (range) per line");

    flag.A = G_define_flag();
    flag.A->key = 'A';
    flag.A->description = _("Print averaged values instead of intervals");
    flag.A->guisection = _("Print");

    flag.a = G_define_flag();
    flag.a->key = 'a';
    flag.a->description = _("Print area totals");
    flag.a->guisection = _("Print");

    flag.c = G_define_flag();
    flag.c->key = 'c';
    flag.c->description = _("Print cell counts");
    flag.c->guisection = _("Print");

    flag.p = G_define_flag();
    flag.p->key = 'p';
    flag.p->description =
	_("Print APPROXIMATE percents (total percent may not be 100%)");
    flag.p->guisection = _("Print");

    flag.l = G_define_flag();
    flag.l->key = 'l';
    flag.l->description = _("Print category labels");
    flag.l->guisection = _("Print");

    flag.g = G_define_flag();
    flag.g->key = 'g';
    flag.g->description = _("Print grid coordinates (east and north)");
    flag.g->guisection = _("Print");

    flag.x = G_define_flag();
    flag.x->key = 'x';
    flag.x->description = _("Print x and y (column and row)");
    flag.x->guisection = _("Print");

    flag.r = G_define_flag();
    flag.r->key = 'r';
    flag.r->description = _("Print raw indexes of fp ranges (fp maps only)");
    flag.r->guisection = _("Print");

    flag.n = G_define_flag();
    flag.n->key = 'n';
    flag.n->description = _("Suppress reporting of any NULLs");

    flag.N = G_define_flag();
    flag.N->key = 'N';
    flag.N->description =
	_("Suppress reporting of NULLs when all values are NULL");

    flag.C = G_define_flag();
    flag.C->key = 'C';
    flag.C->description = _("Report for cats fp ranges (fp maps only)");

    flag.i = G_define_flag();
    flag.i->key = 'i';
    flag.i->description = _("Read fp map as integer (use map's quant rules)");

    if (G_parser(argc, argv))
	exit(EXIT_FAILURE);

    name = option.output->answer;
    if (name != NULL && strcmp(name, "-") != 0) {
	if (NULL == freopen(name, "w", stdout)) {
	    G_fatal_error(_("Unable to open file <%s> for writing"), name);
	}
    }

    sscanf(option.nsteps->answer, "%d", &nsteps);
    if (nsteps <= 0) {
	G_warning(_("'%s' must be greater than zero; using %s=255"),
		  option.nsteps->key, option.nsteps->key);
	nsteps = 255;
    }
    cat_ranges = flag.C->answer;

    averaged = flag.A->answer;
    raw_output = flag.r->answer;
    as_int = flag.i->answer;
    nrows = Rast_window_rows();
    ncols = Rast_window_cols();

    fd = NULL;
    nfiles = 0;
    dp = -1;

    with_percents = flag.p->answer;
    with_counts = flag.c->answer;
    with_areas = flag.a->answer;
    with_labels = flag.l->answer;

    no_nulls = flag.n->answer;
    no_nulls_all = flag.N->answer;
    no_data_str = option.nv->answer;

    raw_data = flag.one->answer;
    with_coordinates = flag.g->answer;
    with_xy = flag.x->answer;
    if (with_coordinates || with_xy)
	raw_data = 1;

    /* get field separator */
    strcpy(fs, " ");
    if (option.fs->answer) {
	if (strcmp(option.fs->answer, "space") == 0)
	    *fs = ' ';
	else if (strcmp(option.fs->answer, "tab") == 0)
	    *fs = '\t';
	else if (strcmp(option.fs->answer, "\\t") == 0)
	    *fs = '\t';
	else
	    *fs = *option.fs->answer;
    }


    /* open all raster maps */
    if (option.cell->answers[0] == NULL)
	G_fatal_error(_("Raster map not found"));

    names = option.cell->answers;
    ptr = option.cell->answers;

    for (; *ptr != NULL; ptr++) {
	name = *ptr;
	fd = (int *)G_realloc(fd, (nfiles + 1) * sizeof(int));
	is_fp = (int *)G_realloc(is_fp, (nfiles + 1) * sizeof(int));
	DMAX = (DCELL *) G_realloc(DMAX, (nfiles + 1) * sizeof(DCELL));
	DMIN = (DCELL *) G_realloc(DMIN, (nfiles + 1) * sizeof(DCELL));

	fd[nfiles] = Rast_open_old(name, "");
	if (!as_int)
	    is_fp[nfiles] = Rast_map_is_fp(name, "");
	else {
	    is_fp[nfiles] = 0;
	    if (cat_ranges || nsteps != 255)
		G_warning(_("Raster map <%s> is reading as integer map! "
			    "Flag '-%c' and/or '%s' option will be ignored."),
			  name, flag.C->key, option.nsteps->key);
	}
	if (with_labels || (cat_ranges && is_fp[nfiles])) {
	    labels = (struct Categories *)
		G_realloc(labels, (nfiles + 1) * sizeof(struct Categories));
	    if (Rast_read_cats(name, "", &labels[nfiles]) < 0)
		Rast_init_cats("", &labels[nfiles]);
	}
	if (is_fp[nfiles])
	    /* floating point map */
	{
	    Rast_quant_init(&q);
	    if (cat_ranges) {
		if (!Rast_quant_nof_rules(&labels[nfiles].q)) {
		    G_warning(_("Cats for raster map <%s> are either missing or have no explicit labels. "
			       "Using %s=%d."),
			      name, option.nsteps->key, nsteps);
		    cat_ranges = 0;
		}
		else if (nsteps != 255)
		    G_warning(_("Flag '-%c' was given, using cats fp ranges of raster map <%s>, "
			       "ignoring '%s' option"),
			      flag.C->key, name, option.nsteps->key);
	    }
	    if (!cat_ranges) {	/* DO NOT use else here, cat_ranges can change */
		if (Rast_read_fp_range(name, "", &fp_range) < 0)
		    G_fatal_error(_("Unable to read fp range of raster map <%s>"),
				  name);
		Rast_get_fp_range_min_max(&fp_range, &DMIN[nfiles],
				       &DMAX[nfiles]);
		G_debug(3, "file %2d: dmin=%f  dmax=%f", nfiles, DMIN[nfiles], 
			DMAX[nfiles]);

		Rast_quant_add_rule(&q, DMIN[nfiles], DMAX[nfiles], 1, nsteps+1);

		/* set the quant rules for reading the map */
		Rast_set_quant_rules(fd[nfiles], &q);
		Rast_quant_get_limits(&q, &dmin, &dmax, &min, &max);
		G_debug(2, "overall: dmin=%f  dmax=%f,  qmin=%d  qmax=%d",
			dmin, dmax, min, max);

		Rast_quant_free(&q);
	    }
	    else {		/* cats ranges */

		/* set the quant rules for reading the map */
		Rast_set_quant_rules(fd[nfiles], &labels[nfiles].q);
		Rast_quant_get_limits(&labels[nfiles].q, &dmin, &dmax, &min,
				   &max);
	    }
	}
	else {
	    if (Rast_read_range(name, "", &range) < 0)
		G_fatal_error(_("Unable to read range for map <%s>"), name);
	    Rast_get_range_min_max(&range, &min, &max);
	}
	if (!null_set) {
	    null_set = 1;
	    NULL_CELL = max + 1;
	}
	else if (NULL_CELL < max + 1)
	    NULL_CELL = max + 1;

	nfiles++;
    }

    if (dp < 0)
	strcpy(fmt, "%lf");
    else
	sprintf(fmt, "%%.%dlf", dp);

    if (raw_data)
	raw_stats(fd, with_coordinates, with_xy, with_labels);
    else
	cell_stats(fd, with_percents, with_counts, with_areas, with_labels,
		   fmt);

    exit(EXIT_SUCCESS);
}
Ejemplo n.º 2
0
/*!
 * \brief Set a raster category label (DCELL)
 *
 * Adds the label for range <i>rast1</i> through <i>rast2</i> in
 * category structure <i>pcats</i>.
 *
 * \param rast1, rast2 raster values (range)
 * \param label category label
 * \param pcats pointer to Categories structure
 *
 * \return -1 on error
 * \return 0 if null value detected
 * \return 1 on success
 */
int Rast_set_d_cat(const DCELL * rast1, const DCELL * rast2,
		   const char *label, struct Categories *pcats)
{
    long len;
    DCELL dtmp1, dtmp2;
    int i;
    char *descr;

    /* DEBUG fprintf(stderr,"Rast_set_d_cat(rast1 = %p,rast2 = %p,label = '%s',pcats = %p)\n",
       rast1,rast2,label,pcats); */
    if (Rast_is_d_null_value(rast1))
	return 0;
    if (Rast_is_d_null_value(rast2))
	return 0;
    /* DEBUG fprintf (stderr, "Rast_set_d_cat(): adding quant rule: %f %f %d %d\n", *rast1, *rast2, pcats->ncats, pcats->ncats); */
    /* the set_cat() functions are used in many places to reset the labels
       for the range (or cat) with existing label. In this case we don't
       want to store both rules with identical range even though the result
       of get_cat() will be correct, since it will use rule added later.
       we don't want to overuse memory and we don't want rules which are
       not used to be writen out in cats file. So we first look if
       the label for this range has been sen, and if it has, overwrite it */

    for (i = 0; i < pcats->ncats; i++) {
	descr = Rast_get_ith_d_cat(pcats, i, &dtmp1, &dtmp2);
	if ((dtmp1 == *rast1 && dtmp2 == *rast2)
	    || (dtmp1 == *rast2 && dtmp2 == *rast1)) {
	    if (pcats->labels[i] != NULL)
		G_free(pcats->labels[i]);
	    pcats->labels[i] = G_store(label);
	    G_newlines_to_spaces(pcats->labels[i]);
	    G_strip(pcats->labels[i]);
	    return 1;
	}
    }
    /* when rule for this range does not exist */
    /* DEBUG fprintf (stderr, "Rast_set_d_cat(): New rule: adding %d %p\n", i, pcats->labels); */
    Rast_quant_add_rule(&pcats->q, *rast1, *rast2, pcats->ncats,
			pcats->ncats);
    pcats->ncats++;
    if (pcats->nalloc < pcats->ncats) {
	/* DEBUG fprintf (stderr, "Rast_set_d_cat(): need more space nalloc = %d ncats = %d\n", pcats->nalloc,pcats->ncats); */
	len = (pcats->nalloc + 256) * sizeof(char *);
	/* DEBUG fprintf (stderr, "Rast_set_d_cat(): allocating %d labels(%d)\n", pcats->nalloc + 256,(int)len); */
	if (len != (int)len) {	/* make sure len doesn't overflow int */
	    pcats->ncats--;
	    return -1;
	}
	/* DEBUG fprintf(stderr,"Rast_set_d_cat(): pcats->nalloc = %d, pcats->labels = (%p), len = %d\n",pcats->nalloc,pcats->labels,(int)len); */
	if (pcats->nalloc) {
	    /* DEBUG fprintf(stderr,"Rast_set_d_cat(): Realloc-ing pcats->labels (%p)\n",pcats->labels); */
	    pcats->labels =
		(char **)G_realloc((char *)pcats->labels, (int)len);
	}
	else {
	    /* DEBUG fprintf(stderr,"Rast_set_d_cat(): alloc-ing new labels pointer array\n"); */
	    pcats->labels = (char **)G_malloc((int)len);
	}
	/* fflush(stderr); */
	/* DEBUG fprintf (stderr, "Rast_set_d_cats(): allocating %d marks(%d)\n", pcats->nalloc + 256,(int)len); */
	len = (pcats->nalloc + 256) * sizeof(int);
	if (len != (int)len) {	/* make sure len doesn't overflow int */
	    pcats->ncats--;
	    return -1;
	}
	if (pcats->nalloc)
	    pcats->marks = (int *)G_realloc((char *)pcats->marks, (int)len);
	else
	    pcats->marks = (int *)G_malloc((int)len);
	pcats->nalloc += 256;
    }
    /* DEBUG fprintf(stderr,"Rast_set_d_cats(): store new label\n"); */
    pcats->labels[pcats->ncats - 1] = G_store(label);
    G_newlines_to_spaces(pcats->labels[pcats->ncats - 1]);
    G_strip(pcats->labels[pcats->ncats - 1]);
    /* DEBUG
       fprintf (stderr, "%d %s\n", pcats->ncats - 1, pcats->labels[pcats->ncats - 1]);
     */
    /* updates cats.num = max cat values. This is really just used in old
       raster programs, and I am doing it for backwards cmpatibility (Olga) */
    if ((CELL) * rast1 > pcats->num)
	pcats->num = (CELL) * rast1;
    if ((CELL) * rast2 > pcats->num)
	pcats->num = (CELL) * rast2;
    /* DEBUG fprintf(stderr,"Rast_set_d_cat(): done\n"); */
    /* DEBUG fflush(stderr); */
    return 1;
}
Ejemplo n.º 3
0
int read_rules(const char *filename)
{
    char buf[1024];
    DCELL dLow, dHigh;
    CELL iLow, iHigh;
    int line, n, nrules = 0;
    int first = 1;
    DCELL dmin, dmax;
    CELL cmin, cmax;
    FILE *fp;

    if (strcmp(filename, "-") == 0)
        fp = stdin;
    else {
        fp = fopen(filename, "r");
        if (!fp)
            G_fatal_error(_("unable to open input file <%s>"), filename);
    }

    read_range();
    report_range();
    if (isatty(fileno(fp)))
        fprintf(stderr, _("\nEnter the rule or 'help' for the format description or 'end' to exit:\n"));
    Rast_quant_init(&quant_struct);
    for (line = 1;; line++) {
        if (isatty(fileno(fp)))
            fprintf(stderr, "> ");
        if (!G_getl2(buf, sizeof(buf), fp))
            break;
        for (n = 0; buf[n]; n++)
            if (buf[n] == ',')
                buf[n] = ' ';
        G_strip(buf);
        G_chop(buf);
        if (*buf == 0)
            continue;
        if (*buf == '#')
            continue;
        if (strcmp(buf, "end") == 0) {
            if (nrules == 0)
                break;		/* if no new rules have been specified */

            /* give warning when quant rules do not cover the whole range of map */
            Rast_quant_get_limits(&quant_struct, &dmin, &dmax, &cmin, &cmax);
            if ((dmin > old_dmin || dmax < old_dmax) && !first)
                G_warning(_("quant rules do not cover the whole range map"));
            break;
        }

        if (strcmp(buf, "help") == 0) {
            fprintf(stderr,
                    "Enter a rule in one of these formats:\n"
                    "float_low:float_high:int_low:int_high\n"
                    "float_low:float_high:int_val  (i.e. int_high == int_low)\n"
                    "*:float_val:int_val           (interval [inf, float_val])\n"
                    "float_val:*:int_val           (interval [float_val, inf])\n");
        }

        /* we read and record into quant table all values, even int as doubles
           we convert the range and domain values to the right format when we
           lookup the values in the quant table */
        switch (sscanf(buf, "%lf:%lf:%d:%d", &dLow, &dHigh, &iLow, &iHigh)) {
        case 3:
            Rast_quant_add_rule(&quant_struct, dLow, dHigh, iLow, iLow);
            nrules++;
            first = 0;
            break;

        case 4:
            Rast_quant_add_rule(&quant_struct, dLow, dHigh, iLow, iHigh);
            nrules++;
            first = 0;
            break;

        default:
            if (sscanf(buf, "%lf:*:%d", &dLow, &iLow) == 2) {
                Rast_quant_set_pos_infinite_rule(&quant_struct, dLow, iLow);
                nrules++;
                first = 0;
            }

            else if (sscanf(buf, "*:%lf:%d", &dHigh, &iLow) == 2) {
                Rast_quant_set_neg_infinite_rule(&quant_struct, dHigh, iLow);
                nrules++;
                first = 0;
            }

            else if (strcmp(buf, "help") == 0)
                break;

            else
                G_warning(_("%s is not a valid rule"), buf);
            break;
        }			/* switch */
    }				/* loop */

    if (fp != stdin)
        fclose(fp);

    return nrules;
}