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