OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
o3qc.c
Go to the documentation of this file.
1 /*******************************************************************
2  * File: o3qc.c
3  *
4  * Purpose: QC HDF ancillary real time OZONE datafile against
5  * climatology for the same month.
6  *
7  * Description: This program will create a HDF with:
8  * 2-D of standard devs of real to clim (parameter = OZONE)
9  * A mailable (stdout) text file of %points in each STD category.
10  *
11  * The real time parameter is read into array RT. The climatological average
12  * and standard deviation for the same time period (month) is read into
13  * CLMAVG and CLMSTD respectively. The CLMAVG array is subtracted from the
14  * RT array and divided by the CLMSTD array to produce an array of the
15  * number of std deviations from the mean for the real-time data.
16  * As the data is processed a tally of points falling + and - 1, 2, and 3
17  * STDs from the mean will be stored for later writing of percentages in
18  * each category.
19  *
20  * For OZONE data:
21  * The real time parameters are read into array ozoneRT
22  *
23  * The climatological averages and standard deviations for the same time
24  * period (month) are read into:
25  * ozoneCLMAVG and ozoneCLMSTD respectively.
26  *
27  * Real-time and climatology files are dimensioned 180x288.
28  * S19891991_TOMS.OZONE does not require regidding like the MET file did.
29  *
30  *
31  * Input parms (command line arguments):
32  * o3qc <nrtfile> <climfile> <outfile> <monthstr> ozone <stdlimit1>
33  * <stdlimit2> <stdlimit3> <maxmissing> <maxmissing> [loval] [hival]
34  * [outmax] [min_lat] [max_lat] [gridflag] [ifileflag]
35  *
36  * <nrtfile> (char *) - real-time input file to process
37  * ("a199310000_TOVS.OZONE")
38  * <climfile> (char *) - clim input file to process
39  * ("S19891991_TOMS.OZONE")
40  * <outfile> (char *) - output QC filename
41  * ("S199310000_TOVS.OZONE.qc")
42  * <monthstr> (char *) - month being processed
43  * <stdlimit1> (float32) - % w/in 1 STD
44  * <stdlimit2> (float32) - % w/in 2 STD
45  * <stdlimit3> (float32) - % w/in 3 STD
46  * <maxmissing> (int) - max num missing pts.
47  *
48  * Optional inputs: (defaults are available, described below)
49  * [loval] (int) - lowest acceptable value in NRT file
50  * [hival] (int) - highest acceptable value in NRT file
51  * [outmax] (int) - # of points that can be outside lo/hival before
52  * an error flag is set
53  * [min_lat] (float) - minimum latitude above which to check, default -90.
54  * [max_lat] (float) - maximum latitude below which to check, default 90.
55  * NOTE that if min_lat = 95, the limits will be determined using
56  * the julian day in the equation:
57  * zen = -23. * cos( ( jday + 10 ) * 360 / 365 )
58  * min_lat = -90. + zen + mmoffset
59  * max_lat = 90. - zen - mmoffset
60  * where mmoffset = max_lat and defaults to 10. if nothing there
61  * [gridflag] (char) - 's' or 'd' for std dev or direct numeric difference
62  * only the 's' option is valid for statistical reporting.
63  * [ifileflag] (int) - a 1 if the input realtime file name is actually a
64  * climatology file. 0 or blank if not.
65  *
66  * Output parms:
67  * Example name: "S199312300_TOVS.OZONE.qc"
68  *
69  * Returns: SUCCESS or FAILURE depending on threshold checks.
70  *
71  * Local vars: numerous variables for storing HDFs.
72  *
73  * Subs called: int rdsds - reads an HDF SDS data grid
74  * int8 check_usage - confirm args
75  * int startHDF - open HDF file for output
76  * int setupGrid - setup HDF geometry struct
77  * int writeGeom - write HDF geometry struct
78  * int wrtsds - write HDF SDS array
79  * int addAttr - add HDF SDS attributes
80  * int setSDSref - set HDF SDS reference
81  * void deattachHDFgrid - detach HDF grid struct
82  * int closeHDFstructs - close HDF files
83  *
84  * History: none
85  *
86  * Note: This program is meant to generate HDF QC SDS data sets.
87  *
88  * Author: Brian D. Schieber, GSC, 4/93
89  *
90  * Modification history:
91  * 10/8/93 BDS, work with new HDF design format
92  * 03/94 BDS, mods to run from script and work in CVDB
93  * 05/94 BDS, outfile is passed in rather than derived.
94  * 08/95 BDS, mod to reflect NRT and CLM HDF format changes (spec 2.7).
95  * 11/95 BDS, add ability to sum number of values in image < or >
96  * two specified range arguments and return FAIL if > outmax.
97  * Values for LO(lower range), HI (upper range),
98  * and OUTMAX (MAX. Pts allowed outside range) hardcoded within.
99  * Also, print min and max value of data.
100  * 8/96 BDS, renamed 'perror' to 'pexit' to avoid HDF4.0 conflict.
101  * W. Robinson, GSC, 13 Mar 97 add a latitude range to perform check
102  * within (for use with TOMS data which misses the pole(s))
103  * 6/97 KJS. Problems with SUN port due to strings not being
104  * long enough - gridflg, sdsname. Changed malloc to calloc-
105  * QC array outside lats was not being initialized. Hdiff issue.
106  * W. Robinson, GSC, 16 jun 97 add feature for day-of-year controlled
107  * min, max latitude
108  * W. Robinson, SAIC, 28 Sep 07 for count of high and low O3, weight by
109  * cos( lat )
110  **************************************************************************/
111 
112 #include "ancil.h"
113 #include "l1io.h"
114 #include <genutils.h>
115 
116 /*
117  * Ozone specific settings
118  */
119 
120 #define VGROUPCLASS "PlanetaryGrid"
121 #define BIN_METH 2
122 #define REGISTRATION CENTER
123 #define VSIZE 1.25
124 #define HSIZE 1.00
125 #define MAX_NORTH 89.5
126 #define MAX_SOUTH -89.5
127 #define MAX_WEST -179.375
128 #define MAX_EAST 179.375
129 #define TOMSLATSZ 180
130 #define TOMSLONSZ 288
131 #define CLMfile 1
132 
133 int main(int argc, char *argv[]) {
134  int i, j, l;
135  int rank;
136  int result = 0;
137  int missing = 0;
138  int minval = 1000; /* initial minimum value of all points */
139  int maxval = -1; /* initial maximum value of all points */
140  int rtmiss = 0;
141  int neg1cnt = 0;
142  int neg2cnt = 0;
143  int neg3cnt = 0;
144  int pos1cnt = 0;
145  int pos2cnt = 0;
146  int pos3cnt = 0;
147  int failed = 0;
148  int totalpts = 0;
149  int array_size = 0;
150  int32 inShape[2];
151  int32 shape[2];
152  char infileRT[MAXNAMELNG];
153  char infileCLM[MAXNAMELNG];
154  char monthstr[10];
155  char sdsname[MAXNAMELNG];
156  char vgroupname[MAXNAMELNG];
157  char gridflag[2];
158  char datalabel[MAXNAMELNG];
159  char *dataattr;
160  char *dataunit;
161  char outfile[MAXNAMELNG];
162  int ifileflag = 0;
163  float32 stdlimit1, stdlimit2, stdlimit3;
164  int maxmissing;
165  int loval = 100; /* default lo range threshold */
166  int hival = 500; /* default hi range threshold */
167  int outmax = 25; /* max num pts allowed to fall outside range */
168  int locnt; /* pts under lo limit */
169  int hicnt; /* pts above hi limit */
170  float flocnt = 0., fhicnt = 0., coslat;
171 
172  int min_lin = (-20), max_lin = (TOMSLATSZ + 20), pts_used;
173  float min_lat = -90., max_lat = 90., mmoffset = 10., zen, lat;
174  float pi;
175  int jday;
176 
177  int lo_cnts[5] = {0, 0, 0, 0, 0}, hi_cnts[5] = {0, 0, 0, 0, 0};
178  int z_st[4] = {-1, -1, -1, -1}, z_en[4] = {-1, -1, -1, -1};
179  int lo_vals[5] = {50, 100, 150, 200, 250},
180  hi_vals[5] = {400, 450, 500, 550, 600};
181  int in_z_run = 0, zcur = 0, zline, ipx, iv; /* for extra info on data */
182 
183  /*
184  * HDF datafile variables
185  */
186 
187  int32 sdfid, fid;
188  int32 gridid, sdsid, geomid;
189  int32 datatype;
190  char vgname[MAXNAMELNG];
191 
192  /*
193  * data type array pointers
194  */
195 
196  int16 *int_SDSdataRT;
197  int16 *int_SDSdataCLMAVG;
198  int16 *int_SDSdataCLMSTD;
199  float32 *float_SDSdataQC;
200 
201  /* external functions used */
202 
203  int8 check_usage();
204 
205  int anc_daymon(char *, int*, char*);
206  /*
207  * ------- check command line arguments and set args ------------------
208  */
209  pi = acos(-1.);
210 
211  strcpy(gridflag, "s");
212  if ((check_usage(argc, argv)) != 0) pexit("insufficient args provided");
213  strcpy(infileRT, argv[1]);
214  strcpy(infileCLM, argv[2]);
215  strcpy(outfile, argv[3]);
216  strcpy(monthstr, argv[4]);
217 
218  if (!strcmp(lowcase(argv[5]), "ozone"))
219  strcpy(vgroupname, "Geophysical Data");
220  else if (!strcmp(lowcase(argv[5]), "uwind"))
221  pexit("Only OZONE parameter supported by this program.");
222  else if (!strcmp(lowcase(argv[5]), "vwind"))
223  pexit("Only OZONE parameter supported by this program.");
224  else if (!strcmp(lowcase(argv[5]), "pres"))
225  pexit("Only OZONE parameter supported by this program.");
226  else if (!strcmp(lowcase(argv[5]), "rhum"))
227  pexit("Only OZONE parameter supported by this program.");
228  else pexit("Invalid Parameter string specified");
229 
230  sscanf(argv[6], "%f", &stdlimit1);
231  sscanf(argv[7], "%f", &stdlimit2);
232  sscanf(argv[8], "%f", &stdlimit3);
233  sscanf(argv[9], "%d", &maxmissing);
234  if (argc >= 11) sscanf(argv[10], "%d", &loval);
235  if (argc >= 12) sscanf(argv[11], "%d", &hival);
236  if (argc >= 13) sscanf(argv[12], "%d", &outmax);
237  if (argc >= 14) sscanf(argv[13], "%f", &min_lat);
238  if (argc >= 15) sscanf(argv[14], "%f", &max_lat);
239 
240  if (argc >= 16) {
241  strncpy(gridflag, argv[15], 1);
242  gridflag[1] = '\0';
243  }
244  if (argc == 17) ifileflag = atoi(argv[16]);
245 
246  /*
247  * -------- Allocate space for 2D data arrays -----------------------
248  */
249 
250  rank = 2;
251  shape[0] = TOMSLATSZ; /* lat */
252  shape[1] = TOMSLONSZ; /* lon */
253  array_size = shape[0] * shape[1];
254 
255  if ((int_SDSdataRT =
256  /* (int16 *) malloc (sizeof(int16) * array_size)) == NULL) */
257  (int16 *) calloc(array_size, sizeof (int16))) == NULL)
258  pexit("calloc int_SDSdataRT");
259 
260  if ((int_SDSdataCLMAVG =
261  /* (int16 *) malloc (sizeof(int16) * array_size)) == NULL) */
262  (int16 *) calloc(array_size, sizeof (int16))) == NULL)
263  pexit("calloc int_SDSdataCLMAVG");
264 
265  if ((int_SDSdataCLMSTD =
266  /* (int16 *) malloc (sizeof(int16) * array_size)) == NULL) */
267  (int16 *) calloc(array_size, sizeof (int16))) == NULL)
268  pexit("calloc int_SDSdataCLMSTD");
269 
270  if ((float_SDSdataQC =
271  /* (float32 *) malloc (sizeof(float32) * array_size)) == NULL) */
272  (float32 *) calloc(array_size, sizeof (float32))) == NULL)
273  pexit("calloc float_SDSdataQC");
274 
275  /*
276  * ------- Determine appropriate real-time (SDS) to match clim. file -----
277  * (The "real-time" file could also be a clim. itself.)
278  * In OZONE NRT there are two SDS's in the realtime file:
279  * "ozone" and "ozone_QC"
280  *
281  * In OZONE CLM there are 3 SDSs X 12 months or 36 SDS arrays.
282  * The below matching must consider or determine:
283  * - The NRT month desired
284  * - The corresponding CLM "Statistics" SDS
285  */
286 
287  /*
288  * Read CLM type file if ifileflag == CLMfile.
289  * Read NRT type file otherwise and by default.
290  */
291 
292  if (ifileflag == CLMfile) {
293  strcpy(vgname, monthstr);
294  strcpy(sdsname, "ozone_mean");
295  } else {
296  strcpy(vgname, vgroupname);
297  strcpy(sdsname, "ozone");
298  /*
299  * The month will be derived from the file start day rather than the
300  * input month.
301  * Read start day attribute
302  */
303  if (anc_daymon(infileRT, &jday, monthstr) != 0)
304  pexit("in getting day, month");
305  /*
306  * add logic to get proper min, max lat
307  */
308  if (min_lat == 95.) {
309  if (argc >= 15) mmoffset = max_lat;
310  zen = -23. * cos((jday + 10.) * 2 * pi / 365.);
311  min_lat = -90. + zen + mmoffset;
312  if (min_lat < -90.) min_lat = -90.;
313  max_lat = 90. + zen - mmoffset;
314  if (max_lat > 90.) max_lat = 90.;
315  printf("day dependent min, max latitude chosen:\n");
316  printf("day = %d, mmoffset = %f, sun lat = %f\n",
317  jday, mmoffset, zen);
318  }
319  }
320 
321  if ((rdsds(infileRT, vgname, sdsname, inShape,
322  int_SDSdataRT)) != 0) pexit("rdsds RT");
323 
324  if ((inShape[0] != shape[0]) || (inShape[1] != shape[1]))
325  pexit("real-time dimensions not matching expected");
326 
327  /*
328  * ------- Determine appropriate climatology month (SDS) to match ------
329  * real time file. Get the average and std.dev. SDSs.
330  */
331 
332  strcpy(vgname, monthstr);
333  strcpy(sdsname, "ozone_mean");
334 
335  if ((rdsds(infileCLM, vgname, sdsname, inShape,
336  int_SDSdataCLMAVG)) != 0) pexit("rdsds CLMAVG");
337 
338  if ((inShape[0] != shape[0]) || (inShape[1] != shape[1]))
339  pexit("clim avg dimensions not matching expected");
340 
341  strcpy(sdsname, "ozone_std_dev");
342 
343  if ((rdsds(infileCLM, vgname, sdsname, inShape,
344  int_SDSdataCLMSTD)) != 0) pexit("rdsds CLMSTD");
345 
346  if ((inShape[0] != shape[0]) || (inShape[1] != shape[1]))
347  pexit("clim std dimensions not matching expected");
348 
349  /* Out for now
350  l = 0;
351  for (i = 0; i < TOMSLATSZ; i++) {
352  printf ("\n");
353  for (j = 0; j < TOMSLONSZ; j++) {
354  printf ("%d ", int_SDSdataRT[l]);
355  l++;
356  }
357  }
358  */
359 
360  /*
361  * ------- Compute variance of real-time from climatology -----------
362  * and tally missing points, #+ & - 1,2,3 std dev
363  * for writing to file for mailing.
364  */
365 
366  l = 0;
367  missing = 0;
368  locnt = 0;
369  hicnt = 0;
370  rtmiss = 0;
371  neg1cnt = 0;
372  neg2cnt = 0;
373  neg3cnt = 0;
374  pos1cnt = 0;
375  pos2cnt = 0;
376  pos3cnt = 0;
377  pts_used = 0;
378 
379  for (i = 0; i < TOMSLATSZ; i++) {
380  /*
381  * this code will find the 1st 4 runs of lines with all 0 values
382  */
383  zline = 1; /* say this line is a zero line */
384  if (zcur < 4) /* only can do first 4 0 runs (should be max of 2 */ {
385  for (ipx = 0; ipx < TOMSLONSZ; ipx++) /* look for != 0 pix i line */ {
386  if (int_SDSdataRT[l + ipx] > 0) {
387  zline = 0; /* this is not a zero line */
388  if (in_z_run == 1) {
389  z_en[zcur] = i - 1; /* if we find a non-zero line while in a */
390  zcur++; /* run of zero lines, note the end of the */
391  in_z_run = 0; /* run and say we are out of a zero run */
392  }
393  break;
394  }
395  }
396  /*
397  * if a line is found = 0, we either start a run if we are not in one
398  * or continue in current zero run
399  */
400  if (zline == 1) {
401  if (in_z_run == 0) {
402  z_st[ zcur ] = i;
403  in_z_run = 1;
404  }
405  if (i == TOMSLATSZ - 1) z_en[ zcur ] = i;
406  }
407  }
408  /*** end run location code ***/
409  /*
410  * only do data within the min, max latitude range
411  */
412  lat = 90. - (i * 180. / TOMSLATSZ);
413  coslat = cos(lat);
414  if (lat >= min_lat && lat <= max_lat) {
415  pts_used += TOMSLONSZ;
416  if (i > min_lin) min_lin = i;
417  if (i < max_lin) max_lin = i;
418 
419  for (j = 0; j < TOMSLONSZ; j++) {
420  float_SDSdataQC[l] = 0.0; /* initialize each point */
421 
422  /* pt. is missing, NRT missing, a MIN val, and counted as out of
423  lower range */
424  if ((int_SDSdataRT[l] <= 0) || (int_SDSdataCLMAVG[l] <= 0)) {
425  missing++;
426  if (int_SDSdataRT[l] <= 0) rtmiss++;
427  if (int_SDSdataRT[l] < minval) minval = int_SDSdataRT[l];
428  if (int_SDSdataRT[l] < loval) locnt++;
429  /*
430  * get lo_cnts
431  */
432  for (iv = 0; iv < 5; iv++) {
433  if (int_SDSdataRT[l] < lo_vals[iv]) lo_cnts[iv]++;
434  }
435  } else { /* non-missing point */
436 
437  if ((!strcmp(gridflag, "d")) || (!strcmp(gridflag, "D"))) {
438  float_SDSdataQC[l] =
439  (float32) int_SDSdataRT[l] - int_SDSdataCLMAVG[l];
440  } else {
441  if (int_SDSdataCLMSTD[l] > 0)
442  float_SDSdataQC[l] = (float32)
443  (int_SDSdataRT[l] - int_SDSdataCLMAVG[l]) /
444  int_SDSdataCLMSTD[l];
445  }
446 
447  /* find min and max of all points */
448  if (int_SDSdataRT[l] < minval) minval = int_SDSdataRT[l];
449  if (int_SDSdataRT[l] > maxval) maxval = int_SDSdataRT[l];
450 
451  /* sum up points outside lo/hi range (LO adds to missing counts)*/
452  if (int_SDSdataRT[l] < loval) flocnt += coslat;
453  if (int_SDSdataRT[l] > hival) fhicnt += coslat;
454  /*
455  * get lo_cnts and hi_cnts */
456  for (iv = 0; iv < 5; iv++) {
457  if (int_SDSdataRT[l] < lo_vals[iv]) lo_cnts[iv]++;
458  if (int_SDSdataRT[l] > hi_vals[iv]) hi_cnts[iv]++;
459  }
460 
461  if (float_SDSdataQC[l] < -1.0) neg1cnt++;
462  if (float_SDSdataQC[l] < -2.0) neg2cnt++;
463  if (float_SDSdataQC[l] < -3.0) neg3cnt++;
464 
465  if (float_SDSdataQC[l] > 1.0) pos1cnt++;
466  if (float_SDSdataQC[l] > 2.0) pos2cnt++;
467  if (float_SDSdataQC[l] > 3.0) pos3cnt++;
468  }
469 
470  /* Not in use
471  if ((j > 100) && (j < 150)) {
472  printf("QC [%d][%d]: %f\n", i,j,float_SDSdataQC[l]);
473  printf("RT [%d][%d]: %d\n", i,j,int_SDSdataRT[l]);
474  printf("AVG [%d][%d]: %d\n", i,j,int_SDSdataCLMAVG[l]);
475  printf("STD [%d][%d]: %d\n", i,j,int_SDSdataCLMSTD[l]);
476  }
477  printf("[%d][%d]: %d %d %d\n", i,j,int_SDSdataRT[l],
478  int_SDSdataCLMAVG[l], int_SDSdataCLMSTD[l]);
479  */
480  l++;
481  } /* for j */
482  }
483  else {
484  l += TOMSLONSZ; /* we still have to move along thru the array */
485  }
486  } /* for i */
487 
488  totalpts = pts_used - missing;
489 
490  free(int_SDSdataRT);
491  free(int_SDSdataCLMAVG);
492  free(int_SDSdataCLMSTD);
493 
494  /*
495  * ----------------- Write QC SDS ----------------------------
496  */
497 
498  /*
499  * Create HDF file
500  */
501 
502  if ((startHDF(outfile, &sdfid, &fid, DFACC_CREATE)) != 0)
503  pexit("Fatal error starting HDF file");
504 
505  /*
506  * Create grid structure
507  */
508 
509  /* gridid = setupGrid(fid, VGROUPCLASS, "QC difference data"); */
510  gridid = setupGrid(fid, "QC difference data");
511 
512  /*
513  * Write geometry Vdata, get ref, and add to grid Vgroup (geomid not used)
514  */
515 
516  if ((geomid = writeGeom(fid, gridid, GEOMNAME, BIN_METH, REGISTRATION,
518  MAX_WEST, MAX_EAST)) == ERROR)
519  pexit("Fatal error writing geometry");
520 
521  /*
522  * Write SDS grid
523  */
524 
525  strcpy(datalabel, "QC array");
526  datatype = DFNT_FLOAT32;
527  dataattr = "UNITS";
528  dataunit = "std dev diff";
529 
530  /* datalabel, dataunit, datafmt, */
531  if ((sdsid = wrtsds(sdfid, rank, shape, datatype,
532  datalabel,
533  float_SDSdataQC)) < 0) pexit("main wrtsds");
534 
535  free(float_SDSdataQC);
536 
537  /*
538  * set SDS attribute
539  */
540 
541  if ((result = addAttr(sdsid, dataattr, DFNT_CHAR, dataunit)) != 0)
542  pexit("addAttr");
543 
544  /*
545  * add SDS to Vgroup and deattach SDS
546  */
547 
548  if ((result = setSDSref(sdsid, gridid)) != 0)
549  pexit("setSDSref");
550 
551  /*
552  * deattach HDF grid
553  */
554 
555  deattachHDFgrid(gridid);
556 
557  /*
558  * close HDF structures
559  */
560 
561  if ((result = closeHDFstructs(sdfid, fid)) != 0) pexit("closeHDFstructs");
562 
563  /*
564  * make integer hi and low counts
565  */
566  locnt = (int) flocnt;
567  hicnt = (int) fhicnt;
568  /*
569  * ----------------- Print stats to standard output -----------
570  */
571 
572 
573  if (!strcmp(gridflag, "s")) {
574  printf("\n");
575  printf(
576  "---------------------------------------------------------------\n");
577  printf("Results of comparison of real-time and climatological files:\n");
578  printf("%s\t%s\n", infileRT, infileCLM);
579  printf("Month: %s\tParameter: %s\n", monthstr, "Ozone");
580  printf("Thresholds: %f %f %f Max Missings: %d\n",
581  stdlimit1, stdlimit2, stdlimit3, maxmissing);
582  printf("Lines considered range from %d (lat %f) to %d (lat %f)\n",
583  max_lin, max_lat, min_lin, min_lat);
584 
585  printf("\n");
586  printf("Minimum value: %d Maximum: %d\n", minval, maxval);
587  printf("Total # non-missing values: %6d / considered: %d\n",
588  totalpts, pts_used);
589  printf("Total # values <%d: %d >%d: %d allowed: %d",
590  loval, locnt, hival, hicnt, outmax);
591  if (locnt >= outmax || hicnt >= outmax) {
592  failed = 1;
593  printf(" ***\n\n");
594  } else {
595  printf("\n\n");
596  }
597 
598  /* if (locnt >= outmax) failed = 1; lo points out of range exceeded */
599  /* if (hicnt >= outmax) failed = 1; hi points out of range exceeded */
600 
601  printf("Total # points/percentage < -1 STD: %6d (%5.2f percent)\n",
602  neg1cnt, (float) neg1cnt / totalpts * 100.0);
603  printf("Total # points/percentage +/- 1 STD: %6d (%5.2f percent)",
604  totalpts - (neg1cnt + pos1cnt),
605  (float) (totalpts - (pos1cnt + neg1cnt)) / totalpts * 100.0);
606 
607  if (((float) (totalpts - (pos1cnt + neg1cnt)) / totalpts * 100.0) <
608  stdlimit1) {
609  failed = 1;
610  printf(" ***\n");
611  } else {
612  printf("\n");
613  }
614 
615  printf("Total # points/percentage > 1 STD: %6d (%5.2f percent)\n",
616  pos1cnt, (float) pos1cnt / totalpts * 100.0);
617  printf("\n");
618 
619  printf("Total # points/percentage < -2 STD: %6d (%5.2f percent)\n",
620  neg2cnt, (float) neg2cnt / totalpts * 100.0);
621  printf("Total # points/percentage +/- 2 STD: %6d (%5.2f percent)",
622  totalpts - (neg2cnt + pos2cnt),
623  (float) (totalpts - (pos2cnt + neg2cnt)) / totalpts * 100.0);
624 
625  if (((float) (totalpts - (pos2cnt + neg2cnt)) / totalpts * 100.0) <
626  stdlimit2) {
627  failed = 1;
628  printf(" ***\n");
629  } else {
630  printf("\n");
631  }
632 
633  printf("Total # points/percentage > 2 STD: %6d (%5.2f percent)\n",
634  pos2cnt, (float) pos2cnt / totalpts * 100.0);
635  printf("\n");
636 
637  printf("Total # points/percentage < -3 STD: %6d (%5.2f percent)\n",
638  neg3cnt, (float) neg3cnt / totalpts * 100.0);
639  printf("Total # points/percentage +/- 3 STD: %6d (%5.2f percent)",
640  totalpts - (neg3cnt + pos3cnt),
641  (float) (totalpts - (pos3cnt + neg3cnt)) / totalpts * 100.0);
642 
643  if (((float) (totalpts - (pos3cnt + neg3cnt)) / totalpts * 100.0) <
644  stdlimit3) {
645  failed = 1;
646  printf(" ***\n");
647  } else {
648  printf("\n");
649  }
650 
651  printf("Total # points/percentage > 3 STD: %6d (%5.2f percent)\n",
652  pos3cnt, (float) pos3cnt / totalpts * 100.0);
653  printf("\n");
654 
655  printf("Total # missing values: %6d\n", missing);
656  printf("Total # missing real-time: %6d, max allowed: %6d",
657  rtmiss, maxmissing);
658  if (rtmiss > maxmissing) {
659  failed = 1;
660  printf(" ***\n");
661  } else {
662  printf("\n");
663  }
664  printf(
665  "---------------------------------------------------------------\n");
666  /*
667  * do 2 line terse report of the info for easy extraction
668  */
669  printf("++%6d+%6d+%6d+%6d+%6d+%6d+%6d+%6d+%6d+%6d+\n", lo_cnts[0],
670  lo_cnts[1], lo_cnts[2], lo_cnts[3], lo_cnts[4], hi_cnts[0],
671  hi_cnts[1], hi_cnts[2], hi_cnts[3], hi_cnts[4]);
672  printf("++%5.2f+%5.2f+%5.2f+%6d+%5d+%5d+%5d+%5d+%5d+%5d+%5d+%5d+\n",
673  (float) (totalpts - (pos1cnt + neg1cnt)) / totalpts * 100.0,
674  (float) (totalpts - (pos2cnt + neg2cnt)) / totalpts * 100.0,
675  (float) (totalpts - (pos3cnt + neg3cnt)) / totalpts * 100.0,
676  rtmiss, z_st[0], z_en[0], z_st[1], z_en[1], z_st[2], z_en[2],
677  z_st[3], z_en[3]);
678  printf("++%5.2f+%5.2f+%5.2f+%5.2f+%5.2f+%5.2f+%5d+%5d+%6.2f+%6.2f+\n",
679  (float) neg1cnt / totalpts * 100.0, (float) neg2cnt / totalpts * 100.0,
680  (float) neg3cnt / totalpts * 100.0, (float) pos1cnt / totalpts * 100.0,
681  (float) pos2cnt / totalpts * 100.0, (float) pos3cnt / totalpts * 100.0,
682  max_lin, min_lin, max_lat, min_lat);
683  printf(
684  "---------------------------------------------------------------\n");
685  printf("\n\n");
686 
687  }
688 
689  /* set exit value to reflect threshold checks */
690 
691  if (failed) {
692  printf("Threshold Status: FAILED\n");
693  return (FAILURE);
694  } else {
695  printf("Threshold Status: SUCCESS\n");
696  return (SUCCESS);
697  }
698 
699 } /* main */
700 
701 /*****************************************************************
702  *
703  * check user parameters and show example if not all parms given
704  *
705  *****************************************************************/
706 
707 int8 check_usage(int argc, char *argv[]) {
708  if (argc < 10) {
709  printf("\n\nUsage:\n");
710  printf("\t%s <nrtfile><clmfile><outfile><monthstr>\n", argv[0]);
711  printf("\t <param><t1><t2><t3><maxmiss><loval><hival><outmax>\n");
712  printf("\t <min_lat><max_lat>[diff][type]\n");
713  printf("\nWhere:\n");
714  printf("\tnrtfile: Real-time file to process\n");
715  printf("\tclmfile: Climatology file\n");
716  printf("\toutfile: output QC file\n");
717  printf("\tmonthstr: Month in string form (i.e., January)\n");
718  printf("\t (only used for examining climatology file,\n\t otherwise derived from the input file name\n");
719  printf("\tparam: Parameter to run: OZONE ...only\n");
720  printf(
721  "\tt1: Threshold percent of pts w/in 1 STD DEV of climatology\n");
722  printf(
723  "\tt2: Threshold percent of pts w/in 2 STD DEV of climatology\n");
724  printf(
725  "\tt3: Threshold percent of pts w/in 3 STD DEV of climatology\n");
726  printf("\tmaxmiss: Max num of missing NRT points permitted.\n");
727  printf("\tloval: lowest acceptable value in NRT file\n");
728  printf("\thival: highest acceptable value in NRT file\n");
729  printf("\toutmax: # of points, weighted by cos( latitude )\n");
730  printf("\t that can be outside lo/hival before error set\n");
731  printf("\tmin_lat: minimum latitude to consider (default -90.).\n");
732  printf("\tmax_lat: maximum latitude to consider (default 90.).\n");
733  printf("\t NOTE that if min_lat = 95, the limits will be\n");
734  printf("\t determined using the julian day in the equation:\n");
735  printf("\t min_lat = -90. + zen + max_lat\n");
736  printf("\t max_lat = 90. - zen - max_lat\n");
737  printf("\t where max_lat = limit adjustment, default, 10.\n");
738  printf("\t and zen = -23. * cos( ( jday + 10 ) * 360 / 365 )\n");
739  printf("\t ** [optional] parameters follow. Preceeding args \n");
740  printf(
741  "\t are required for subsequently ones used (fill spaces).\n");
742  printf(
743  "\tdiff: [optional] Enter 'd' to see a simple difference output\n");
744  printf("\t grid rather than the default STD variance 's'.\n");
745  printf("\t Difference calculations do not product reports.\n");
746  printf(
747  "\ttype [optional] Enter 1 if NRT file is actually a CLM file.\n");
748  printf("\t This will allow the program to read the CLM\n");
749  printf("\t as of test of CLM to itself.\n");
750  printf("\n");
751  printf("Example: \n\n");
752 
753  printf("\t o3qc $SDSDEMO/S199407100_TOVS.OZONE.hdf \n");
754  printf("\t $SDSDATA/S19891991_TOMS.OZONE.hdf output.hdf \n");
755  printf("\t March OZONE 25 50 75 50\n\n");
756  return (ERROR);
757  }
758  return 0;
759 }
int32_t setupGrid(int32_t fid, char *grpname)
Definition: ANCroutines.c:51
integer, parameter int16
Definition: cubeio.f90:3
#define MAX_WEST
Definition: o3qc.c:127
#define SUCCESS
Definition: ObpgReadGrid.h:15
int j
Definition: decode_rs.h:73
char * lowcase(char *instr)
Definition: lowcase.c:10
int addAttr(int32_t sdsid, char *dataattr, int32_t datatype, char *dataunit)
Definition: ANCroutines.c:222
#define NULL
Definition: decode_rs.h:63
const double pi
float * lat
int32_t jday(int16_t i, int16_t j, int16_t k)
Definition: jday.c:4
#define REGISTRATION
Definition: o3qc.c:122
int anc_daymon(char *fname, int *jday, char *monstr)
Definition: anc_daymon.c:3
#define MAX_EAST
Definition: o3qc.c:128
#define MAX_NORTH
Definition: o3qc.c:125
#define TOMSLONSZ
Definition: o3qc.c:130
int main(int argc, char *argv[])
Definition: o3qc.c:133
#define TOMSLATSZ
Definition: o3qc.c:129
#define BIN_METH
Definition: o3qc.c:121
#define CLMfile
Definition: o3qc.c:131
int32_t wrtsds(int32_t sdfid, int rank, int32_t *shape, int32_t datatype, char *datalabel, void *data)
int deattachHDFgrid(int32_t gridid)
Definition: ANCroutines.c:267
#define VSIZE
Definition: o3qc.c:123
int closeHDFstructs(int32_t sdfid, int32_t fid)
Definition: ANCroutines.c:281
void pexit(char *string)
Definition: pexit.c:10
int32_t writeGeom(int32_t fid, int32_t gridid, char *geomname, int32_t bin_meth, int32_t registration, float vsize, float hsize, float max_north, float max_south, float max_west, float max_east)
Definition: ANCroutines.c:92
#define FAILURE
Definition: ancil.h:25
Extra metadata that will be written to the HDF4 file l2prod rank
#define HSIZE
Definition: o3qc.c:124
PARAM_TYPE_NONE Default value No parameter is buried in the product name name_prefix is case insensitive string compared to the product name PARAM_TYPE_VIS_WAVE The visible wavelength bands from the sensor are buried in the product name The product name is compared by appending and name_suffix ie aph_412_giop where prod_ix will be set to PARAM_TYPE_IR_WAVE same search method as PARAM_TYPE_VIS_WAVE except only wavelength above are looped through but prod_ix is still based ie aph_2_giop for the second and prod_ix set to PARAM_TYPE_INT name_prefix is compared with the beginning of the product name If name_suffix is not empty the it must match the end of the product name The characters right after the prefix are read as an integer and prod_ix is set to that number strncpy(l2prod->name_prefix, "myprod", UNITLEN)
double min_lat
Definition: GEO_DEM.c:63
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_FLOAT32
int setSDSref(int32_t sdsid, int32_t gridid)
Definition: ANCroutines.c:245
#define MAXNAMELNG
Definition: ancil.h:43
int i
Definition: decode_rs.h:71
#define GEOMNAME
Definition: ancil.h:44
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
int rdsds(char *filename, char *vgname, char *sdsname, int32_t *dimsizes, void *inData)
#define MAX_SOUTH
Definition: o3qc.c:126
int startHDF(char *outfile, int32_t *sdfid, int32_t *fid, int32_t mode)
Definition: ANCroutines.c:27
#define ERROR
Definition: ancil.h:24
int8 check_usage(int argc, char *argv[])
Definition: o3qc.c:707