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 */
Lookup(const char ** table,size_t n,size_t index)56 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 if (index < (n / sizeof (char *))) {
61 return table[index];
62 } else if (index < 192) {
63 return def[0];
64 } else if (index < 255) {
65 return def[1];
66 } else {
67 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 */
Print(const char * label,const char * varName,Prt_TYPE fmt,...)115 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 if (fmt == Prt_NULL) {
126 ans = buffer;
127 buffer = NULL;
128 return ans;
129 }
130 va_start (ap, fmt); /* make ap point to 1st unnamed arg. */
131 switch (fmt) {
132 case Prt_D:
133 lival = va_arg (ap, sInt4);
134 reallocSprintf (&buffer, "%s | %s | %ld\n", label, varName, lival);
135 break;
136 case Prt_DS:
137 lival = va_arg (ap, sInt4);
138 sval = va_arg (ap, char *);
139 reallocSprintf (&buffer, "%s | %s | %ld (%s)\n", label, varName,
140 lival, sval);
141 break;
142 case Prt_DSS:
143 lival = va_arg (ap, sInt4);
144 sval = va_arg (ap, char *);
145 unit = va_arg (ap, char *);
146 reallocSprintf (&buffer, "%s | %s | %ld (%s [%s])\n", label,
147 varName, lival, sval, unit);
148 break;
149 case Prt_S:
150 sval = va_arg (ap, char *);
151 reallocSprintf (&buffer, "%s | %s | %s\n", label, varName, sval);
152 break;
153 case Prt_SS:
154 sval = va_arg (ap, char *);
155 unit = va_arg (ap, char *);
156 reallocSprintf (&buffer, "%s | %s | %s (%s)\n", label, varName,
157 sval, unit);
158 break;
159 case Prt_F:
160 dval = va_arg (ap, double);
161 reallocSprintf (&buffer, "%s | %s | %f\n", label, varName, dval);
162 break;
163 case Prt_E:
164 dval = va_arg (ap, double);
165 reallocSprintf (&buffer, "%s | %s | %e\n", label, varName, dval);
166 break;
167 case Prt_G:
168 dval = va_arg (ap, double);
169 reallocSprintf (&buffer, "%s | %s | %g\n", label, varName, dval);
170 break;
171 case Prt_FS:
172 dval = va_arg (ap, double);
173 unit = va_arg (ap, char *);
174 reallocSprintf (&buffer, "%s | %s | %f (%s)\n", label, varName,
175 dval, unit);
176 break;
177 case Prt_ES:
178 dval = va_arg (ap, double);
179 unit = va_arg (ap, char *);
180 reallocSprintf (&buffer, "%s | %s | %e (%s)\n", label, varName,
181 dval, unit);
182 break;
183 case Prt_GS:
184 dval = va_arg (ap, double);
185 unit = va_arg (ap, char *);
186 reallocSprintf (&buffer, "%s | %s | %g (%s)\n", label, varName,
187 dval, unit);
188 break;
189 default:
190 reallocSprintf (&buffer, "ERROR: Invalid Print option '%d'\n", fmt);
191 }
192 va_end (ap); /* clean up when done. */
193 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 */
PrintSect1(pdsG2Type * pds2,unsigned short int center,unsigned short int subcenter)222 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 ptr = centerLookup (center);
248 if (ptr != NULL) {
249 Print ("PDS-S1", "Originating center", Prt_DS, center, ptr);
250 } else {
251 Print ("PDS-S1", "Originating center", Prt_D, center);
252 }
253 if (subcenter != GRIB2MISSING_u2) {
254 ptr = subCenterLookup (center, subcenter);
255 if (ptr != NULL) {
256 Print ("PDS-S1", "Originating sub-center", Prt_DS, subcenter, ptr);
257 } else {
258 Print ("PDS-S1", "Originating sub-center", Prt_D, subcenter);
259 }
260 }
261 Print ("PDS-S1", "GRIB Master Tables Version", Prt_D, pds2->mstrVersion);
262 Print ("PDS-S1", "GRIB Local Tables Version", Prt_D, pds2->lclVersion);
263 Print ("PDS-S1", "Significance of reference time", Prt_DS, pds2->sigTime,
264 Lookup (table12, sizeof (table12), pds2->sigTime));
265
266 /* strftime (buffer, 25, "%m/%d/%Y %H:%M:%S UTC", gmtime (&(pds2->refTime)));*/
267 Clock_Print (buffer, 25, pds2->refTime, "%m/%d/%Y %H:%M:%S UTC", 0);
268
269 Print ("PDS-S1", "Reference Time", Prt_S, buffer);
270 Print ("PDS-S1", "Operational Status", Prt_DS, pds2->operStatus,
271 Lookup (table13, sizeof (table13), pds2->operStatus));
272 Print ("PDS-S1", "Type of Data", Prt_DS, pds2->dataType,
273 Lookup (table14, sizeof (table14), pds2->dataType));
274 }
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 */
PrintSect2(sect2_type * sect2)298 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 switch (sect2->ptrType) {
304 case GS2_WXTYPE:
305 Print ("PDS-S2", "Number of Elements in Section 2", Prt_D,
306 sect2->wx.dataLen);
307 for (i = 0; i < sect2->wx.dataLen; i++) {
308 if (sect2->wx.ugly[i].validIndex != -1) {
309 sprintf (buffer, "Elem %3d Is Used", (int) i);
310 } else {
311 sprintf (buffer, "Elem %3d NOT Used", (int) i);
312 }
313 Print ("PDS-S2", buffer, Prt_S, sect2->wx.data[i]);
314 }
315 break;
316 case GS2_UNKNOWN:
317 Print ("PDS-S2", "Number of Elements in Section 2", Prt_D,
318 sect2->unknown.dataLen);
319 for (i = 0; i < sect2->unknown.dataLen; i++) {
320 sprintf (buffer, "Element %d", (int) i);
321 Print ("PDS-S2", buffer, Prt_F, sect2->unknown.data[i]);
322 }
323 break;
324 default:
325 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 */
PrintSect4_Category(grib_MetaData * meta)352 static void PrintSect4_Category (grib_MetaData *meta)
353 {
354 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 switch (meta->pds2.prodType) {
386 case 0: /* Meteo category. */
387 switch (sect4->cat) {
388 case 190:
389 Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
390 "CCITT IA5 string");
391 break;
392 case 191:
393 Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
394 "Miscellaneous");
395 break;
396 default:
397 Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
398 Lookup (tbl41_0, sizeof (tbl41_0), sect4->cat));
399 }
400 break;
401 case 1: /* Hydrological */
402 Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
403 Lookup (tbl41_1, sizeof (tbl41_1), sect4->cat));
404 break;
405 case 2: /* Land surface */
406 Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
407 Lookup (tbl41_2, sizeof (tbl41_2), sect4->cat));
408 break;
409 case 3: /* Space */
410 Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
411 Lookup (tbl41_3, sizeof (tbl41_3), sect4->cat));
412 break;
413 case 10: /* Oceanographic */
414 Print ("PDS-S4", "Category Description", Prt_DS, sect4->cat,
415 Lookup (tbl41_10, sizeof (tbl41_10), sect4->cat));
416 break;
417 default:
418 Print ("PDS-S4", "PrintSect4() does not handle this prodType",
419 Prt_D, meta->pds2.prodType);
420 }
421 }
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 */
PrintSect4(grib_MetaData * meta,sChar f_unit)461 static int PrintSect4 (grib_MetaData *meta, sChar f_unit)
462 {
463 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 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 tbl40[sect4->templat]);
563 break;
564 case GS4_PROBABIL_PNT:
565 Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[3]);
566 break;
567 case GS4_STATISTIC:
568 Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[4]);
569 break;
570 case GS4_PROBABIL_TIME:
571 Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[5]);
572 break;
573 case GS4_PERCENTILE:
574 Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[6]);
575 break;
576 case GS4_ENSEMBLE_STAT:
577 Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[7]);
578 break;
579 case GS4_DERIVED_INTERVAL:
580 Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[8]);
581 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 Print ("PDS-S4", "Product type", Prt_DS, sect4->templat, tbl40[10]);
592 break;
593 default:
594 Print ("PDS-S4", "Product type", Prt_D, sect4->templat);
595 errSprintf ("Un-supported Sect4 template %ld\n", sect4->templat);
596 return -2;
597 }
598
599 PrintSect4_Category (meta);
600 Print ("PDS-S4", "Category Sub-Description", Prt_DS, sect4->subcat,
601 meta->comment);
602
603 if (f_unit == 1) {
604 Print ("PDS-S4", "Output grid, (COMPUTED) english unit is", Prt_S,
605 meta->unitName);
606 } else if (f_unit == 2) {
607 Print ("PDS-S4", "Output grid, (COMPUTED) metric unit is", Prt_S,
608 meta->unitName);
609 }
610 Print ("PDS-S4", "Generation process", Prt_DS, sect4->genProcess,
611 Lookup (tbl43, sizeof (tbl43), sect4->genProcess));
612 if (sect4->templat == GS4_SATELLITE) {
613 Print ("PDS-S4", "Observation generating process", Prt_D, sect4->genID);
614 Print ("PDS-S4", "Number of contributing spectral bands", Prt_D,
615 sect4->numBands);
616 for (i = 0; i < sect4->numBands; i++) {
617 Print ("PDS-S4", "Satellite series", Prt_D, sect4->bands[i].series);
618 Print ("PDS-S4", "Satellite numbers", Prt_D,
619 sect4->bands[i].numbers);
620 Print ("PDS-S4", "Instrument type", Prt_D, sect4->bands[i].instType);
621 Print ("PDS-S4", "Scale Factor of central wave number", Prt_D,
622 sect4->bands[i].centWaveNum.factor);
623 Print ("PDS-S4", "Scale Value of central wave number", Prt_D,
624 sect4->bands[i].centWaveNum.value);
625 }
626 return 0;
627 }
628 if (sect4->bgGenID != GRIB2MISSING_u1) {
629 ptr = processLookup (meta->center, sect4->bgGenID);
630 if (ptr != NULL) {
631 Print ("PDS-S4", "Background generating process ID", Prt_DS,
632 sect4->bgGenID, ptr);
633 } else {
634 Print ("PDS-S4", "Background generating process ID", Prt_D,
635 sect4->bgGenID);
636 }
637 }
638 if (sect4->genID != GRIB2MISSING_u1) {
639 ptr = processLookup (meta->center, sect4->genID);
640 if (ptr != NULL) {
641 Print ("PDS-S4", "Forecast generating process ID", Prt_DS,
642 sect4->genID, ptr);
643 } else {
644 Print ("PDS-S4", "Forecast generating process ID", Prt_D,
645 sect4->genID);
646 }
647 }
648 if (sect4->f_validCutOff) {
649 Print ("PDS-S4", "Data cut off after reference time in seconds", Prt_D,
650 sect4->cutOff);
651 }
652 Print ("PDS-S4", "Forecast time in hours", Prt_F,
653 (double) (sect4->foreSec / 3600.));
654 surf = Table45Index (sect4->fstSurfType, &f_reserved, meta->center,
655 meta->subcenter);
656 Print ("PDS-S4", "Type of first fixed surface", Prt_DSS,
657 sect4->fstSurfType, surf.comment, surf.unit);
658 Print ("PDS-S4", "Value of first fixed surface", Prt_F,
659 sect4->fstSurfValue);
660 if (sect4->sndSurfType != GRIB2MISSING_u1) {
661 surf = Table45Index (sect4->sndSurfType, &f_reserved, meta->center,
662 meta->subcenter);
663 Print ("PDS-S4", "Type of second fixed surface", Prt_DSS,
664 sect4->sndSurfType, surf.comment, surf.unit);
665 Print ("PDS-S4", "Value of second fixed surface", Prt_F,
666 sect4->sndSurfValue);
667 }
668 switch (sect4->templat) {
669 case GS4_ANALYSIS:
670 break;
671 case GS4_ENSEMBLE:
672 Print ("PDS-S4", "Type of Ensemble forecast", Prt_DS,
673 sect4->typeEnsemble,
674 Lookup (tbl46, sizeof (tbl46), sect4->typeEnsemble));
675 Print ("PDS-S4", "Perturbation number", Prt_D, sect4->perturbNum);
676 Print ("PDS-S4", "Number of forecasts in ensemble", Prt_D,
677 sect4->numberFcsts);
678 break;
679 case GS4_ENSEMBLE_STAT:
680 Print ("PDS-S4", "Type of Ensemble forecast", Prt_DS,
681 sect4->typeEnsemble,
682 Lookup (tbl46, sizeof (tbl46), sect4->typeEnsemble));
683 Print ("PDS-S4", "Perturbation number", Prt_D, sect4->perturbNum);
684 Print ("PDS-S4", "Number of forecasts in ensemble", Prt_D,
685 sect4->numberFcsts);
686 Clock_Print (buffer, 100, sect4->validTime, "%m/%d/%Y %H:%M:%S UTC",
687 0);
688 Print ("PDS-S4", "End of overall time interval", Prt_S, buffer);
689 Print ("PDS-S4", "Total number of missing values", Prt_D,
690 sect4->numMissing);
691 Print ("PDS-S4", "Number of time range specifications", Prt_D,
692 sect4->numInterval);
693 for (i = 0; i < sect4->numInterval; i++) {
694 Print ("PDS-S4", "Interval number", Prt_D, i + 1);
695 Print ("PDS-S4", "Statistical process", Prt_DS,
696 sect4->Interval[i].processID,
697 Lookup (tbl410, sizeof (tbl410),
698 sect4->Interval[i].processID));
699 Print ("PDS-S4", "Type of time increment", Prt_DS,
700 sect4->Interval[i].incrType,
701 Lookup (tbl411, sizeof (tbl411),
702 sect4->Interval[i].incrType));
703 /* Following is so we get "# str" not "# (str)" */
704 sprintf (buffer, "%d %s", sect4->Interval[i].lenTime,
705 Lookup (tbl44, sizeof (tbl44),
706 sect4->Interval[i].timeRangeUnit));
707 Print ("PDS-S4", "Time range for processing", Prt_S, buffer);
708 /* Following is so we get "# str" not "# (str)" */
709 sprintf (buffer, "%d %s", sect4->Interval[i].timeIncr,
710 Lookup (tbl44, sizeof (tbl44),
711 sect4->Interval[i].incrUnit));
712 Print ("PDS-S4", "Time increment", Prt_S, buffer);
713 }
714 break;
715 case GS4_DERIVED:
716 Print ("PDS-S4", "Derived forecast", Prt_DS, sect4->derivedFcst,
717 Lookup (tbl47, sizeof (tbl47), sect4->derivedFcst));
718 Print ("PDS-S4", "Number of forecasts in ensemble", Prt_D,
719 sect4->numberFcsts);
720 break;
721 case GS4_DERIVED_INTERVAL:
722 Print ("PDS-S4", "Derived forecast", Prt_DS, sect4->derivedFcst,
723 Lookup (tbl47, sizeof (tbl47), sect4->derivedFcst));
724 Print ("PDS-S4", "Number of forecasts in ensemble", Prt_D,
725 sect4->numberFcsts);
726 Clock_Print (buffer, 100, sect4->validTime, "%m/%d/%Y %H:%M:%S UTC",
727 0);
728
729 Print ("PDS-S4", "End of overall time interval", Prt_S, buffer);
730 Print ("PDS-S4", "Total number of missing values", Prt_D,
731 sect4->numMissing);
732 Print ("PDS-S4", "Number of time range specifications", Prt_D,
733 sect4->numInterval);
734 for (i = 0; i < sect4->numInterval; i++) {
735 Print ("PDS-S4", "Interval number", Prt_D, i + 1);
736 Print ("PDS-S4", "Statistical process", Prt_DS,
737 sect4->Interval[i].processID,
738 Lookup (tbl410, sizeof (tbl410),
739 sect4->Interval[i].processID));
740 Print ("PDS-S4", "Type of time increment", Prt_DS,
741 sect4->Interval[i].incrType,
742 Lookup (tbl411, sizeof (tbl411),
743 sect4->Interval[i].incrType));
744 /* Following is so we get "# str" not "# (str)" */
745 sprintf (buffer, "%d %s", sect4->Interval[i].lenTime,
746 Lookup (tbl44, sizeof (tbl44),
747 sect4->Interval[i].timeRangeUnit));
748 Print ("PDS-S4", "Time range for processing", Prt_S, buffer);
749 /* Following is so we get "# str" not "# (str)" */
750 sprintf (buffer, "%d %s", sect4->Interval[i].timeIncr,
751 Lookup (tbl44, sizeof (tbl44),
752 sect4->Interval[i].incrUnit));
753 Print ("PDS-S4", "Time increment", Prt_S, buffer);
754 }
755 break;
756 case GS4_PROBABIL_PNT:
757 Print ("PDS-S4", "Forecast Probability Number", Prt_D,
758 sect4->foreProbNum);
759 Print ("PDS-S4", "Total Number of Forecast Probabilities", Prt_D,
760 sect4->numForeProbs);
761 Print ("PDS-S4", "Probability type", Prt_DS, sect4->probType,
762 Lookup (tbl49, sizeof (tbl49), sect4->probType));
763 sprintf (buffer, "%d, %d", sect4->lowerLimit.value,
764 sect4->lowerLimit.factor);
765 Print ("PDS-S4", "Lower limit (scale value, scale factor)", Prt_GS,
766 sect4->lowerLimit.value *
767 pow (10.0, -1 * sect4->lowerLimit.factor), buffer);
768 sprintf (buffer, "%d, %d", sect4->upperLimit.value,
769 sect4->upperLimit.factor);
770 Print ("PDS-S4", "Upper limit (scale value, scale factor)", Prt_GS,
771 sect4->upperLimit.value *
772 pow (10.0, -1 * sect4->upperLimit.factor), buffer);
773 /* printf ("Hello world 1\n");*/
774 break;
775 case GS4_PERCENTILE:
776 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);
781
782 Print ("PDS-S4", "End of overall time interval", Prt_S, buffer);
783 Print ("PDS-S4", "Total number of missing values", Prt_D,
784 sect4->numMissing);
785 Print ("PDS-S4", "Number of time range specifications", Prt_D,
786 sect4->numInterval);
787 for (i = 0; i < sect4->numInterval; i++) {
788 Print ("PDS-S4", "Interval number", Prt_D, i + 1);
789 Print ("PDS-S4", "Statistical process", Prt_DS,
790 sect4->Interval[i].processID,
791 Lookup (tbl410, sizeof (tbl410),
792 sect4->Interval[i].processID));
793 Print ("PDS-S4", "Type of time increment", Prt_DS,
794 sect4->Interval[i].incrType,
795 Lookup (tbl411, sizeof (tbl411),
796 sect4->Interval[i].incrType));
797 /* Following is so we get "# str" not "# (str)" */
798 sprintf (buffer, "%d %s", sect4->Interval[i].lenTime,
799 Lookup (tbl44, sizeof (tbl44),
800 sect4->Interval[i].timeRangeUnit));
801 Print ("PDS-S4", "Time range for processing", Prt_S, buffer);
802 /* Following is so we get "# str" not "# (str)" */
803 sprintf (buffer, "%d %s", sect4->Interval[i].timeIncr,
804 Lookup (tbl44, sizeof (tbl44),
805 sect4->Interval[i].incrUnit));
806 Print ("PDS-S4", "Time increment", Prt_S, buffer);
807 }
808 break;
809 case GS4_PROBABIL_TIME:
810 Print ("PDS-S4", "Forecast Probability Number", Prt_D,
811 sect4->foreProbNum);
812 Print ("PDS-S4", "Total Number of Forecast Probabilities", Prt_D,
813 sect4->numForeProbs);
814 Print ("PDS-S4", "Probability type", Prt_DS, sect4->probType,
815 Lookup (tbl49, sizeof (tbl49), sect4->probType));
816 sprintf (buffer, "%d, %d", sect4->lowerLimit.value,
817 sect4->lowerLimit.factor);
818 Print ("PDS-S4", "Lower limit (scale value, scale factor)", Prt_GS,
819 sect4->lowerLimit.value *
820 pow (10.0, -1 * sect4->lowerLimit.factor), buffer);
821 sprintf (buffer, "%d, %d", sect4->upperLimit.value,
822 sect4->upperLimit.factor);
823 Print ("PDS-S4", "Upper limit (scale value, scale factor)", Prt_GS,
824 sect4->upperLimit.value *
825 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);
832
833 Print ("PDS-S4", "End of overall time interval", Prt_S, buffer);
834 Print ("PDS-S4", "Total number of missing values", Prt_D,
835 sect4->numMissing);
836 Print ("PDS-S4", "Number of time range specifications", Prt_D,
837 sect4->numInterval);
838 for (i = 0; i < sect4->numInterval; i++) {
839 Print ("PDS-S4", "Interval number", Prt_D, i + 1);
840 Print ("PDS-S4", "Statistical process", Prt_DS,
841 sect4->Interval[i].processID,
842 Lookup (tbl410, sizeof (tbl410),
843 sect4->Interval[i].processID));
844 Print ("PDS-S4", "Type of time increment", Prt_DS,
845 sect4->Interval[i].incrType,
846 Lookup (tbl411, sizeof (tbl411),
847 sect4->Interval[i].incrType));
848 /* Following is so we get "# str" not "# (str)" */
849 sprintf (buffer, "%d %s", sect4->Interval[i].lenTime,
850 Lookup (tbl44, sizeof (tbl44),
851 sect4->Interval[i].timeRangeUnit));
852 Print ("PDS-S4", "Time range for processing", Prt_S, buffer);
853 /* Following is so we get "# str" not "# (str)" */
854 sprintf (buffer, "%d %s", sect4->Interval[i].timeIncr,
855 Lookup (tbl44, sizeof (tbl44),
856 sect4->Interval[i].incrUnit));
857 Print ("PDS-S4", "Time increment", Prt_S, buffer);
858 }
859 break;
860 default:
861 /* This case should have been handled in first switch statement of
862 * this procedure, but just in case... */
863 errSprintf ("Un-supported Sect4 template %d\n", sect4->templat);
864 return -2;
865 }
866 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 */
PrintPDS2(grib_MetaData * meta,sChar f_unit)892 static int PrintPDS2 (grib_MetaData *meta, sChar f_unit)
893 {
894 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 switch (pds2->prodType) {
904 case 10: /* Oceanographic Product. */
905 Print ("PDS-S0", "DataType", Prt_DS, pds2->prodType, table0[4]);
906 break;
907 case 5: /* Reserved. */
908 Print ("PDS-S0", "DataType", Prt_DS, pds2->prodType,
909 Lookup (table0, sizeof (table0), 191));
910 break;
911 default:
912 Print ("PDS-S0", "DataType", Prt_DS, pds2->prodType,
913 Lookup (table0, sizeof (table0), pds2->prodType));
914 }
915 PrintSect1 (pds2, meta->center, meta->subcenter);
916 PrintSect2 (&(pds2->sect2));
917 if ((ierr = PrintSect4 (meta, f_unit)) != 0) {
918 return ierr;
919 }
920 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 */
PrintPDS1(pdsG1Type * pds1,char * comment,unsigned short int center,unsigned short int subcenter,sChar f_unit,char * unitName,int convert)954 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 Print ("PDS-S1", "Parameter Tables Version", Prt_D, pds1->mstrVersion);
963 ptr = centerLookup (center);
964 if (ptr != NULL) {
965 Print ("PDS-S1", "Originating center", Prt_DS, center, ptr);
966 } else {
967 Print ("PDS-S1", "Originating center", Prt_D, center);
968 }
969 ptr = subCenterLookup (center, subcenter);
970 if (ptr != NULL) {
971 Print ("PDS-S1", "Originating sub-center", Prt_DS, subcenter, ptr);
972 } else {
973 Print ("PDS-S1", "Originating sub-center", Prt_D, subcenter);
974 }
975 ptr = processLookup (center, pds1->genProcess);
976 if (ptr != NULL) {
977 Print ("PDS-S1", "Generation process", Prt_DS, pds1->genProcess, ptr);
978 } else {
979 Print ("PDS-S1", "Generation process", Prt_D, pds1->genProcess);
980 }
981 Print ("PDS-S1", "Grid Identification Number", Prt_D, pds1->gridID);
982 Print ("PDS-S1", "Indicator of parameter and units", Prt_DS, pds1->cat,
983 comment);
984 if (convert != UC_NONE) {
985 if (f_unit == 1) {
986 Print ("PDS-S1", "Output grid, (COMPUTED) english unit is", Prt_S,
987 unitName);
988 } else if (f_unit == 2) {
989 Print ("PDS-S1", "Output grid, (COMPUTED) metric unit is", Prt_S,
990 unitName);
991 }
992 }
993 Print ("PDS-S1", "Type of fixed surface", Prt_D, pds1->levelType);
994 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 Clock_Print (buffer, 25, pds1->refTime, "%m/%d/%Y %H:%M:%S UTC", 0);
998
999 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 Clock_Print (buffer, 25, pds1->validTime, "%m/%d/%Y %H:%M:%S UTC", 0);
1004
1005 Print ("PDS-S1", "Valid Time", Prt_S, buffer);
1006
1007 /* strftime (buffer, 25, "%m/%d/%Y %H:%M:%S UTC", gmtime (&(pds1->P1))); */
1008 Clock_Print (buffer, 25, pds1->P1, "%m/%d/%Y %H:%M:%S UTC", 0);
1009
1010 Print ("PDS-S1", "P1 Time", Prt_S, buffer);
1011
1012 /* strftime (buffer, 25, "%m/%d/%Y %H:%M:%S UTC", gmtime (&(pds1->P2))); */
1013 Clock_Print (buffer, 25, pds1->P2, "%m/%d/%Y %H:%M:%S UTC", 0);
1014
1015 Print ("PDS-S1", "P2 Time", Prt_S, buffer);
1016 Print ("PDS-S1", "Time range indicator", Prt_D, pds1->timeRange);
1017 Print ("PDS-S1", "Number included in average", Prt_D, pds1->Average);
1018 Print ("PDS-S1", "Number missing from average or accumulation", Prt_D,
1019 pds1->numberMissing);
1020
1021 if (pds1->f_hasEns) {
1022 Print ("PDS-S1", "Ensemble BitFlag (octet 29)", Prt_D,
1023 pds1->ens.BitFlag);
1024 Print ("PDS-S1", "Ensemble Application", Prt_D, pds1->ens.Application);
1025 Print ("PDS-S1", "Ensemble Type", Prt_D, pds1->ens.Type);
1026 Print ("PDS-S1", "Ensemble Number", Prt_D, pds1->ens.Number);
1027 Print ("PDS-S1", "Ensemble ProdID", Prt_D, pds1->ens.ProdID);
1028 Print ("PDS-S1", "Ensemble Smoothing", Prt_D, pds1->ens.Smooth);
1029 }
1030 if (pds1->f_hasProb) {
1031 Print ("PDS-S1", "Prob Category", Prt_D, pds1->prob.Cat);
1032 Print ("PDS-S1", "Prob Type", Prt_D, pds1->prob.Type);
1033 Print ("PDS-S1", "Prob lower", Prt_F, pds1->prob.lower);
1034 Print ("PDS-S1", "Prob upper", Prt_F, pds1->prob.upper);
1035 }
1036 if (pds1->f_hasCluster) {
1037 Print ("PDS-S1", "Cluster Ens Size", Prt_D, pds1->cluster.ensSize);
1038 Print ("PDS-S1", "Cluster Size", Prt_D, pds1->cluster.clusterSize);
1039 Print ("PDS-S1", "Cluster Number", Prt_D, pds1->cluster.Num);
1040 Print ("PDS-S1", "Cluster Method", Prt_D, pds1->cluster.Method);
1041 Print ("PDS-S1", "Cluster North Latitude", Prt_F, pds1->cluster.NorLat);
1042 Print ("PDS-S1", "Cluster South Latitude", Prt_F, pds1->cluster.SouLat);
1043 Print ("PDS-S1", "Cluster East Longitude", Prt_F, pds1->cluster.EasLon);
1044 Print ("PDS-S1", "Cluster West Longitude", Prt_F, pds1->cluster.WesLon);
1045 sprintf (buffer, "'%10s'", pds1->cluster.Member);
1046 Print ("PDS-S1", "Cluster Membership", Prt_S, buffer);
1047 }
1048 }
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 */
PrintGDS(gdsType * gds,int version)1082 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 Print ("GDS", "Number of Points", Prt_D, gds->numPts);
1094 switch (gds->projType) {
1095 case GS3_LATLON: /* 0 */
1096 if (version == 1) {
1097 Print ("GDS", "Projection Type", Prt_DS, GB1S2_LATLON,
1098 table31[0]);
1099 } else {
1100 Print ("GDS", "Projection Type", Prt_DS, gds->projType,
1101 table31[0]);
1102 }
1103 break;
1104 case GS3_MERCATOR: /* 10 */
1105 if (version == 1) {
1106 Print ("GDS", "Projection Type", Prt_DS, GB1S2_MERCATOR,
1107 table31[1]);
1108 } else if (version == -1) {
1109 Print ("GDS", "Projection Type", Prt_DS, TDLP_MERCATOR,
1110 table31[1]);
1111 } else {
1112 Print ("GDS", "Projection Type", Prt_DS, gds->projType,
1113 table31[1]);
1114 }
1115 break;
1116 case GS3_POLAR: /* 20 */
1117 if (version == 1) {
1118 Print ("GDS", "Projection Type", Prt_DS, GB1S2_POLAR, table31[2]);
1119 } else if (version == -1) {
1120 Print ("GDS", "Projection Type", Prt_DS, TDLP_POLAR, table31[2]);
1121 } else {
1122 Print ("GDS", "Projection Type", Prt_DS, gds->projType,
1123 table31[2]);
1124 }
1125 break;
1126 case GS3_LAMBERT: /* 30 */
1127 if (version == 1) {
1128 Print ("GDS", "Projection Type", Prt_DS, GB1S2_LAMBERT,
1129 table31[3]);
1130 } else if (version == -1) {
1131 Print ("GDS", "Projection Type", Prt_DS, TDLP_LAMBERT,
1132 table31[3]);
1133 } else {
1134 Print ("GDS", "Projection Type", Prt_DS, gds->projType,
1135 table31[3]);
1136 }
1137 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 Print ("GDS", "Projection Type", Prt_D, gds->projType);
1154 errSprintf ("Un-supported Map Projection %d\n", gds->projType);
1155 return -1;
1156 }
1157 if (gds->f_sphere) {
1158 Print ("GDS", "Shape of Earth", Prt_S, "sphere");
1159 Print ("GDS", "Radius", Prt_FS, gds->majEarth, "km");
1160 } else {
1161 Print ("GDS", "Shape of Earth", Prt_S, "oblate spheroid");
1162 Print ("GDS", "semi Major axis", Prt_FS, gds->majEarth, "km");
1163 Print ("GDS", "semi Minor axis", Prt_FS, gds->minEarth, "km");
1164 }
1165 Print ("GDS", "Nx (Number of points on parallel)", Prt_D, gds->Nx);
1166 Print ("GDS", "Ny (Number of points on meridian)", Prt_D, gds->Ny);
1167 Print ("GDS", "Lat1", Prt_F, gds->lat1);
1168 Print ("GDS", "Lon1", Prt_F, gds->lon1);
1169 if (gds->resFlag & GRIB2BIT_5) {
1170 Print ("GDS", "u/v vectors relative to", Prt_S, "grid");
1171 } else {
1172 Print ("GDS", "u/v vectors relative to", Prt_S, "easterly/northerly");
1173 }
1174 if (gds->projType == GS3_LATLON) {
1175 Print ("GDS", "Lat2", Prt_F, gds->lat2);
1176 Print ("GDS", "Lon2", Prt_F, gds->lon2);
1177 Print ("GDS", "Dx", Prt_FS, gds->Dx, "degrees");
1178 Print ("GDS", "Dy", Prt_FS, gds->Dy, "degrees");
1179 } else if (gds->projType == GS3_MERCATOR) {
1180 Print ("GDS", "Lat2", Prt_F, gds->lat2);
1181 Print ("GDS", "Lon2", Prt_F, gds->lon2);
1182 Print ("GDS", "Dx", Prt_FS, gds->Dx, "m");
1183 Print ("GDS", "Dy", Prt_FS, gds->Dy, "m");
1184 } else if ((gds->projType == GS3_POLAR)
1185 || (gds->projType == GS3_LAMBERT)) {
1186 Print ("GDS", "Dx", Prt_FS, gds->Dx, "m");
1187 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 ((gds->scan & GRIB2BIT_4) / GRIB2BIT_4));
1196 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 Print ("GDS", "Output grid, scan mode", Prt_DS, 64, "0100");
1203 Print ("GDS", "(.flt file grid), scan mode", Prt_DS, 0, "0000");
1204 Print ("GDS", "Output grid, scan i/x direction", Prt_S, "positive");
1205 Print ("GDS", "Output grid, scan j/y direction", Prt_S, "positive");
1206 Print ("GDS", "(.flt file grid), scan j/y direction", Prt_S, "negative");
1207 Print ("GDS", "Output grid, consecutive points in", Prt_S,
1208 "i/x direction");
1209 Print ("GDS", "Output grid, adjacent rows scan in", Prt_S,
1210 "same direction");
1211
1212 /* Meshlat/orient lon/scale lat have no meaning for lat/lon grids. */
1213 if (gds->projType != GS3_LATLON) {
1214 Print ("GDS", "MeshLat", Prt_F, gds->meshLat);
1215 Print ("GDS", "OrientLon", Prt_F, gds->orientLon);
1216 if ((gds->projType == GS3_POLAR) || (gds->projType == GS3_LAMBERT)) {
1217 if (gds->center & GRIB2BIT_1) {
1218 Print ("GDS", "Which pole is on the plane", Prt_S, "South");
1219 } else {
1220 Print ("GDS", "Which pole is on the plane", Prt_S, "North");
1221 }
1222 if (gds->center & GRIB2BIT_2) {
1223 Print ("GDS", "bi-polar projection", Prt_S, "Yes");
1224 } else {
1225 Print ("GDS", "bi-polar projection", Prt_S, "No");
1226 }
1227 }
1228 Print ("GDS", "Tangent Lat1", Prt_F, gds->scaleLat1);
1229 Print ("GDS", "Tangent Lat2", Prt_F, gds->scaleLat2);
1230 Print ("GDS", "Southern Lat", Prt_F, gds->southLat);
1231 Print ("GDS", "Southern Lon", Prt_F, gds->southLon);
1232 }
1233 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 */
PrintGridAttrib(gridAttribType * attrib,sChar decimal)1259 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 if ((attrib->packType == GS5_JPEG2000) ||
1279 (attrib->packType == GS5_JPEG2000_ORG)) {
1280 Print ("Info", "Packing that was used", Prt_DS, attrib->packType,
1281 "JPEG 2000");
1282 } else if ((attrib->packType == GS5_PNG) ||
1283 (attrib->packType == GS5_PNG_ORG)) {
1284 Print ("Info", "Packing that was used", Prt_DS, attrib->packType,
1285 "Portable Network Graphics (PNG)");
1286 } else {
1287 Print ("Info", "Packing that was used", Prt_DS, attrib->packType,
1288 Lookup (table50, sizeof (table50), attrib->packType));
1289 }
1290 /* Added next two 1/27/2006 because of questions from Val. */
1291 Print ("Info", "Decimal Scale Factor", Prt_D, attrib->DSF);
1292 Print ("Info", "Binary Scale Factor", Prt_D, attrib->ESF);
1293 Print ("Info", "Original field type", Prt_DS, attrib->fieldType,
1294 Lookup (table51, sizeof (table51), attrib->fieldType));
1295 Print ("Info", "Missing value management", Prt_DS, attrib->f_miss,
1296 Lookup (table55, sizeof (table55), attrib->f_miss));
1297 if (attrib->f_miss == 1) {
1298 Print ("Info", "Primary missing value", Prt_F,
1299 myRound (attrib->missPri, decimal));
1300 } else if (attrib->f_miss == 2) {
1301 Print ("Info", "Primary missing value", Prt_F,
1302 myRound (attrib->missPri, decimal));
1303 Print ("Info", "Secondary missing value", Prt_F,
1304 myRound (attrib->missSec, decimal));
1305 }
1306 Print ("Info", "Detected number of Missing", Prt_D, attrib->numMiss);
1307 if (attrib->f_maxmin) {
1308 Print ("Info", "Field minimum value", Prt_F,
1309 myRound (attrib->min, decimal));
1310 Print ("Info", "Field maximum value", Prt_F,
1311 myRound (attrib->max, decimal));
1312 }
1313 }
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 */
MetaPrintGDS(gdsType * gds,int version,char ** ans)1344 int MetaPrintGDS (gdsType *gds, int version, char **ans)
1345 {
1346 int ierr; /* The error code of a called routine */
1347
1348 if ((ierr = PrintGDS (gds, version)) != 0) {
1349 *ans = Print (NULL, NULL, Prt_NULL);
1350 preErrSprintf ("Print error Section 3\n");
1351 return ierr;
1352 }
1353 *ans = Print (NULL, NULL, Prt_NULL);
1354 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 */
MetaPrint(grib_MetaData * meta,char ** ans,sChar decimal,sChar f_unit)1385 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 if (meta->GribVersion == 1) {
1390 PrintPDS1 (&(meta->pds1), meta->comment, meta->center,
1391 meta->subcenter, f_unit, meta->unitName, meta->convert);
1392 } else if (meta->GribVersion == -1) {
1393 PrintPDS_TDLP (&(meta->pdsTdlp));
1394 } else {
1395 if ((ierr = PrintPDS2 (meta, f_unit)) != 0) {
1396 *ans = Print (NULL, NULL, Prt_NULL);
1397 preErrSprintf ("Print error in PDS for GRIB2\n");
1398 return ierr;
1399 }
1400 }
1401 if ((ierr = PrintGDS (&(meta->gds), meta->GribVersion)) != 0) {
1402 *ans = Print (NULL, NULL, Prt_NULL);
1403 preErrSprintf ("Print error Section 3\n");
1404 return ierr;
1405 }
1406 PrintGridAttrib (&(meta->gridAttrib), decimal);
1407 *ans = Print (NULL, NULL, Prt_NULL);
1408 return 0;
1409 }
1410