Due to the lapse in federal government funding, NASA is not updating this website. We sincerely regret this inconvenience.
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
int32_t jday(int16_t i, int16_t j, int16_t k)
Converts a calendar date to the corresponding Julian day starting at noon on the calendar date....
Definition: jday.c:14
#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