/*-------------------------------------------------------------------- * $Id: grdinfo.c,v 1.2.4.4 2002/02/27 17:41:10 pwessel Exp $ * * Copyright (c) 1991-2002 by P. Wessel and W. H. F. Smith * See COPYING file for copying and redistribution conditions. * * 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; version 2 of the License. * * 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 General Public License for more details. * * Contact info: gmt.soest.hawaii.edu *--------------------------------------------------------------------*/ /* * grdinfo reads one or more grd file and [optionally] prints out various * statistics like mean/standard deviation and median/scale * * Author: Paul Wessel * Date: 20-OCT-1999 * Version: 3.1 Based on 3.0 * 3.3.2 Added -D option * 3.3.3 Added -F option via M. Odegard * 3.3.5 12-JUL-2000 * Version: 3.4.1 */ #include "gmt.h" void GMT_format_ddmmss (double val, char *format); float *a; char *type[2] = { "Normal", "Pixel"}; main (int argc, char **argv) { int nfiles = 0, k, i, j, i_min, i_max, nm, n_nan = 0, n; BOOLEAN error = FALSE, l1 = FALSE, l2 = FALSE, quick = TRUE, find_max = FALSE; BOOLEAN world_form = FALSE, geographic = FALSE, columns = FALSE; double x_min, y_min, z_min, x_max, y_max, z_max; double mean, median, sum2, stdev, scale, rms, x, half; char file[BUFSIZ], format[BUFSIZ]; struct GRD_HEADER grd; argc = GMT_begin (argc, argv); for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { /* Common parameters */ case 'V': case '\0': error += GMT_get_common_args (argv[i], 0, 0, 0, 0); break; /* Supplemental parameters */ case 'C': columns = TRUE; break; case 'D': geographic = TRUE; break; case 'F': world_form = TRUE; break; case 'M': quick = FALSE; find_max = TRUE; break; case 'L': quick = FALSE; if (argv[i][2] == 0 || argv[i][2] == '2') l2 = TRUE; else if (argv[i][2] == '1') l1 = TRUE; else { error = TRUE; fprintf (stderr, "%s: GMT SYNTAX ERROR -L option: Choose between -L1 or -L2\n", GMT_program); } break; default: error = TRUE; GMT_default_error (argv[i][1]); break; } } else nfiles ++; } if (argc == 1 || GMT_quick) { fprintf (stderr, "grdinfo %s - Extract information from netCDF grdfiles\n\n", GMT_VERSION); fprintf (stderr, "usage: grdinfo [-C] [-D] [-F] [-L1] [-L[2]] [-M]\n"); if (GMT_quick) exit (EXIT_FAILURE); fprintf (stderr, "\t may be one or more netCDF grdfiles\n"); fprintf (stderr, "\n\tOPTIONS:\n"); fprintf (stderr, "\t-C formats report in fields on a single line using the format\n"); fprintf (stderr, "\t file w e s n z0 z1 dx dy nx ny [x0 y0 x1 y1] [med scale] [mean std rms] [n_nan]\n"); fprintf (stderr, "\t (-M gives [x0 y0 x1 y1] and [n_nan]; -L1 gives [med scale]; -L2 gives [mean std rms])\n"); fprintf (stderr, "\t-D reports domain in dd:mm:ss format [Default is decimal]\n"); fprintf (stderr, "\t-F reports domain in world mapping format [Default is generic]\n"); fprintf (stderr, "\t-L1 reports median and L1-scale of data set\n"); fprintf (stderr, "\t-L[2] reports mean, standard deviation, and rms of data set\n"); fprintf (stderr, "\t-M searches for the global min and max locations (x0,y0) and (x1,y1)\n"); GMT_explain_option ('V'); exit (EXIT_FAILURE); } if (nfiles == 0) { fprintf (stderr, "%s: GMT SYNTAX ERROR: Must specify one or more input files\n", GMT_program); error++; } if (geographic && world_form) { fprintf (stderr, "%s: GMT SYNTAX ERROR: Must specify only one of -D and -F\n", GMT_program); error++; } if (error) exit (EXIT_FAILURE); GMT_put_history (argc, argv); /* Update .gmtcommands */ a = (float *) GMT_memory (VNULL, (size_t)1, sizeof (float), GMT_program); for (k = 1; k < argc; k++) { /* Loop over arguments, skip options */ if (argv[k][0] == '-') continue; strcpy (file, argv[k]); for (j = 0; file[j]; j++) if (file[j] == '=') file[j] = 0; if (strcmp (file, "=") && access (file, R_OK)) { fprintf (stderr, "%s: File %s not found\n", GMT_program, file); continue; } GMT_grd_init (&grd, argc, argv, FALSE); if (GMT_read_grd_info (argv[k], &grd)) { fprintf (stderr, "%s: Error opening file %s\n", GMT_program, file); continue; } if (gmtdefs.verbose) fprintf (stderr, "%s: Processing file %s\n", GMT_program, file); half = (grd.node_offset) ? 0.5 : 0.0; if (grd.z_min == grd.z_max && GMT_grd_i_format) quick = FALSE, find_max = TRUE; if (!quick) { /* Must determine the location of global min and max values */ nm = grd.nx * grd.ny; a = (float *) GMT_memory ((void *)a, (size_t)nm, sizeof (float), GMT_program); if (GMT_read_grd (argv[k], &grd, a, 0.0, 0.0, 0.0, 0.0, GMT_pad, FALSE)) continue; z_min = DBL_MAX; z_max = -DBL_MAX; mean = median = sum2 = 0.0; i_min = i_max = 0; n_nan = 0; for (i = 0; i < nm; i++) { if (GMT_is_fnan (a[i])) { n_nan++; continue; } if (find_max) { if (a[i] < z_min) { z_min = a[i]; i_min = i; } if (a[i] > z_max) { z_max = a[i]; i_max = i; } } if (l2) { mean += a[i]; sum2 += a[i]*a[i]; } } x_min = grd.x_min + ((i_min % grd.nx) + half) * grd.x_inc; y_min = grd.y_max - ((i_min / grd.nx) + half) * grd.y_inc; x_max = grd.x_min + ((i_max % grd.nx) + half) * grd.x_inc; y_max = grd.y_max - ((i_max / grd.nx) + half) * grd.y_inc; } if (l1) { /* Calculate the median and L1 scale */ qsort ((void *)a, (size_t)nm, sizeof (float), GMT_comp_float_asc); n = nm - n_nan; median = (n%2) ? a[n/2] : 0.5*(a[n/2-1] + a[n/2]); for (i = 0; i < n; i++) a[i] = (float)fabs (a[i] - median); qsort ((void *)a, (size_t)n, sizeof (float), GMT_comp_float_asc); scale = (n%2) ? 1.4826 * a[n/2] : 0.7413 * (a[n/2-1] + a[n/2]); } if (l2) { /* Calculate the mean, standard deviation, and rms */ x = (double)(nm - n_nan); stdev = (rint (x) > 1.0) ? sqrt((x*sum2 - mean*mean)/(x*(x-1))) : GMT_d_NaN; rms = (rint (x) > 0.0) ? sqrt (sum2 / x) : GMT_d_NaN; mean = (rint (x) > 0.0) ? mean / x : GMT_d_NaN; } /* OK, time to report results */ if (columns) { sprintf (format, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%d\t%d", file, gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format, grd.nx, grd.ny); fprintf (GMT_stdout, format, grd.x_min, grd.x_max, grd.y_min, grd.y_max, grd.z_min, grd.z_max, grd.x_inc, grd.y_inc); if (find_max) { sprintf (format, "\t%s\t%s\t%s\t%s", gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format); fprintf (GMT_stdout, format, x_min, y_min, x_max, y_max); } if (l1) { sprintf (format, "\t%s\t%s\n", gmtdefs.d_format, gmtdefs.d_format); fprintf (GMT_stdout, format, median, scale); } if (l2) { sprintf (format, "\t%s\t%s\t%s", gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format); fprintf (GMT_stdout, format, mean, stdev, rms); } if (find_max) fprintf (GMT_stdout, "\t%d", n_nan); fprintf (GMT_stdout, "\n"); } else { fprintf (GMT_stdout, "%s: Title: %s\n", file, grd.title); fprintf (GMT_stdout, "%s: Command: %s\n", file, grd.command); fprintf (GMT_stdout, "%s: Remark: %s\n", file, grd.remark); fprintf (GMT_stdout, "%s: %s node registration used\n", file, type[grd.node_offset]); fprintf (GMT_stdout, "%s: grdfile format # %d\n", file, GMT_grd_i_format); if (geographic) { char item1[80], item2[80], item3[80]; GMT_format_ddmmss (grd.x_min, item1); GMT_format_ddmmss (grd.x_max, item2); GMT_format_ddmmss (grd.x_inc, item3); fprintf (GMT_stdout, "%s: x_min: %s x_max: %s x_inc: %s units: %s nx: %d\n", file, item1, item2, item3, grd.x_units, grd.nx); GMT_format_ddmmss (grd.y_min, item1); GMT_format_ddmmss (grd.y_max, item2); GMT_format_ddmmss (grd.y_inc, item3); fprintf (GMT_stdout, "%s: y_min: %s y_max: %s y_inc: %s units: %s ny: %d\n", file, item1, item2, item3, grd.y_units, grd.ny); } else if (world_form) { if ((fabs (grd.x_min) < 500.0) && (fabs (grd.x_max) < 500.0) && (fabs (grd.y_min) < 500.0) && (fabs (grd.y_max) < 500.0)) { fprintf (GMT_stdout, "%s: x_min: %.7f\n", file, grd.x_min); fprintf (GMT_stdout, "%s: x_max: %.7f\n", file, grd.x_max); fprintf (GMT_stdout, "%s: x_inc: %.7f\n", file, grd.x_inc); fprintf (GMT_stdout, "%s: units: %s\n", file, grd.x_units); fprintf (GMT_stdout, "%s: nx: %d\n", file, grd.nx); fprintf (GMT_stdout, "%s: y_min: %.7f\n", file, grd.y_min); fprintf (GMT_stdout, "%s: y_max: %.7f\n", file, grd.y_max); fprintf (GMT_stdout, "%s: y_inc: %.7f\n", file, grd.y_inc); fprintf (GMT_stdout, "%s: units: %s\n", file, grd.y_units); fprintf (GMT_stdout, "%s: ny: %d\n", file, grd.ny); } else { fprintf (GMT_stdout, "%s: x_min: %.2f\n", file, grd.x_min); fprintf (GMT_stdout, "%s: x_max: %.2f\n", file, grd.x_max); fprintf (GMT_stdout, "%s: x_inc: %.2f\n", file, grd.x_inc); fprintf (GMT_stdout, "%s: units: %s\n", file, grd.x_units); fprintf (GMT_stdout, "%s: nx: %d\n", file, grd.nx); fprintf (GMT_stdout, "%s: y_min: %.2f\n", file, grd.y_min); fprintf (GMT_stdout, "%s: y_max: %.2f\n", file, grd.y_max); fprintf (GMT_stdout, "%s: y_inc: %.2f\n", file, grd.y_inc); fprintf (GMT_stdout, "%s: units: %s\n", file, grd.y_units); fprintf (GMT_stdout, "%s: ny: %d\n", file, grd.ny); } } else { sprintf (format, "%s: x_min: %s x_max: %s x_inc: %s units: %s nx: %d\n", file, gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format, grd.x_units, grd.nx); fprintf (GMT_stdout, format, grd.x_min, grd.x_max, grd.x_inc); sprintf (format, "%s: y_min: %s y_max: %s y_inc: %s units: %s ny: %d\n", file, gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format, grd.y_units, grd.ny); fprintf (GMT_stdout, format, grd.y_min, grd.y_max, grd.y_inc); } if (find_max) { if (z_min == -DBL_MAX) z_min = GMT_d_NaN; if (z_max == +DBL_MAX) z_max = GMT_d_NaN; sprintf (format, "%s: z_min: %s at x = %s y = %s z_max: %s at x = %s y = %s units: %s\n", file, gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format, grd.z_units); fprintf (GMT_stdout, format, z_min, x_min, y_min, z_max, x_max, y_max); } else if (world_form) { fprintf (GMT_stdout, "%s: zmin: %lg\n", file, grd.z_min); fprintf (GMT_stdout, "%s: zmax: %lg\n", file, grd.z_max); fprintf (GMT_stdout, "%s: units: %s\n", file, grd.z_units); } else { sprintf (format, "%s: z_min: %s z_max: %s units: %s\n", file, gmtdefs.d_format, gmtdefs.d_format, grd.z_units); fprintf (GMT_stdout, format, grd.z_min, grd.z_max); } sprintf (format, "%s: scale_factor: %s add_offset: %s\n", file, gmtdefs.d_format, gmtdefs.d_format); fprintf (GMT_stdout, format, grd.z_scale_factor, grd.z_add_offset); if (n_nan) fprintf (GMT_stdout, "%s: %d nodes set to NaN\n", file, n_nan); if (l1) { sprintf (format, "%s: median: %s scale: %s\n", file, gmtdefs.d_format, gmtdefs.d_format); fprintf (GMT_stdout, format, median, scale); } if (l2) { sprintf (format, "%s: mean: %s stdev: %s rms: %s\n", file, gmtdefs.d_format, gmtdefs.d_format, gmtdefs.d_format); fprintf (GMT_stdout, format, mean, stdev, rms); } } } GMT_free ((void *)a); GMT_end (argc, argv); } void GMT_format_ddmmss (double val, char *format) { int sign, minutes, seconds, ival; double frac_sec, f_seconds; /* Return a formatted dd:mm:ss or dd:mm:ss.fff string */ sign = (val < 0.0) ? -1 : 1; val = fabs (val); ival = (int)val; /* Truncate to integer in the direction toward 0 */ minutes = seconds = 0; if ((val - (double) ival) > SMALL) { minutes = (int)floor (((val - ival) * 60.0) + SMALL); if (minutes == 60) { minutes = 0; ival = irint (val); } f_seconds = (val - (double)ival - (double)minutes / 60.0) * 3600.0; seconds = (int)floor (f_seconds + SMALL); frac_sec = f_seconds - (double)seconds; if (seconds == 60 && frac_sec < SMALL) { seconds = 0; minutes++; if (minutes == 60) { minutes = 0; ival = irint (val); } } } if (frac_sec > SMALL) /* Must preserve second fraction */ sprintf (format, "%d:%2.2d:%2.2d.%3.3d", sign * ival, minutes, seconds, irint (1000.0 * frac_sec)); else sprintf (format, "%d:%2.2d:%2.2d", sign * ival, minutes, seconds); }