Line data Source code
1 : /*****************************************************************************
2 : * metaprint.c
3 : *
4 : * DESCRIPTION
5 : * This file contains the code necessary to write out the meta data
6 : * structure.
7 : *
8 : * HISTORY
9 : * 9/2002 Arthur Taylor (MDL / RSIS): Created.
10 : *
11 : * NOTES
12 : * 1) Need to add support for GS3_ORTHOGRAPHIC = 90,
13 : * GS3_EQUATOR_EQUIDIST = 110, GS3_AZIMUTH_RANGE = 120
14 : * 2) Need to add support for GS4_RADAR = 20, GS4_SATELLITE = 30
15 : *****************************************************************************
16 : */
17 : #include <stdio.h>
18 : #include <stdlib.h>
19 : #include <stdarg.h>
20 : #include <math.h>
21 : #ifndef DONT_DEPRECATE_SPRINTF
22 : #define DONT_DEPRECATE_SPRINTF
23 : #endif
24 : #include "cpl_port.h"
25 : #include "meta.h"
26 : #include "metaname.h"
27 : #include "myerror.h"
28 : #include "myutil.h"
29 : #if 0
30 : /* tdlpack is no longer supported by GDAL */
31 : #include "tdlpack.h"
32 : #endif
33 : #include "myassert.h"
34 : #include "clock.h"
35 :
36 : /*****************************************************************************
37 : * Lookup() --
38 : *
39 : * Arthur Taylor / MDL
40 : *
41 : * PURPOSE
42 : * To lookup the string value in a table, given the table, the index, and
43 : * some default values.
44 : *
45 : * ARGUMENTS
46 : * table = The table to look in. (Input)
47 : * n = Size of table. (Input)
48 : * index = Index to look up. (Input)
49 : *
50 : * FILES/DATABASES: None
51 : *
52 : * RETURNS: char *
53 : * The desired index value, or the appropriate default message.
54 : *
55 : * HISTORY
56 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
57 : *
58 : * NOTES
59 : * Can not do a sizeof(table) here because table is now of arbitrary length.
60 : * Instead do sizeof(table) in calling procedure.
61 : *****************************************************************************
62 : */
63 : #if 0 // Unused with GDAL.
64 : static const char *Lookup(const char * const *table, size_t n, size_t index)
65 : {
66 : static const char * const def[] =
67 : { "Reserved", "Reserved for local use", "Missing" };
68 : if (index < (n / sizeof (char *))) {
69 : return table[index];
70 : } else if (index < 192) {
71 : return def[0];
72 : } else if (index < 255) {
73 : return def[1];
74 : } else {
75 : return def[2];
76 : }
77 : }
78 : #endif
79 :
80 : /*****************************************************************************
81 : * Print() --
82 : *
83 : * Arthur Taylor / MDL
84 : *
85 : * PURPOSE
86 : * To print the message to a local static array in a way similar to
87 : * myerror.c::errSprintf. This allows us to pass the results back to Tcl/Tk,
88 : * as well as to save it to disk. It also serves as a central place to
89 : * change if we want a different style of output.
90 : *
91 : * The caller gives a series of calls with fmt != NULL, followed by
92 : * a fmt == NULL. This last call will return the constructed message to the
93 : * caller, and reset the message to NULL. It is caller's responsibility to
94 : * free the message, and to make sure that last call to Print has fmt = NULL,
95 : * so that the routine doesn't accidentally keep memory.
96 : *
97 : * ARGUMENTS
98 : * label = A label for this set of data. (Input)
99 : * varName = A char string describing the variable.. (Input)
100 : * fmt = Prt_NULL, Prt_D, Prt_DS, Prt_DSS, Prt_S, Prt_F, Prt_FS, Prt_E,
101 : * Prt_ES. (Input)
102 : * determines what to expect in the rest of the arguments.
103 : * d = sInt4, s = char *, f = double,
104 : * NULL = return the constructed answer, and reset answer to NULL.
105 : *
106 : * FILES/DATABASES: None
107 : *
108 : * RETURNS: char *
109 : * NULL if (fmt != NULL) (i.e. we added to message)
110 : * message if (fmt == NULL) (i.e. return the message).
111 : * It is caller's responsibility to free the message, and to make sure
112 : * that last call to Print has fmt = NULL.
113 : *
114 : * HISTORY
115 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
116 : * 4/2003 AAT: Changed so it could print different types of labels
117 : * "GDS" instead of "S3"
118 : * 10/2004 AAT: Added Prt_SS
119 : *
120 : * NOTES
121 : * Using enumerated type instead of "ds" "dss" etc. For speed considerations.
122 : *****************************************************************************
123 : */
124 0 : char *Print(const char *label, const char *varName, int fmt, ...)
125 : {
126 : static char *buffer = nullptr; /* Copy of message generated so far. */
127 : va_list ap; /* pointer to variable argument list. */
128 : sInt4 lival; /* Store a sInt4 val from argument list. */
129 : char *sval; /* Store a string val from argument. */
130 : char *unit; /* Second string val is usually a unit string. */
131 : double dval; /* Store a double val from argument list. */
132 : char *ans; /* Final message to return if fmt = Prt_NULL. */
133 :
134 0 : if (fmt == Prt_NULL) {
135 0 : ans = buffer;
136 0 : buffer = nullptr;
137 0 : return ans;
138 : }
139 0 : va_start (ap, fmt); /* make ap point to 1st unnamed arg. */
140 0 : switch (fmt) {
141 0 : case Prt_D:
142 0 : lival = va_arg (ap, sInt4);
143 0 : reallocSprintf (&buffer, "%s | %s | %ld\n", label, varName, lival);
144 0 : break;
145 0 : case Prt_DS:
146 0 : lival = va_arg (ap, sInt4);
147 0 : sval = va_arg (ap, char *);
148 0 : reallocSprintf (&buffer, "%s | %s | %ld (%s)\n", label, varName,
149 : lival, sval);
150 0 : break;
151 0 : case Prt_DSS:
152 0 : lival = va_arg (ap, sInt4);
153 0 : sval = va_arg (ap, char *);
154 0 : unit = va_arg (ap, char *);
155 0 : reallocSprintf (&buffer, "%s | %s | %ld (%s [%s])\n", label,
156 : varName, lival, sval, unit);
157 0 : break;
158 0 : case Prt_S:
159 0 : sval = va_arg (ap, char *);
160 0 : reallocSprintf (&buffer, "%s | %s | %s\n", label, varName, sval);
161 0 : break;
162 0 : case Prt_SS:
163 0 : sval = va_arg (ap, char *);
164 0 : unit = va_arg (ap, char *);
165 0 : reallocSprintf (&buffer, "%s | %s | %s (%s)\n", label, varName,
166 : sval, unit);
167 0 : break;
168 0 : case Prt_F:
169 0 : dval = va_arg (ap, double);
170 0 : reallocSprintf (&buffer, "%s | %s | %f\n", label, varName, dval);
171 0 : break;
172 0 : case Prt_E:
173 0 : dval = va_arg (ap, double);
174 0 : reallocSprintf (&buffer, "%s | %s | %e\n", label, varName, dval);
175 0 : break;
176 0 : case Prt_G:
177 0 : dval = va_arg (ap, double);
178 0 : reallocSprintf (&buffer, "%s | %s | %g\n", label, varName, dval);
179 0 : break;
180 0 : case Prt_FS:
181 0 : dval = va_arg (ap, double);
182 0 : unit = va_arg (ap, char *);
183 0 : reallocSprintf (&buffer, "%s | %s | %f (%s)\n", label, varName,
184 : dval, unit);
185 0 : break;
186 0 : case Prt_ES:
187 0 : dval = va_arg (ap, double);
188 0 : unit = va_arg (ap, char *);
189 0 : reallocSprintf (&buffer, "%s | %s | %e (%s)\n", label, varName,
190 : dval, unit);
191 0 : break;
192 0 : case Prt_GS:
193 0 : dval = va_arg (ap, double);
194 0 : unit = va_arg (ap, char *);
195 0 : reallocSprintf (&buffer, "%s | %s | %g (%s)\n", label, varName,
196 : dval, unit);
197 0 : break;
198 0 : default:
199 0 : reallocSprintf (&buffer, "ERROR: Invalid Print option '%d'\n", fmt);
200 : }
201 0 : va_end (ap); /* clean up when done. */
202 0 : return nullptr;
203 : }
204 :
205 : #if 0 // Unused with GDAL.
206 : /*****************************************************************************
207 : * PrintSect1() --
208 : *
209 : * Arthur Taylor / MDL
210 : *
211 : * PURPOSE
212 : * To generate the message for GRIB2 section 1.
213 : *
214 : * ARGUMENTS
215 : * pds2 = The GRIB2 Product Definition Section to print. (Input)
216 : * center = The Center that created the data (Input)
217 : * subcenter = The Sub Center that created the data (Input)
218 : *
219 : * FILES/DATABASES: None
220 : *
221 : * RETURNS: void
222 : *
223 : * HISTORY
224 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
225 : * 4/2003 AAT: Changed to accept pointer to pdsG2Type pds2
226 : * 10/2005 AAT: Adjusted to take center, subcenter as we moved that out of
227 : * the pdsG2 type.
228 : *
229 : * NOTES
230 : *****************************************************************************
231 : */
232 : static void PrintSect1 (pdsG2Type * pds2, unsigned short int center,
233 : unsigned short int subcenter)
234 : {
235 : /* Based on Grib2 Code Table 1.2 */
236 : static const char * const table12[] = { "Analysis", "Start of Forecast",
237 : "Verifying time of forecast", "Observation time"
238 : };
239 :
240 : /* Based on Grib2 Code Table 1.3 */
241 : static const char * const table13[] = { "Operational products",
242 : "Operational test products", "Research products",
243 : "Re-analysis products"
244 : };
245 :
246 : /* Based on Grib2 Code Table 1.4 */
247 : static const char * const table14[] = { "Analysis products",
248 : "Forecast products", "Analysis and forecast products",
249 : "Control forecast products", "Perturbed forecast products",
250 : "Control and perturbed forecast products",
251 : "Processed satellite observations", "Processed radar observations"
252 : };
253 :
254 : char buffer[25]; /* Stores format of pds2->refTime. */
255 : const char *ptr;
256 :
257 : ptr = centerLookup (center);
258 : if (ptr != NULL) {
259 : Print ("PDS-S1", "Originating center", Prt_DS, center, ptr);
260 : } else {
261 : Print ("PDS-S1", "Originating center", Prt_D, center);
262 : }
263 : if (subcenter != GRIB2MISSING_u2) {
264 : ptr = subCenterLookup (center, subcenter);
265 : if (ptr != NULL) {
266 : Print ("PDS-S1", "Originating sub-center", Prt_DS, subcenter, ptr);
267 : } else {
268 : Print ("PDS-S1", "Originating sub-center", Prt_D, subcenter);
269 : }
270 : }
271 : Print ("PDS-S1", "GRIB Master Tables Version", Prt_D, pds2->mstrVersion);
272 : Print ("PDS-S1", "GRIB Local Tables Version", Prt_D, pds2->lclVersion);
273 : Print ("PDS-S1", "Significance of reference time", Prt_DS, pds2->sigTime,
274 : Lookup (table12, sizeof (table12), pds2->sigTime));
275 :
276 : /* strftime (buffer, 25, "%m/%d/%Y %H:%M:%S UTC", gmtime (&(pds2->refTime)));*/
277 : Clock_Print (buffer, 25, pds2->refTime, "%m/%d/%Y %H:%M:%S UTC", 0);
278 :
279 : Print ("PDS-S1", "Reference Time", Prt_S, buffer);
280 : Print ("PDS-S1", "Operational Status", Prt_DS, pds2->operStatus,
281 : Lookup (table13, sizeof (table13), pds2->operStatus));
282 : Print ("PDS-S1", "Type of Data", Prt_DS, pds2->dataType,
283 : Lookup (table14, sizeof (table14), pds2->dataType));
284 : }
285 :
286 : /*****************************************************************************
287 : * PrintSect2() --
288 : *
289 : * Arthur Taylor / MDL
290 : *
291 : * PURPOSE
292 : * To generate a message for the section 2 data. This may be more
293 : * appropriate in its own file (particularly the weather table.)
294 : *
295 : * ARGUMENTS
296 : * sect2 = The sect2 structure to print (initialized by ParseSect2). (Input)
297 : *
298 : * FILES/DATABASES: None
299 : *
300 : * RETURNS: void
301 : *
302 : * HISTORY
303 : * 2/2003 Arthur Taylor (MDL/RSIS): Created.
304 : *
305 : * NOTES
306 : *****************************************************************************
307 : */
308 : static void PrintSect2 (sect2_type * sect2)
309 : {
310 : size_t i; /* loop counter over number of sect2 data. */
311 : char buffer[25]; /* Assists with labeling. */
312 :
313 : switch (sect2->ptrType) {
314 : case GS2_WXTYPE:
315 : Print ("PDS-S2", "Number of Elements in Section 2", Prt_D,
316 : sect2->wx.dataLen);
317 : for (i = 0; i < sect2->wx.dataLen; i++) {
318 : if (sect2->wx.ugly[i].validIndex != -1) {
319 : sprintf (buffer, "Elem %3d Is Used", (int) i);
320 : } else {
321 : sprintf (buffer, "Elem %3d NOT Used", (int) i);
322 : }
323 : Print ("PDS-S2", buffer, Prt_S, sect2->wx.data[i]);
324 : }
325 : break;
326 : case GS2_UNKNOWN:
327 : Print ("PDS-S2", "Number of Elements in Section 2", Prt_D,
328 : sect2->unknown.dataLen);
329 : for (i = 0; i < sect2->unknown.dataLen; i++) {
330 : sprintf (buffer, "Element %d", (int) i);
331 : Print ("PDS-S2", buffer, Prt_F, sect2->unknown.data[i]);
332 : }
333 : break;
334 : default:
335 : return;
336 : }
337 : }
338 :
339 : /*****************************************************************************
340 : * PrintSect4_Category() --
341 : *
342 : * Arthur Taylor / MDL
343 : *
344 : * PURPOSE
345 : * To generate the category message for section 4.
346 : *
347 : * ARGUMENTS
348 : * meta = The meta file structure to generate the message for. (Input)
349 : *
350 : * FILES/DATABASES: None
351 : *
352 : * RETURNS: void
353 : *
354 : * HISTORY
355 : * 6/2003 Arthur Taylor (MDL/RSIS): Extracted this part from PrintSect4().
356 : * 1/2004 AAT: Combined PrintSect4_Meteo and PrintSect4_Ocean into this.
357 : * 5/2004 AAT: Found out that I skipped "Momentum Probabilities" in tbl41_0.
358 : *
359 : * NOTES
360 : *****************************************************************************
361 : */
362 : static void PrintSect4_Category_OAR (uChar cat) {
363 : if (cat == 2) {
364 : Print ("PDS-S4", "Category Description", Prt_DS, cat, "Lightning Products");
365 : } else if (cat == 3) {
366 : Print ("PDS-S4", "Category Description", Prt_DS, cat, "Severe Weather Products");
367 : } else if (cat == 4) {
368 : Print ("PDS-S4", "Category Description", Prt_DS, cat, "Satellite Products");
369 : } else if (cat == 5) {
370 : Print ("PDS-S4", "Category Description", Prt_DS, cat, "Forecast Products");
371 : } else if (cat == 6) {
372 : Print ("PDS-S4", "Category Description", Prt_DS, cat, "Precipitation Products");
373 : } else if (cat == 7) {
374 : Print ("PDS-S4", "Category Description", Prt_DS, cat, "Model-based Products");
375 : } else if (cat == 8) {
376 : Print ("PDS-S4", "Category Description", Prt_DS, cat, "Intermediate Products");
377 : } else if (cat == 9) {
378 : Print ("PDS-S4", "Category Description", Prt_DS, cat, "3D Reflectivity Mosaics");
379 : } else if (cat == 10) {
380 : Print ("PDS-S4", "Category Description", Prt_DS, cat, "Composite Reflectivity Mosaics");
381 : } else if (cat == 11) {
382 : Print ("PDS-S4", "Category Description", Prt_DS, cat, "Other Reflectivity Mosaics");
383 : } else {
384 : Print ("PDS-S4", "Category Description", Prt_DS, cat, "unknown");
385 : }
386 : }
387 :
388 : static void PrintSect4_Category (grib_MetaData *meta)
389 : {
390 : sect4_type *sect4 = &(meta->pds2.sect4);
391 :
392 : /* Based on Grib2 Code Table 4.1 discipline 0 */
393 : static const char * const tbl41_0[] = {
394 : "Temperature", "Moisture", "Momentum", "Mass", "Short-wave Radiation",
395 : "Long-wave Radiation", "Cloud", "Thermodynamic Stability indices",
396 : "Kinematic Stability indices", "Temperature Probabilities",
397 : "Moisture Probabilities", "Momentum Probabilities",
398 : "Mass Probabilities", "Aerosols", "Trace gases (e.g. ozone, C02)",
399 : "Radar", "Forecast Radar Imagery", "Electro-dynamics",
400 : "Nuclear/radiology", "Physical atmospheric properties",
401 : "Atmospheric chemical Constituents",
402 : };
403 : /* Based on Grib2 Code Table 4.1 discipline 1 */
404 : static const char * const tbl41_1[] = {
405 : "Hydrology basic products", "Hydrology probabilities"
406 : };
407 : /* Based on Grib2 Code Table 4.1 discipline 2 */
408 : static const char * const tbl41_2[] = {
409 : "Vegetation/Biomass", "Agri-/aquacultural Special Products",
410 : "Transportation-related Products", "Soil Products"
411 : };
412 : /* Based on Grib2 Code Table 4.1 discipline 3 */
413 : static const char * const tbl41_3[] = {
414 : "Image format products", "Quantitative products"
415 : };
416 : /* Based on Grib2 Code Table 4.1 discipline 10 */
417 : static const char * const tbl41_10[] = {
418 : "Waves", "Currents", "Ice", "Surface Properties",
419 : "Sub-surface Properties"
420 : };
421 :
422 : if (meta->pds2.mstrVersion == 255) {
423 : if (meta->center == 161) {
424 : PrintSect4_Category_OAR(sect4->cat);
425 : } else {
426 : Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat, "unknown");
427 : }
428 : return;
429 : }
430 : switch (meta->pds2.prodType) {
431 : case 0: /* Meteo category. */
432 : switch (sect4->cat) {
433 : case 190:
434 : Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
435 : "CCITT IA5 string");
436 : break;
437 : case 191:
438 : Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
439 : "Miscellaneous");
440 : break;
441 : case 192:
442 : Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
443 : "Covariance");
444 : break;
445 : default:
446 : Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
447 : Lookup (tbl41_0, sizeof (tbl41_0), sect4->cat));
448 : }
449 : break;
450 : case 1: /* Hydrological */
451 : Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
452 : Lookup (tbl41_1, sizeof (tbl41_1), sect4->cat));
453 : break;
454 : case 2: /* Land surface */
455 : Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
456 : Lookup (tbl41_2, sizeof (tbl41_2), sect4->cat));
457 : break;
458 : case 3: /* Space */
459 : switch (sect4->cat) {
460 : case 192:
461 : Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
462 : "Forecast Satellite Imagery");
463 : break;
464 : default:
465 : Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
466 : Lookup (tbl41_3, sizeof (tbl41_3), sect4->cat));
467 : }
468 : break;
469 : case 10: /* Oceanographic */
470 : switch (sect4->cat) {
471 : case 191:
472 : Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
473 : "Miscellaneous");
474 : break;
475 : default:
476 : Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
477 : Lookup (tbl41_10, sizeof (tbl41_10), sect4->cat));
478 : }
479 : break;
480 : default:
481 : Print ("PDS-S4", "PrintSect4() does not handle this prodType",
482 : Prt_D, meta->pds2.prodType);
483 : }
484 : }
485 :
486 : /*****************************************************************************
487 : * PrintSect4() --
488 : *
489 : * Arthur Taylor / MDL
490 : *
491 : * PURPOSE
492 : * To generate the message for section 4.
493 : *
494 : * ARGUMENTS
495 : * meta = The meta file structure to generate the message for. (Input)
496 : * f_unit = 0 (GRIB unit), 1 (english), 2 (metric) (Input)
497 : *
498 : * FILES/DATABASES: None
499 : *
500 : * RETURNS: int (could use errSprintf())
501 : * 0 if no error.
502 : * -2 if asked to print data for a template that we don't support.
503 : *
504 : * HISTORY
505 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
506 : * 2/2003 AAT: Adjusted the interpretation of the scale vector and value.
507 : * to be consistent with what Matt found from email conversations
508 : * with WMO GRIB2 experts.
509 : * 2/2003 AAT: Switched from: value / pow (10, factor)
510 : * to: value * pow (10, -1 * factor)
511 : * 6/2003 AAT: Extracted the prodType = 0 only info and put in _Meteo
512 : * 6/2003 AAT: Created a PrintSect4_Ocean for ocean stuff.
513 : * 1/2004 AAT: Updated table 4.7
514 : * 1/2004 AAT: Modified to use "comment" from metaname.c instead of
515 : * PrintSect4_Meteo, and PrintSect4_Ocean (that way local tables are
516 : * enabled.) (Fixed meta file for PoP12).
517 : * 3/2004 AAT: Added emphasis on "computation" of unit conversion.
518 : * 3/2005 AAT: Added support for GS4_PROBABIL_PNT
519 : *
520 : * NOTES
521 : * Need to add support for GS4_RADAR = 20
522 : *****************************************************************************
523 : */
524 : static int PrintSect4 (grib_MetaData *meta, sChar f_unit)
525 : {
526 : sect4_type *sect4 = &(meta->pds2.sect4);
527 : /* Based on Grib2 Code Table 4.0 */
528 : static const char * const tbl40[] = {
529 : "Analysis at a horizontal layer at a point in time",
530 : "Individual ensemble forecast at a horizontal layer at a point in time",
531 : "Derived forecast based on ensemble members at a horizontal layer at a"
532 : " point in time",
533 : "Probability forecast at a horizontal layer or level at a point in "
534 : "time",
535 : "Percentile forecasts at a horizontal layer or level at a point in "
536 : "time",
537 : "Statistically processed data at a horizontal layer or level in a time"
538 : " interval",
539 : "Probability forecast at a horizontal layer or level in a time "
540 : "interval",
541 : "Percentile forecasts at a horizontal layer or level in a time "
542 : "interval",
543 : "Individual ensemble forecast at a horizontal layer or level in a time"
544 : " interval",
545 : "Derived forecasts based in all ensemble members at a horizontal level "
546 : "or layer in a time interval",
547 : "Radar product", "Satellite product"
548 : };
549 :
550 : /* Based on Grib2 Code Table 4.3 */
551 : static const char * const tbl43[] = {
552 : "Analysis", "Initialization", "Forecast", "Bias corrected forecast",
553 : "Ensemble forecast", "Probability forecast", "Forecast error",
554 : "Analysis error", "Observation"
555 : };
556 :
557 : /* Based on Grib2 Code Table 4.4 */
558 : static const char * const tbl44[] = {
559 : "Minute", "Hour", "Day", "Month", "Year", "Decade",
560 : "Normal (30 years)", "Century", "Reserved", "Reserved",
561 : "3 hours", "6 hours", "12 hours", "Second"
562 : };
563 :
564 : /* Based on Grib2 Code Table 4.5 */
565 : /* See "metaname.c :: Surface[]" */
566 :
567 : /* Based on Grib2 Code Table 4.6 */
568 : static const char * const tbl46[] = {
569 : "Unperturbed high-resolution control forecast",
570 : "Unperturbed low-resolution control forecast",
571 : "Negatively perturbed forecast", "Positively perturbed forecast"
572 : };
573 :
574 : /* Based on Grib2 Code Table 4.7 */
575 : static const char * const tbl47[] = {
576 : "Unweighted mean of all members", "Weighted mean of all members",
577 : "Standard deviation with respect to cluster mean",
578 : "Standard deviation with respect to cluster mean, normalized",
579 : "Spread of all members",
580 : "Large anomaly index of all members",
581 : "Unweighted mean of the cluster members"
582 : };
583 :
584 : /* Based on Grib2 Code Table 4.9 */
585 : static const char * const tbl49[] = {
586 : "Probability of event below lower limit",
587 : "Probability of event above upper limit",
588 : "Probability of event between limits (include lower, exclude upper)",
589 : "Probability of event above lower limit",
590 : "Probability of event below upper limit"
591 : };
592 :
593 : /* Based on Grib2 Code Table 4.10 */
594 : static const char * const tbl410[] = {
595 : "Average", "Accumulation", "Maximum", "Minimum",
596 : "Difference (Value at end of time minus beginning)",
597 : "Root mean square", "Standard deviation",
598 : "Covariance (Temporal variance)",
599 : "Difference (Value at beginning of time minus end)", "Ratio",
600 : "Standardized Anomaly", "Summation", "Confidence Index",
601 : "Quality Indicator"
602 : };
603 :
604 : /* Based on Grib2 Code Table 4.11 */
605 : static const char * const tbl411[] = {
606 : "Reserved",
607 : "Successive times; same forecast time, start time incremented",
608 : "Successive times; same start time, forecast time incremented",
609 : "Successive times; start time incremented, forecast time decremented, "
610 : "valid time constant",
611 : "Successive times; start time decremented, forecast time incremented, "
612 : "valid time constant",
613 : "Floating subinterval of time between forecast time, and end"
614 : };
615 :
616 : char buffer[50]; /* Temp storage for various uses including time
617 : * format. */
618 : int i; /* counter for templat 4.8/4.9 for num time range
619 : * specs. */
620 : int f_reserved; /* Whether Table4.5 is a reserved entry or not. */
621 : GRIB2SurfTable surf; /* Surface look up in Table4.5. */
622 : const char *ptr;
623 :
624 : switch (sect4->templat) {
625 : case GS4_ANALYSIS:
626 : case GS4_ERROR:
627 : case GS4_ENSEMBLE:
628 : case GS4_DERIVED:
629 : Print ("PDS-S4", "Product type", Prt_DS, sect4->templat,
630 : tbl40[sect4->templat]);
631 : break;
632 : case GS4_PROBABIL_PNT:
633 : Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[3]);
634 : break;
635 : case GS4_PERCENT_PNT:
636 : Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[4]);
637 : break;
638 : case GS4_STATISTIC:
639 : Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[5]);
640 : break;
641 : case GS4_PROBABIL_TIME:
642 : Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[6]);
643 : break;
644 : case GS4_PERCENT_TIME:
645 : Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[7]);
646 : break;
647 : case GS4_ENSEMBLE_STAT:
648 : Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[8]);
649 : break;
650 : case GS4_DERIVED_INTERVAL:
651 : Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[9]);
652 : break;
653 : /*
654 : * The following lines were removed until such time that the rest of this
655 : * procedure can properly handle this template type.
656 : *
657 : case GS4_RADAR:
658 : Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[10]);
659 : break;
660 : */
661 : case GS4_SATELLITE:
662 : Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[11]);
663 : break;
664 : default:
665 : Print ("PDS-S4", "Product type", Prt_D, sect4->templat);
666 : errSprintf ("Un-supported Sect4 template %ld\n", sect4->templat);
667 : return -2;
668 : }
669 :
670 : PrintSect4_Category (meta);
671 : Print ("PDS-S4", "Category Sub-Description", Prt_DS, sect4->subcat,
672 : meta->comment);
673 :
674 : if (f_unit == 1) {
675 : Print ("PDS-S4", "Output grid, (COMPUTED) english unit is", Prt_S,
676 : meta->unitName);
677 : } else if (f_unit == 2) {
678 : Print ("PDS-S4", "Output grid, (COMPUTED) metric unit is", Prt_S,
679 : meta->unitName);
680 : }
681 : Print ("PDS-S4", "Generation process", Prt_DS, sect4->genProcess,
682 : Lookup (tbl43, sizeof (tbl43), sect4->genProcess));
683 : if (sect4->templat == GS4_SATELLITE) {
684 : Print ("PDS-S4", "Observation generating process", Prt_D, sect4->genID);
685 : Print ("PDS-S4", "Number of contributing spectral bands", Prt_D,
686 : sect4->numBands);
687 : for (i = 0; i < sect4->numBands; i++) {
688 : Print ("PDS-S4", "Satellite series", Prt_D, sect4->bands[i].series);
689 : Print ("PDS-S4", "Satellite numbers", Prt_D,
690 : sect4->bands[i].numbers);
691 : Print ("PDS-S4", "Instrument type", Prt_D, sect4->bands[i].instType);
692 : Print ("PDS-S4", "Scale Factor of central wave number", Prt_D,
693 : sect4->bands[i].centWaveNum.factor);
694 : Print ("PDS-S4", "Scale Value of central wave number", Prt_D,
695 : sect4->bands[i].centWaveNum.value);
696 : }
697 : return 0;
698 : }
699 : if (sect4->bgGenID != GRIB2MISSING_u1) {
700 : ptr = processLookup (meta->center, sect4->bgGenID);
701 : if (ptr != NULL) {
702 : Print ("PDS-S4", "Background generating process ID", Prt_DS,
703 : sect4->bgGenID, ptr);
704 : } else {
705 : Print ("PDS-S4", "Background generating process ID", Prt_D,
706 : sect4->bgGenID);
707 : }
708 : }
709 : if (sect4->genID != GRIB2MISSING_u1) {
710 : ptr = processLookup (meta->center, sect4->genID);
711 : if (ptr != NULL) {
712 : Print ("PDS-S4", "Forecast generating process ID", Prt_DS,
713 : sect4->genID, ptr);
714 : } else {
715 : Print ("PDS-S4", "Forecast generating process ID", Prt_D,
716 : sect4->genID);
717 : }
718 : }
719 : if (sect4->f_validCutOff) {
720 : Print ("PDS-S4", "Data cut off after reference time in seconds", Prt_D,
721 : sect4->cutOff);
722 : }
723 : Print ("PDS-S4", "Forecast time in hours", Prt_F,
724 : (double) (sect4->foreSec / 3600.));
725 : surf = Table45Index (sect4->fstSurfType, &f_reserved, meta->center,
726 : meta->subcenter);
727 : Print ("PDS-S4", "Type of first fixed surface", Prt_DSS,
728 : sect4->fstSurfType, surf.comment, surf.unit);
729 : Print ("PDS-S4", "Value of first fixed surface", Prt_F,
730 : sect4->fstSurfValue);
731 : if (sect4->sndSurfType != GRIB2MISSING_u1) {
732 : surf = Table45Index (sect4->sndSurfType, &f_reserved, meta->center,
733 : meta->subcenter);
734 : Print ("PDS-S4", "Type of second fixed surface", Prt_DSS,
735 : sect4->sndSurfType, surf.comment, surf.unit);
736 : Print ("PDS-S4", "Value of second fixed surface", Prt_F,
737 : sect4->sndSurfValue);
738 : }
739 : switch (sect4->templat) {
740 : case GS4_ANALYSIS:
741 : case GS4_ERROR:
742 : break;
743 : case GS4_ENSEMBLE:
744 : Print ("PDS-S4", "Type of Ensemble forecast", Prt_DS,
745 : sect4->typeEnsemble,
746 : Lookup (tbl46, sizeof (tbl46), sect4->typeEnsemble));
747 : Print ("PDS-S4", "Perturbation number", Prt_D, sect4->perturbNum);
748 : Print ("PDS-S4", "Number of forecasts in ensemble", Prt_D,
749 : sect4->numberFcsts);
750 : break;
751 : case GS4_ENSEMBLE_STAT:
752 : Print ("PDS-S4", "Type of Ensemble forecast", Prt_DS,
753 : sect4->typeEnsemble,
754 : Lookup (tbl46, sizeof (tbl46), sect4->typeEnsemble));
755 : Print ("PDS-S4", "Perturbation number", Prt_D, sect4->perturbNum);
756 : Print ("PDS-S4", "Number of forecasts in ensemble", Prt_D,
757 : sect4->numberFcsts);
758 : Clock_Print (buffer, 100, sect4->validTime, "%m/%d/%Y %H:%M:%S UTC",
759 : 0);
760 : Print ("PDS-S4", "End of overall time interval", Prt_S, buffer);
761 : Print ("PDS-S4", "Total number of missing values", Prt_D,
762 : sect4->numMissing);
763 : Print ("PDS-S4", "Number of time range specifications", Prt_D,
764 : sect4->numInterval);
765 : for (i = 0; i < sect4->numInterval; i++) {
766 : Print ("PDS-S4", "Interval number", Prt_D, i + 1);
767 : Print ("PDS-S4", "Statistical process", Prt_DS,
768 : sect4->Interval[i].processID,
769 : Lookup (tbl410, sizeof (tbl410),
770 : sect4->Interval[i].processID));
771 : Print ("PDS-S4", "Type of time increment", Prt_DS,
772 : sect4->Interval[i].incrType,
773 : Lookup (tbl411, sizeof (tbl411),
774 : sect4->Interval[i].incrType));
775 : /* Following is so we get "# str" not "# (str)" */
776 : sprintf (buffer, "%d %s", sect4->Interval[i].lenTime,
777 : Lookup (tbl44, sizeof (tbl44),
778 : sect4->Interval[i].timeRangeUnit));
779 : Print ("PDS-S4", "Time range for processing", Prt_S, buffer);
780 : /* Following is so we get "# str" not "# (str)" */
781 : sprintf (buffer, "%d %s", sect4->Interval[i].timeIncr,
782 : Lookup (tbl44, sizeof (tbl44),
783 : sect4->Interval[i].incrUnit));
784 : Print ("PDS-S4", "Time increment", Prt_S, buffer);
785 : }
786 : break;
787 : case GS4_DERIVED:
788 : Print ("PDS-S4", "Derived forecast", Prt_DS, sect4->derivedFcst,
789 : Lookup (tbl47, sizeof (tbl47), sect4->derivedFcst));
790 : Print ("PDS-S4", "Number of forecasts in ensemble", Prt_D,
791 : sect4->numberFcsts);
792 : break;
793 : case GS4_DERIVED_INTERVAL:
794 : Print ("PDS-S4", "Derived forecast", Prt_DS, sect4->derivedFcst,
795 : Lookup (tbl47, sizeof (tbl47), sect4->derivedFcst));
796 : Print ("PDS-S4", "Number of forecasts in ensemble", Prt_D,
797 : sect4->numberFcsts);
798 : Clock_Print (buffer, 100, sect4->validTime, "%m/%d/%Y %H:%M:%S UTC",
799 : 0);
800 :
801 : Print ("PDS-S4", "End of overall time interval", Prt_S, buffer);
802 : Print ("PDS-S4", "Total number of missing values", Prt_D,
803 : sect4->numMissing);
804 : Print ("PDS-S4", "Number of time range specifications", Prt_D,
805 : sect4->numInterval);
806 : for (i = 0; i < sect4->numInterval; i++) {
807 : Print ("PDS-S4", "Interval number", Prt_D, i + 1);
808 : Print ("PDS-S4", "Statistical process", Prt_DS,
809 : sect4->Interval[i].processID,
810 : Lookup (tbl410, sizeof (tbl410),
811 : sect4->Interval[i].processID));
812 : Print ("PDS-S4", "Type of time increment", Prt_DS,
813 : sect4->Interval[i].incrType,
814 : Lookup (tbl411, sizeof (tbl411),
815 : sect4->Interval[i].incrType));
816 : /* Following is so we get "# str" not "# (str)" */
817 : sprintf (buffer, "%d %s", sect4->Interval[i].lenTime,
818 : Lookup (tbl44, sizeof (tbl44),
819 : sect4->Interval[i].timeRangeUnit));
820 : Print ("PDS-S4", "Time range for processing", Prt_S, buffer);
821 : /* Following is so we get "# str" not "# (str)" */
822 : sprintf (buffer, "%d %s", sect4->Interval[i].timeIncr,
823 : Lookup (tbl44, sizeof (tbl44),
824 : sect4->Interval[i].incrUnit));
825 : Print ("PDS-S4", "Time increment", Prt_S, buffer);
826 : }
827 : break;
828 : case GS4_PROBABIL_PNT:
829 : Print ("PDS-S4", "Forecast Probability Number", Prt_D,
830 : sect4->foreProbNum);
831 : Print ("PDS-S4", "Total Number of Forecast Probabilities", Prt_D,
832 : sect4->numForeProbs);
833 : Print ("PDS-S4", "Probability type", Prt_DS, sect4->probType,
834 : Lookup (tbl49, sizeof (tbl49), sect4->probType));
835 : sprintf (buffer, "%d, %d", sect4->lowerLimit.value,
836 : sect4->lowerLimit.factor);
837 : Print ("PDS-S4", "Lower limit (scale value, scale factor)", Prt_GS,
838 : sect4->lowerLimit.value *
839 : pow (10.0, -1 * sect4->lowerLimit.factor), buffer);
840 : sprintf (buffer, "%d, %d", sect4->upperLimit.value,
841 : sect4->upperLimit.factor);
842 : Print ("PDS-S4", "Upper limit (scale value, scale factor)", Prt_GS,
843 : sect4->upperLimit.value *
844 : pow (10.0, -1 * sect4->upperLimit.factor), buffer);
845 : /* printf ("Hello world 1\n");*/
846 : break;
847 : case GS4_PERCENT_PNT:
848 : Print ("PDS-S4", "Percentile", Prt_DS, sect4->percentile, "[%]");
849 : break;
850 : case GS4_PERCENT_TIME:
851 : Print ("PDS-S4", "Percentile", Prt_DS, sect4->percentile, "[%]");
852 : /* strftime (buffer, 100, "%m/%d/%Y %H:%M:%S UTC",
853 : gmtime (&(sect4->validTime)));*/
854 : Clock_Print (buffer, 100, sect4->validTime, "%m/%d/%Y %H:%M:%S UTC",
855 : 0);
856 :
857 : Print ("PDS-S4", "End of overall time interval", Prt_S, buffer);
858 : Print ("PDS-S4", "Total number of missing values", Prt_D,
859 : sect4->numMissing);
860 : Print ("PDS-S4", "Number of time range specifications", Prt_D,
861 : sect4->numInterval);
862 : for (i = 0; i < sect4->numInterval; i++) {
863 : Print ("PDS-S4", "Interval number", Prt_D, i + 1);
864 : Print ("PDS-S4", "Statistical process", Prt_DS,
865 : sect4->Interval[i].processID,
866 : Lookup (tbl410, sizeof (tbl410),
867 : sect4->Interval[i].processID));
868 : Print ("PDS-S4", "Type of time increment", Prt_DS,
869 : sect4->Interval[i].incrType,
870 : Lookup (tbl411, sizeof (tbl411),
871 : sect4->Interval[i].incrType));
872 : /* Following is so we get "# str" not "# (str)" */
873 : sprintf (buffer, "%d %s", sect4->Interval[i].lenTime,
874 : Lookup (tbl44, sizeof (tbl44),
875 : sect4->Interval[i].timeRangeUnit));
876 : Print ("PDS-S4", "Time range for processing", Prt_S, buffer);
877 : /* Following is so we get "# str" not "# (str)" */
878 : sprintf (buffer, "%d %s", sect4->Interval[i].timeIncr,
879 : Lookup (tbl44, sizeof (tbl44),
880 : sect4->Interval[i].incrUnit));
881 : Print ("PDS-S4", "Time increment", Prt_S, buffer);
882 : }
883 : break;
884 : case GS4_PROBABIL_TIME:
885 : Print ("PDS-S4", "Forecast Probability Number", Prt_D,
886 : sect4->foreProbNum);
887 : Print ("PDS-S4", "Total Number of Forecast Probabilities", Prt_D,
888 : sect4->numForeProbs);
889 : Print ("PDS-S4", "Probability type", Prt_DS, sect4->probType,
890 : Lookup (tbl49, sizeof (tbl49), sect4->probType));
891 : sprintf (buffer, "%d, %d", sect4->lowerLimit.value,
892 : sect4->lowerLimit.factor);
893 : Print ("PDS-S4", "Lower limit (scale value, scale factor)", Prt_GS,
894 : sect4->lowerLimit.value *
895 : pow (10.0, -1 * sect4->lowerLimit.factor), buffer);
896 : sprintf (buffer, "%d, %d", sect4->upperLimit.value,
897 : sect4->upperLimit.factor);
898 : Print ("PDS-S4", "Upper limit (scale value, scale factor)", Prt_GS,
899 : sect4->upperLimit.value *
900 : pow (10.0, -1 * sect4->upperLimit.factor), buffer);
901 : /* Intentionally fall through. */
902 : [[fallthrough]];
903 : case GS4_STATISTIC:
904 : /* strftime (buffer, 100, "%m/%d/%Y %H:%M:%S UTC",
905 : gmtime (&(sect4->validTime)));*/
906 : Clock_Print (buffer, 100, sect4->validTime, "%m/%d/%Y %H:%M:%S UTC",
907 : 0);
908 :
909 : Print ("PDS-S4", "End of overall time interval", Prt_S, buffer);
910 : Print ("PDS-S4", "Total number of missing values", Prt_D,
911 : sect4->numMissing);
912 : Print ("PDS-S4", "Number of time range specifications", Prt_D,
913 : sect4->numInterval);
914 : for (i = 0; i < sect4->numInterval; i++) {
915 : Print ("PDS-S4", "Interval number", Prt_D, i + 1);
916 : Print ("PDS-S4", "Statistical process", Prt_DS,
917 : sect4->Interval[i].processID,
918 : Lookup (tbl410, sizeof (tbl410),
919 : sect4->Interval[i].processID));
920 : Print ("PDS-S4", "Type of time increment", Prt_DS,
921 : sect4->Interval[i].incrType,
922 : Lookup (tbl411, sizeof (tbl411),
923 : sect4->Interval[i].incrType));
924 : /* Following is so we get "# str" not "# (str)" */
925 : sprintf (buffer, "%d %s", sect4->Interval[i].lenTime,
926 : Lookup (tbl44, sizeof (tbl44),
927 : sect4->Interval[i].timeRangeUnit));
928 : Print ("PDS-S4", "Time range for processing", Prt_S, buffer);
929 : /* Following is so we get "# str" not "# (str)" */
930 : sprintf (buffer, "%d %s", sect4->Interval[i].timeIncr,
931 : Lookup (tbl44, sizeof (tbl44),
932 : sect4->Interval[i].incrUnit));
933 : Print ("PDS-S4", "Time increment", Prt_S, buffer);
934 : }
935 : break;
936 : default:
937 : /* This case should have been handled in first switch statement of
938 : * this procedure, but just in case... */
939 : errSprintf ("Un-supported Sect4 template %d\n", sect4->templat);
940 : return -2;
941 : }
942 : return 0;
943 : }
944 :
945 : /*****************************************************************************
946 : * PrintPDS2() --
947 : *
948 : * Arthur Taylor / MDL
949 : *
950 : * PURPOSE
951 : * To generate the message for the Product Definition Sections of the GRIB2
952 : * Message.
953 : *
954 : * ARGUMENTS
955 : * meta = The meta file structure to generate the message for. (Input)
956 : * f_unit = 0 (GRIB unit), 1 (english), 2 (metric) (Input)
957 : *
958 : * FILES/DATABASES: None
959 : *
960 : * RETURNS: void
961 : *
962 : * HISTORY
963 : * 4/2003 Arthur Taylor (MDL/RSIS): Created.
964 : *
965 : * NOTES
966 : *****************************************************************************
967 : */
968 : static int PrintPDS2 (grib_MetaData *meta, sChar f_unit)
969 : {
970 : pdsG2Type *pds2 = &(meta->pds2);
971 : /* Based on Grib2 Code Table 0.0 */
972 : static const char * const table0[] = {
973 : "Meteorological products", "Hydrological products",
974 : "Land surface products", "Space products", "Oceanographic products"
975 : };
976 : int ierr; /* The error code of a called routine */
977 :
978 : /* Print the data from Section 0 */
979 : switch (pds2->prodType) {
980 : case 10: /* Oceanographic Product. */
981 : Print ("PDS-S0", "DataType", Prt_DS, pds2->prodType, table0[4]);
982 : break;
983 : case 5: /* Reserved. */
984 : Print ("PDS-S0", "DataType", Prt_DS, pds2->prodType,
985 : Lookup (table0, sizeof (table0), 191));
986 : break;
987 : default:
988 : Print ("PDS-S0", "DataType", Prt_DS, pds2->prodType,
989 : Lookup (table0, sizeof (table0), pds2->prodType));
990 : }
991 : PrintSect1 (pds2, meta->center, meta->subcenter);
992 : PrintSect2 (&(pds2->sect2));
993 : if ((ierr = PrintSect4 (meta, f_unit)) != 0) {
994 : return ierr;
995 : }
996 : return 0;
997 : }
998 :
999 : /*****************************************************************************
1000 : * PrintPDS1() --
1001 : *
1002 : * Arthur Taylor / MDL
1003 : *
1004 : * PURPOSE
1005 : * To generate the message for the Product Definition Sections of the GRIB1
1006 : * Message.
1007 : *
1008 : * ARGUMENTS
1009 : * pds1 = The GRIB1 Product Definition Section to print. (Input)
1010 : * comment = A description about this element. See GRIB1_Table2LookUp (Input)
1011 : * center = The Center that created the data (Input)
1012 : * subcenter = The Sub Center that created the data (Input)
1013 : * f_unit = The unit conversion method used on the output data (Input)
1014 : * unitName = The name of the output unit type. (Input)
1015 : * convert = Conversion method used. (Input)
1016 : *
1017 : * FILES/DATABASES: None
1018 : *
1019 : * RETURNS: void
1020 : *
1021 : * HISTORY
1022 : * 4/2003 Arthur Taylor (MDL/RSIS): Created.
1023 : * 10/2005 AAT: Adjusted to take center, subcenter as we moved that out of
1024 : * the pdsG1 type.
1025 : * 11/2005 AAT: Added f_unit variable.
1026 : *
1027 : * NOTES
1028 : *****************************************************************************
1029 : */
1030 : static void PrintPDS1 (pdsG1Type *pds1, char *comment,
1031 : unsigned short int center,
1032 : unsigned short int subcenter, sChar f_unit,
1033 : char *unitName, int convert)
1034 : {
1035 : char buffer[25]; /* Stores format of pds1->refTime. */
1036 : const char *ptr;
1037 :
1038 : Print ("PDS-S1", "Parameter Tables Version", Prt_D, pds1->mstrVersion);
1039 : ptr = centerLookup (center);
1040 : if (ptr != NULL) {
1041 : Print ("PDS-S1", "Originating center", Prt_DS, center, ptr);
1042 : } else {
1043 : Print ("PDS-S1", "Originating center", Prt_D, center);
1044 : }
1045 : ptr = subCenterLookup (center, subcenter);
1046 : if (ptr != NULL) {
1047 : Print ("PDS-S1", "Originating sub-center", Prt_DS, subcenter, ptr);
1048 : } else {
1049 : Print ("PDS-S1", "Originating sub-center", Prt_D, subcenter);
1050 : }
1051 : ptr = processLookup (center, pds1->genProcess);
1052 : if (ptr != NULL) {
1053 : Print ("PDS-S1", "Generation process", Prt_DS, pds1->genProcess, ptr);
1054 : } else {
1055 : Print ("PDS-S1", "Generation process", Prt_D, pds1->genProcess);
1056 : }
1057 : Print ("PDS-S1", "Grid Identification Number", Prt_D, pds1->gridID);
1058 : Print ("PDS-S1", "Indicator of parameter and units", Prt_DS, pds1->cat,
1059 : comment);
1060 : if (convert != UC_NONE) {
1061 : if (f_unit == 1) {
1062 : Print ("PDS-S1", "Output grid, (COMPUTED) english unit is", Prt_S,
1063 : unitName);
1064 : } else if (f_unit == 2) {
1065 : Print ("PDS-S1", "Output grid, (COMPUTED) metric unit is", Prt_S,
1066 : unitName);
1067 : }
1068 : }
1069 : Print ("PDS-S1", "Type of fixed surface", Prt_D, pds1->levelType);
1070 : Print ("PDS-S1", "Value of fixed surface", Prt_D, pds1->levelVal);
1071 :
1072 : /* strftime (buffer, 25, "%m/%d/%Y %H:%M:%S UTC", gmtime (&(pds1->refTime))); */
1073 : Clock_Print (buffer, 25, pds1->refTime, "%m/%d/%Y %H:%M:%S UTC", 0);
1074 :
1075 : Print ("PDS-S1", "Reference Time", Prt_S, buffer);
1076 :
1077 : /* strftime (buffer, 25, "%m/%d/%Y %H:%M:%S UTC",
1078 : gmtime (&(pds1->validTime))); */
1079 : Clock_Print (buffer, 25, pds1->validTime, "%m/%d/%Y %H:%M:%S UTC", 0);
1080 :
1081 : Print ("PDS-S1", "Valid Time", Prt_S, buffer);
1082 :
1083 : /* strftime (buffer, 25, "%m/%d/%Y %H:%M:%S UTC", gmtime (&(pds1->P1))); */
1084 : Clock_Print (buffer, 25, pds1->P1, "%m/%d/%Y %H:%M:%S UTC", 0);
1085 :
1086 : Print ("PDS-S1", "P1 Time", Prt_S, buffer);
1087 :
1088 : /* strftime (buffer, 25, "%m/%d/%Y %H:%M:%S UTC", gmtime (&(pds1->P2))); */
1089 : Clock_Print (buffer, 25, pds1->P2, "%m/%d/%Y %H:%M:%S UTC", 0);
1090 :
1091 : Print ("PDS-S1", "P2 Time", Prt_S, buffer);
1092 : Print ("PDS-S1", "Time range indicator", Prt_D, pds1->timeRange);
1093 : Print ("PDS-S1", "Number included in average", Prt_D, pds1->Average);
1094 : Print ("PDS-S1", "Number missing from average or accumulation", Prt_D,
1095 : pds1->numberMissing);
1096 :
1097 : if (pds1->f_hasEns) {
1098 : Print ("PDS-S1", "Ensemble BitFlag (octet 29)", Prt_D,
1099 : pds1->ens.BitFlag);
1100 : Print ("PDS-S1", "Ensemble Application", Prt_D, pds1->ens.Application);
1101 : Print ("PDS-S1", "Ensemble Type", Prt_D, pds1->ens.Type);
1102 : Print ("PDS-S1", "Ensemble Number", Prt_D, pds1->ens.Number);
1103 : Print ("PDS-S1", "Ensemble ProdID", Prt_D, pds1->ens.ProdID);
1104 : Print ("PDS-S1", "Ensemble Smoothing", Prt_D, pds1->ens.Smooth);
1105 : }
1106 : if (pds1->f_hasProb) {
1107 : Print ("PDS-S1", "Prob Category", Prt_D, pds1->prob.Cat);
1108 : Print ("PDS-S1", "Prob Type", Prt_D, pds1->prob.Type);
1109 : Print ("PDS-S1", "Prob lower", Prt_F, pds1->prob.lower);
1110 : Print ("PDS-S1", "Prob upper", Prt_F, pds1->prob.upper);
1111 : }
1112 : if (pds1->f_hasCluster) {
1113 : Print ("PDS-S1", "Cluster Ens Size", Prt_D, pds1->cluster.ensSize);
1114 : Print ("PDS-S1", "Cluster Size", Prt_D, pds1->cluster.clusterSize);
1115 : Print ("PDS-S1", "Cluster Number", Prt_D, pds1->cluster.Num);
1116 : Print ("PDS-S1", "Cluster Method", Prt_D, pds1->cluster.Method);
1117 : Print ("PDS-S1", "Cluster North Latitude", Prt_F, pds1->cluster.NorLat);
1118 : Print ("PDS-S1", "Cluster South Latitude", Prt_F, pds1->cluster.SouLat);
1119 : Print ("PDS-S1", "Cluster East Longitude", Prt_F, pds1->cluster.EasLon);
1120 : Print ("PDS-S1", "Cluster West Longitude", Prt_F, pds1->cluster.WesLon);
1121 : sprintf (buffer, "'%10s'", pds1->cluster.Member);
1122 : Print ("PDS-S1", "Cluster Membership", Prt_S, buffer);
1123 : }
1124 : }
1125 :
1126 : /*****************************************************************************
1127 : * PrintGDS() --
1128 : *
1129 : * Arthur Taylor / MDL
1130 : *
1131 : * PURPOSE
1132 : * To generate the message for the Grid Definition Section.
1133 : *
1134 : * ARGUMENTS
1135 : * gds = The gds structure to print. (Input)
1136 : * version = The GRIB version number (so we know what type of projection) (In)
1137 : *
1138 : * FILES/DATABASES: None
1139 : *
1140 : * RETURNS: int (could use errSprintf())
1141 : * 0 if no error.
1142 : * -1 if asked to print a map projection that we don't support.
1143 : *
1144 : * HISTORY
1145 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
1146 : * 4/2003 AAT: Switched from sect3 to gds
1147 : * 5/2003 AAT: Since the number for ProjectionType changed from GRIB1 to
1148 : * GRIB2, we use the GRIB2 internally, but for meta data we want to
1149 : * print the appropriate one.
1150 : * 5/2003 AAT: Decided to have 1,1 be lower left corner in .shp files.
1151 : * 10/2004 AAT: Added TDLP support.
1152 : *
1153 : * NOTES
1154 : * Need to add support for GS3_ORTHOGRAPHIC = 90,
1155 : * GS3_EQUATOR_EQUIDIST = 110, GS3_AZIMUTH_RANGE = 120
1156 : *****************************************************************************
1157 : */
1158 : static int PrintGDS (gdsType *gds, int version)
1159 : {
1160 : /* Based on Grib2 Code Table 3.1 */
1161 : static const char * const table31[] = { "Latitude/Longitude", "Mercator",
1162 : "Polar Stereographic", "Lambert Conformal",
1163 : "Space view perspective orthographic",
1164 : "Equatorial azimuthal equidistant projection",
1165 : "Azimuth-range projection"
1166 : };
1167 : char buffer[50]; /* Temporary storage for info about scan flag. */
1168 :
1169 : Print ("GDS", "Number of Points", Prt_D, gds->numPts);
1170 : switch (gds->projType) {
1171 : case GS3_LATLON: /* 0 */
1172 : if (version == 1) {
1173 : Print ("GDS", "Projection Type", Prt_DS, GB1S2_LATLON,
1174 : table31[0]);
1175 : } else {
1176 : Print ("GDS", "Projection Type", Prt_DS, gds->projType,
1177 : table31[0]);
1178 : }
1179 : break;
1180 : case GS3_MERCATOR: /* 10 */
1181 : if (version == 1) {
1182 : Print ("GDS", "Projection Type", Prt_DS, GB1S2_MERCATOR,
1183 : table31[1]);
1184 : } else if (version == -1) {
1185 : Print ("GDS", "Projection Type", Prt_DS, TDLP_MERCATOR,
1186 : table31[1]);
1187 : } else {
1188 : Print ("GDS", "Projection Type", Prt_DS, gds->projType,
1189 : table31[1]);
1190 : }
1191 : break;
1192 : case GS3_POLAR: /* 20 */
1193 : if (version == 1) {
1194 : Print ("GDS", "Projection Type", Prt_DS, GB1S2_POLAR, table31[2]);
1195 : } else if (version == -1) {
1196 : Print ("GDS", "Projection Type", Prt_DS, TDLP_POLAR, table31[2]);
1197 : } else {
1198 : Print ("GDS", "Projection Type", Prt_DS, gds->projType,
1199 : table31[2]);
1200 : }
1201 : break;
1202 : case GS3_LAMBERT: /* 30 */
1203 : if (version == 1) {
1204 : Print ("GDS", "Projection Type", Prt_DS, GB1S2_LAMBERT,
1205 : table31[3]);
1206 : } else if (version == -1) {
1207 : Print ("GDS", "Projection Type", Prt_DS, TDLP_LAMBERT,
1208 : table31[3]);
1209 : } else {
1210 : Print ("GDS", "Projection Type", Prt_DS, gds->projType,
1211 : table31[3]);
1212 : }
1213 : break;
1214 : /*
1215 : * The following lines were removed until such time that the rest of this
1216 : * procedure can properly handle these three projection types.
1217 : *
1218 : case GS3_ORTHOGRAPHIC: * 90 *
1219 : Print ("GDS", "Projection Type", Prt_DS, gds->projType, table31[4]);
1220 : break;
1221 : case GS3_EQUATOR_EQUIDIST: * 110 *
1222 : Print ("GDS", "Projection Type", Prt_DS, gds->projType, table31[5]);
1223 : break;
1224 : case GS3_AZIMUTH_RANGE: * 120 *
1225 : Print ("GDS", "Projection Type", Prt_DS, gds->projType, table31[6]);
1226 : break;
1227 : */
1228 : default:
1229 : Print ("GDS", "Projection Type", Prt_D, gds->projType);
1230 : errSprintf ("Un-supported Map Projection %d\n", gds->projType);
1231 : return -1;
1232 : }
1233 : if (gds->f_sphere) {
1234 : Print ("GDS", "Shape of Earth", Prt_S, "sphere");
1235 : Print ("GDS", "Radius", Prt_FS, gds->majEarth, "km");
1236 : } else {
1237 : Print ("GDS", "Shape of Earth", Prt_S, "oblate spheroid");
1238 : Print ("GDS", "semi Major axis", Prt_FS, gds->majEarth, "km");
1239 : Print ("GDS", "semi Minor axis", Prt_FS, gds->minEarth, "km");
1240 : }
1241 : Print ("GDS", "Nx (Number of points on parallel)", Prt_D, gds->Nx);
1242 : Print ("GDS", "Ny (Number of points on meridian)", Prt_D, gds->Ny);
1243 : Print ("GDS", "Lat1", Prt_F, gds->lat1);
1244 : Print ("GDS", "Lon1", Prt_F, gds->lon1);
1245 : if (gds->resFlag & GRIB2BIT_5) {
1246 : Print ("GDS", "u/v vectors relative to", Prt_S, "grid");
1247 : } else {
1248 : Print ("GDS", "u/v vectors relative to", Prt_S, "easterly/northerly");
1249 : }
1250 : if (gds->projType == GS3_LATLON) {
1251 : Print ("GDS", "Lat2", Prt_F, gds->lat2);
1252 : Print ("GDS", "Lon2", Prt_F, gds->lon2);
1253 : Print ("GDS", "Dx", Prt_FS, gds->Dx, "degrees");
1254 : Print ("GDS", "Dy", Prt_FS, gds->Dy, "degrees");
1255 : } else if (gds->projType == GS3_MERCATOR) {
1256 : Print ("GDS", "Lat2", Prt_F, gds->lat2);
1257 : Print ("GDS", "Lon2", Prt_F, gds->lon2);
1258 : Print ("GDS", "Dx", Prt_FS, gds->Dx, "m");
1259 : Print ("GDS", "Dy", Prt_FS, gds->Dy, "m");
1260 : } else if ((gds->projType == GS3_POLAR)
1261 : || (gds->projType == GS3_LAMBERT)) {
1262 : Print ("GDS", "Dx", Prt_FS, gds->Dx, "m");
1263 : Print ("GDS", "Dy", Prt_FS, gds->Dy, "m");
1264 : }
1265 : /* For scan mode... The user of this data doesn't necessarily care how it
1266 : * was stored in the Grib2 grid (i.e. gds->scan), they just care about how
1267 : * the data they are accessing is scanned (i.e. scan=0000) */
1268 : sprintf (buffer, "%d%d%d%d", ((gds->scan & GRIB2BIT_1) / GRIB2BIT_1),
1269 : ((gds->scan & GRIB2BIT_2) / GRIB2BIT_2),
1270 : ((gds->scan & GRIB2BIT_3) / GRIB2BIT_3),
1271 : ((gds->scan & GRIB2BIT_4) / GRIB2BIT_4));
1272 : Print ("GDS", "Input GRIB2 grid, scan mode", Prt_DS, gds->scan, buffer);
1273 : /*
1274 : Print ("GDS", "Output grid, scan mode", Prt_DS, 0, "0000");
1275 : Print ("GDS", "Output grid, scan i/x direction", Prt_S, "positive");
1276 : Print ("GDS", "Output grid, scan j/y direction", Prt_S, "negative");
1277 : */
1278 : Print ("GDS", "Output grid, scan mode", Prt_DS, 64, "0100");
1279 : Print ("GDS", "(.flt file grid), scan mode", Prt_DS, 0, "0000");
1280 : Print ("GDS", "Output grid, scan i/x direction", Prt_S, "positive");
1281 : Print ("GDS", "Output grid, scan j/y direction", Prt_S, "positive");
1282 : Print ("GDS", "(.flt file grid), scan j/y direction", Prt_S, "negative");
1283 : Print ("GDS", "Output grid, consecutive points in", Prt_S,
1284 : "i/x direction");
1285 : Print ("GDS", "Output grid, adjacent rows scan in", Prt_S,
1286 : "same direction");
1287 :
1288 : /* Meshlat/orient lon/scale lat have no meaning for lat/lon grids. */
1289 : if (gds->projType != GS3_LATLON) {
1290 : Print ("GDS", "MeshLat", Prt_F, gds->meshLat);
1291 : Print ("GDS", "OrientLon", Prt_F, gds->orientLon);
1292 : if ((gds->projType == GS3_POLAR) || (gds->projType == GS3_LAMBERT)) {
1293 : if (gds->center & GRIB2BIT_1) {
1294 : Print ("GDS", "Which pole is on the plane", Prt_S, "South");
1295 : } else {
1296 : Print ("GDS", "Which pole is on the plane", Prt_S, "North");
1297 : }
1298 : if (gds->center & GRIB2BIT_2) {
1299 : Print ("GDS", "bi-polar projection", Prt_S, "Yes");
1300 : } else {
1301 : Print ("GDS", "bi-polar projection", Prt_S, "No");
1302 : }
1303 : }
1304 : Print ("GDS", "Tangent Lat1", Prt_F, gds->scaleLat1);
1305 : Print ("GDS", "Tangent Lat2", Prt_F, gds->scaleLat2);
1306 : Print ("GDS", "Southern Lat", Prt_F, gds->southLat);
1307 : Print ("GDS", "Southern Lon", Prt_F, gds->southLon);
1308 : }
1309 : return 0;
1310 : }
1311 :
1312 : /*****************************************************************************
1313 : * PrintGridAttrib() --
1314 : *
1315 : * Arthur Taylor / MDL
1316 : *
1317 : * PURPOSE
1318 : * To generate the message for the various attributes of the grid.
1319 : *
1320 : * ARGUMENTS
1321 : * attrib = The Grid Attribute structure to print. (Input)
1322 : * decimal = How many decimals to round to. (Input)
1323 : *
1324 : * FILES/DATABASES: None
1325 : *
1326 : * RETURNS: void
1327 : *
1328 : * HISTORY
1329 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
1330 : * 5/2003 AAT: Added rounding to decimal.
1331 : *
1332 : * NOTES
1333 : *****************************************************************************
1334 : */
1335 : static void PrintGridAttrib (gridAttribType *attrib, sChar decimal)
1336 : {
1337 : /* Based on Grib2 Code Table 5.0 */
1338 : static const char * const table50[] = {
1339 : "Grid point data - simple packing", "Matrix value - simple packing",
1340 : "Grid point data - complex packing",
1341 : "Grid point data - complex packing and spatial differencing"
1342 : };
1343 :
1344 : /* Based on Grib2 Code Table 5.1 */
1345 : static const char * const table51[] = { "Floating point", "Integer" };
1346 :
1347 : /* Based on Grib2 Code Table 5.5 */
1348 : static const char * const table55[] = {
1349 : "No explicit missing value included with data",
1350 : "Primary missing value included with data",
1351 : "Primary and Secondary missing values included with data"
1352 : };
1353 :
1354 : if ((attrib->packType == GS5_JPEG2000) ||
1355 : (attrib->packType == GS5_JPEG2000_ORG)) {
1356 : Print ("Info", "Packing that was used", Prt_DS, attrib->packType,
1357 : "JPEG 2000");
1358 : } else if ((attrib->packType == GS5_PNG) ||
1359 : (attrib->packType == GS5_PNG_ORG)) {
1360 : Print ("Info", "Packing that was used", Prt_DS, attrib->packType,
1361 : "Portable Network Graphics (PNG)");
1362 : } else {
1363 : Print ("Info", "Packing that was used", Prt_DS, attrib->packType,
1364 : Lookup (table50, sizeof (table50), attrib->packType));
1365 : }
1366 : /* Added next two 1/27/2006 because of questions from Val. */
1367 : Print ("Info", "Decimal Scale Factor", Prt_D, attrib->DSF);
1368 : Print ("Info", "Binary Scale Factor", Prt_D, attrib->ESF);
1369 : Print ("Info", "Original field type", Prt_DS, attrib->fieldType,
1370 : Lookup (table51, sizeof (table51), attrib->fieldType));
1371 : Print ("Info", "Missing value management", Prt_DS, attrib->f_miss,
1372 : Lookup (table55, sizeof (table55), attrib->f_miss));
1373 : if (attrib->f_miss == 1) {
1374 : Print ("Info", "Primary missing value", Prt_F,
1375 : myRound (attrib->missPri, decimal));
1376 : } else if (attrib->f_miss == 2) {
1377 : Print ("Info", "Primary missing value", Prt_F,
1378 : myRound (attrib->missPri, decimal));
1379 : Print ("Info", "Secondary missing value", Prt_F,
1380 : myRound (attrib->missSec, decimal));
1381 : }
1382 : Print ("Info", "Detected number of Missing", Prt_D, attrib->numMiss);
1383 : if (attrib->f_maxmin) {
1384 : Print ("Info", "Field minimum value", Prt_F,
1385 : myRound (attrib->min, decimal));
1386 : Print ("Info", "Field maximum value", Prt_F,
1387 : myRound (attrib->max, decimal));
1388 : }
1389 : }
1390 :
1391 : /*****************************************************************************
1392 : * MetaPrintGDS() --
1393 : *
1394 : * Arthur Taylor / MDL
1395 : *
1396 : * PURPOSE
1397 : * To generate a message specific for the GDS. Basically a wrapper for
1398 : * PrintGDS and Print.
1399 : *
1400 : * ARGUMENTS
1401 : * gds = The Grid Definition Section to generate the message for. (Input)
1402 : * version = The GRIB version number (so we know what type of projection) (In)
1403 : * ans = The resulting message. Up to caller to free. (Output)
1404 : *
1405 : * FILES/DATABASES: None
1406 : *
1407 : * RETURNS: int (could use errSprintf())
1408 : * 0 if no error.
1409 : * -1 if asked to print a map projection that we don't support.
1410 : * -2 if asked to print data for a template that we don't support.
1411 : *
1412 : * HISTORY
1413 : * 4/2003 Arthur Taylor (MDL/RSIS): Created.
1414 : * 5/2003 AAT: Commented out. Purpose was mainly for debugging degrib1.c,
1415 : * which is now working.
1416 : *
1417 : * NOTES
1418 : *****************************************************************************
1419 : */
1420 : int MetaPrintGDS (gdsType *gds, int version, char **ans)
1421 : {
1422 : int ierr; /* The error code of a called routine */
1423 :
1424 : if ((ierr = PrintGDS (gds, version)) != 0) {
1425 : *ans = Print (NULL, NULL, Prt_NULL);
1426 : preErrSprintf ("Print error Section 3\n");
1427 : return ierr;
1428 : }
1429 : *ans = Print (NULL, NULL, Prt_NULL);
1430 : return 0;
1431 : }
1432 :
1433 : /*****************************************************************************
1434 : * MetaPrint() --
1435 : *
1436 : * Arthur Taylor / MDL
1437 : *
1438 : * PURPOSE
1439 : * To generate the meta file message.
1440 : *
1441 : * ARGUMENTS
1442 : * meta = The meta file structure to generate the message for. (Input)
1443 : * ans = The resulting message. Up to caller to free. (Output)
1444 : * decimal = How many decimals to round to. (Input)
1445 : * f_unit = 0 (GRIB unit), 1 (english), 2 (metric) (Input)
1446 : *
1447 : * FILES/DATABASES: None
1448 : *
1449 : * RETURNS: int (could use errSprintf())
1450 : * 0 if no error.
1451 : * -1 if asked to print a map projection that we don't support.
1452 : * -2 if asked to print data for a template that we don't support.
1453 : *
1454 : * HISTORY
1455 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
1456 : * 5/2003 AAT: Added rounding to decimal.
1457 : *
1458 : * NOTES
1459 : *****************************************************************************
1460 : */
1461 : int MetaPrint (grib_MetaData *meta, char **ans, sChar decimal, sChar f_unit)
1462 : {
1463 : int ierr; /* The error code of a called routine */
1464 :
1465 : if (meta->GribVersion == 1) {
1466 : PrintPDS1 (&(meta->pds1), meta->comment, meta->center,
1467 : meta->subcenter, f_unit, meta->unitName, meta->convert);
1468 : } else if (meta->GribVersion == -1) {
1469 : PrintPDS_TDLP (&(meta->pdsTdlp));
1470 : } else {
1471 : if ((ierr = PrintPDS2 (meta, f_unit)) != 0) {
1472 : *ans = Print (NULL, NULL, Prt_NULL);
1473 : preErrSprintf ("Print error in PDS for GRIB2\n");
1474 : return ierr;
1475 : }
1476 : }
1477 : if ((ierr = PrintGDS (&(meta->gds), meta->GribVersion)) != 0) {
1478 : *ans = Print (NULL, NULL, Prt_NULL);
1479 : preErrSprintf ("Print error Section 3\n");
1480 : return ierr;
1481 : }
1482 : PrintGridAttrib (&(meta->gridAttrib), decimal);
1483 : *ans = Print (NULL, NULL, Prt_NULL);
1484 : return 0;
1485 : }
1486 : #endif // Unused with GDAL.
|