15 #define VERSION "v1.8.0.9i (12-03-04) Wesley Ebisuzaki\n\t\tDWD-tables 2,201-203 (8-19-2003) Helmut P. Frank\n\t\tspectral: Luis Kornblueh (MPI)"
20 * wgrib.c extract/inventory grib records
25 * 11/94 - v1.1: arbitary size grids, -i option
26 * 11/94 - v1.2: bug fixes, ieee option, more info
27 * 1/95 - v1.2.4: fix headers for SUN acc
28 * 2/95 - v1.2.5: add num_ave in -s listing
29 * 2/95 - v1.2.6: change %d to %ld
30 * 2/95 - v1.2.7: more output, added some polar stereographic support
31 * 2/95 - v1.2.8: max min format changed %f to %g, tidying up more info
32 * 3/95 - v1.3.0: fix bug with bitmap, allow numbers > UNDEFINED
33 * 3/95 - v1.3.1: print number of missing points (verbose)
34 * 3/95 - v1.3.2: -append option added
35 * 4/95 - v1.3.2a,b: more output, polar stereo support (-V option)
36 * 4/95 - v1.3.3: added ECMWF parameter table (prelim)
37 * 6/95 - v1.3.4: nxny from BDS rather than gds?
38 * 9/95 - v1.3.4d: speedup in grib write
39 * 11/95 - v1.3.4f: new ECMWF parameter table (from Mike Fiorino), EC logic
40 * 2/96 - v1.3.4g-h: prelim fix for GDS-less grib files
41 * 2/96 - v1.3.4i: faster missing(), -V: "pos n" -> "n" (field 2)
42 * 3/96 - v1.4: fix return code (!inventory), and short records near EOF
43 * 6/96 - v1.4.1a: faster grib->binary decode, updated ncep parameter table, mod. in clim. desc
44 * 7/96 - v1.5.0: parameter-table aware, -v option changed, added "comments"
45 * increased NTRY to 100 in seek_grib
46 * 11/96 - v1.5.0b: added ECMWF parameter table 128
47 * 1/97 - v1.5.0b2: if nxny != nx*ny { nx = nxny; ny = 1 }
48 * 3/97 - v1.5.0b5: added: -PDS -GDS, Lambert Conformal
49 * 3/97 - v1.5.0b6: added: -verf
50 * 4/97 - v1.5.0b7: added -PDS10, -GDS10 and enhanced -PDS -GDS
51 * 4/97 - v1.5.0b8: "bitmap missing x" -> "bitmap: x undef"
52 * 5/97 - v1.5.0b9: thinned grids meta data
53 * 5/97 - v1.5.0b10: changed 0hr fcst to anal for TR=10 and P1=P2=0
54 * 5/97 - v1.5.0b10: added -H option
55 * 6/97 - v1.5.0b12: thinned lat-long grids -V option
56 * 6/97 - v1.5.0b13: -4yr
57 * 6/97 - v1.5.0b14: fix century mark Y=100 not 0
58 * 7/97 - v1.5.0b15: add ncep opn grib table
59 * 12/97 - v1.6.1.a: made ncep_opn the default table
60 * 12/97 - v1.6.1.b: changed 03TOT to O3TOT in operational ncep table
61 * 1/98 - v1.6.2: added Arakawa E grid meta-data
62 * 1/98 - v1.6.2.1: added some mode data, Scan -> scan
63 * 4/98 - v1.6.2.4: reanalysis id code: subcenter==0 && process==180
64 * 5/98 - v1.6.2.5: fix -H code to write all of GDS
65 * 7/98 - v1.7: fix decoding bug for bitmap and no. bits > 24 (theoretical bug)
66 * 7/98 - v1.7.0.b1: add km to Mercator meta-data
67 * 5/99 - v1.7.2: bug with thinned grids & bitmaps (nxny != nx*ny)
68 * 5/99 - v1.7.3: updated NCEP opn grib table
69 * 8/99 - v1.7.3.1: updated level information
70 * 9/00 - v1.7.3.4a: check for missing grib file
71 * 2/01 - v1.7.3.5: handle data with precision greater than 31 bits
72 * 8/01 - vDWD : added DWD GRIB tables 201, 202, 203, Helmut P. Frank
73 * 9/01 - vDWD : added output "Triangular grid", Helmut P. Frank
74 * 9/01 - v1.7.4: merged Hemut P. Frank's changes to current wgrib source code
75 * 3/02 - vMPIfM: added support for spectral data type
76 * 4/02 - v1.8: merge vMPIfM changes, some fixes/generalizations
77 * 10/02 - v1.8.0.1: added cptec table 254
78 * 10/02 - v1.8.0.2: no test of grib test if no gds, level 117 redone
79 * 10/02 - v1.8.0.3: update ncep_opn grib and levels
80 * 11/02 - v1.8.0.3a: updated ncep_opn and ncep table 129
81 * 9/03 - v1.8.0.4: update dwd tables (Helmut P. Frank), -dwdgrib option
82 * 9/03 - v1.8.0.5: fix scan mode and change format
83 * 10/03 - v1.8.0.7: Changes from Norwegian Met. Inst (ec tab #131, ex_ext)
84 * 10/03 - v1.8.0.8: added -ncep_ens option
89 * MSEEK = I/O buffer size for seek_grib
93 #define BUFF_ALLOC0 40000
97 #define min(a,b) ((a) < (b) ? (a) : (b))
98 #define max(a,b) ((a) < (b) ? (b) : (a))
101 #ifndef DEF_T62_NCEP_TABLE
102 #define DEF_T62_NCEP_TABLE rean
104 enum Def_NCEP_Table def_ncep_table
= DEF_T62_NCEP_TABLE
;
108 int main(int argc
, char **argv
) {
110 unsigned char *buffer
;
112 double temp
, rmin
, rmax
;
113 int i
, nx
, ny
, file_arg
;
114 long int len_grib
, pos
= 0, nxny
, buffer_size
, n_dump
, count
= 1;
115 unsigned char *msg
, *pds
, *gds
, *bms
, *bds
, *pointer
;
116 FILE *input
, *dump_file
= NULL
;
118 enum {BINARY
, TEXT
, IEEE
, GRIB
, NONE
} output_type
= NONE
;
119 enum {DUMP_ALL
, DUMP_RECORD
, DUMP_POSITION
, DUMP_LIST
, INVENTORY
}
121 enum {none
, dwd
, simple
} header
= simple
;
124 int verbose
= 0, append
= 0, v_time
= 0, year_4
= 0, output_PDS_GDS
= 0;
125 int print_GDS
= 0, print_GDS10
= 0, print_PDS
= 0, print_PDS10
= 0;
126 char *dump_file_name
= "dump", open_parm
[3];
130 fprintf(stderr
, "\nPortable Grib decoder for %s etc.\n",
131 (def_ncep_table
== opn_nowarn
|| def_ncep_table
== opn
) ?
132 "NCEP Operations" : "NCEP/NCAR Reanalysis");
133 fprintf(stderr
, " it slices, dices %s\n", VERSION
);
134 fprintf(stderr
, " usage: %s [grib file] [options]\n\n", argv
[0]);
136 fprintf(stderr
, "Inventory/diagnostic-output selections\n");
137 fprintf(stderr
, " -s/-v short/verbose inventory\n");
138 fprintf(stderr
, " -V diagnostic output (not inventory)\n");
139 fprintf(stderr
, " (none) regular inventory\n");
141 fprintf(stderr
, " Options\n");
142 fprintf(stderr
, " -PDS/-PDS10 print PDS in hex/decimal\n");
143 fprintf(stderr
, " -GDS/-GDS10 print GDS in hex/decimal\n");
144 fprintf(stderr
, " -verf print forecast verification time\n");
145 fprintf(stderr
, " -ncep_opn/-ncep_rean default T62 NCEP grib table\n");
146 fprintf(stderr
, " -4yr print year using 4 digits\n");
147 fprintf(stderr
, " -min print minutes\n");
148 fprintf(stderr
, " -ncep_ens ensemble info encoded in ncep format\n");
150 fprintf(stderr
, "Decoding GRIB selection\n");
151 fprintf(stderr
, " -d [record number|all] decode record number\n");
152 fprintf(stderr
, " -p [byte position] decode record at byte position\n");
153 fprintf(stderr
, " -i decode controlled by stdin (inventory list)\n");
154 fprintf(stderr
, " (none) no decoding\n");
156 fprintf(stderr
, " Options\n");
157 fprintf(stderr
, " -text/-ieee/-grib/-bin convert to text/ieee/grib/bin (default)\n");
158 fprintf(stderr
, " -nh/-h output will have no headers/headers (default)\n");
159 fprintf(stderr
, " -dwdgrib output dwd headers, grib (do not append)\n");
160 fprintf(stderr
, " -H output will include PDS and GDS (-bin/-ieee only)\n");
161 fprintf(stderr
, " -append append to output file\n");
162 fprintf(stderr
, " -o [file] output file name, 'dump' is default\n");
166 for (i
= 1; i
< argc
; i
++) {
167 if (strcmp(argv
[i
],"-PDS") == 0) {
171 if (strcmp(argv
[i
],"-PDS10") == 0) {
175 if (strcmp(argv
[i
],"-GDS") == 0) {
179 if (strcmp(argv
[i
],"-GDS10") == 0) {
183 if (strcmp(argv
[i
],"-v") == 0) {
187 if (strcmp(argv
[i
],"-V") == 0) {
191 if (strcmp(argv
[i
],"-s") == 0) {
195 if (strcmp(argv
[i
],"-text") == 0) {
199 if (strcmp(argv
[i
],"-bin") == 0) {
200 output_type
= BINARY
;
203 if (strcmp(argv
[i
],"-ieee") == 0) {
207 if (strcmp(argv
[i
],"-grib") == 0) {
211 if (strcmp(argv
[i
],"-nh") == 0) {
215 if (strcmp(argv
[i
],"-h") == 0) {
219 if (strcmp(argv
[i
],"-dwdgrib") == 0) {
224 if (strcmp(argv
[i
],"-append") == 0) {
228 if (strcmp(argv
[i
],"-verf") == 0) {
232 if (strcmp(argv
[i
],"-d") == 0) {
233 if (strcmp(argv
[i
+1],"all") == 0) {
237 dump
= atol(argv
[i
+1]);
241 if (output_type
== NONE
) output_type
= BINARY
;
244 if (strcmp(argv
[i
],"-p") == 0) {
245 pos
= atol(argv
[i
+1]);
248 if (output_type
== NONE
) output_type
= BINARY
;
249 mode
= DUMP_POSITION
;
252 if (strcmp(argv
[i
],"-i") == 0) {
253 if (output_type
== NONE
) output_type
= BINARY
;
257 if (strcmp(argv
[i
],"-H") == 0) {
261 if (strcmp(argv
[i
],"-NH") == 0) {
265 if (strcmp(argv
[i
],"-4yr") == 0) {
269 if (strcmp(argv
[i
],"-ncep_opn") == 0) {
270 def_ncep_table
= opn_nowarn
;
273 if (strcmp(argv
[i
],"-ncep_rean") == 0) {
274 def_ncep_table
= rean_nowarn
;
277 if (strcmp(argv
[i
],"-o") == 0) {
278 dump_file_name
= argv
[i
+1];
282 if (strcmp(argv
[i
],"--v") == 0) {
283 printf("wgrib: %s\n", VERSION
);
286 if (strcmp(argv
[i
],"-min") == 0) {
290 if (strcmp(argv
[i
],"-ncep_ens") == 0) {
298 fprintf(stderr
,"argument: %s ????\n", argv
[i
]);
302 fprintf(stderr
,"no GRIB file to process\n");
305 if ((input
= fopen(argv
[file_arg
],"rb")) == NULL
) {
306 fprintf(stderr
,"could not open file: %s\n", argv
[file_arg
]);
310 if ((buffer
= (unsigned char *) malloc(BUFF_ALLOC0
)) == NULL
) {
311 fprintf(stderr
,"not enough memory\n");
313 buffer_size
= BUFF_ALLOC0
;
315 /* open output file */
316 if (mode
!= INVENTORY
) {
317 open_parm
[0] = append
? 'a' : 'w'; open_parm
[1] = 'b'; open_parm
[2] = '\0';
318 if (output_type
== TEXT
) open_parm
[1] = '\0';
320 if ((dump_file
= fopen(dump_file_name
,open_parm
)) == NULL
) {
321 fprintf(stderr
,"could not open dump file\n");
324 if (header
== dwd
&& output_type
== GRIB
) wrtieee_header(0, dump_file
);
327 /* skip dump - 1 records */
328 for (i
= 1; i
< dump
; i
++) {
329 msg
= seek_grib(input
, &pos
, &len_grib
, buffer
, MSEEK
);
331 fprintf(stderr
, "ran out of data or bad file\n");
336 if (dump
> 0) count
+= dump
- 1;
340 if (n_dump
== 1 && (mode
== DUMP_RECORD
|| mode
== DUMP_POSITION
)) break;
341 if (mode
== DUMP_LIST
) {
342 if (fgets(line
,sizeof(line
), stdin
) == NULL
) break;
343 line
[sizeof(line
) - 1] = 0;
344 if (sscanf(line
,"%ld:%ld:", &count
, &pos
) != 2) {
345 fprintf(stderr
,"bad input from stdin\n");
346 fprintf(stderr
," %s\n", line
);
351 msg
= seek_grib(input
, &pos
, &len_grib
, buffer
, MSEEK
);
353 if (mode
== INVENTORY
|| mode
== DUMP_ALL
) break;
354 fprintf(stderr
,"missing GRIB record(s)\n");
358 /* read all whole grib record */
359 if (len_grib
+ msg
- buffer
> buffer_size
) {
360 buffer_size
= len_grib
+ msg
- buffer
+ 1000;
361 buffer
= (unsigned char *) realloc((void *) buffer
, buffer_size
);
362 if (buffer
== NULL
) {
363 fprintf(stderr
,"ran out of memory\n");
367 read_grib(input
, pos
, len_grib
, buffer
);
369 /* parse grib message */
373 pointer
= pds
+ PDS_LEN(pds
);
375 printf("LEN_GRIB= 0x%x\n", len_grib
);
376 printf("PDS_LEN= 0x%x: at 0x%x\n", PDS_LEN(pds
),pds
-msg
);
378 if (PDS_HAS_GDS(pds
)) {
380 pointer
+= GDS_LEN(gds
);
382 printf("GDS_LEN= 0x%x: at 0x%x\n", GDS_LEN(gds
), gds
-msg
);
389 if (PDS_HAS_BMS(pds
)) {
391 pointer
+= BMS_LEN(bms
);
393 printf("BMS_LEN= 0x%x: at 0x%x\n", BMS_LEN(bms
),bms
-msg
);
401 pointer
+= BDS_LEN(bds
);
403 printf("BDS_LEN= 0x%x: at 0x%x\n", BDS_LEN(bds
),bds
-msg
);
407 printf("END_LEN= 0x%x: at 0x%x\n", 4,pointer
-msg
);
408 if (pointer
-msg
+4 != len_grib
) {
409 fprintf(stderr
,"Len of grib message is inconsistent.\n");
413 /* end section - "7777" in ascii */
414 if (pointer
[0] != 0x37 || pointer
[1] != 0x37 ||
415 pointer
[2] != 0x37 || pointer
[3] != 0x37) {
416 fprintf(stderr
,"\n\n missing end section\n");
417 fprintf(stderr
, "%2x %2x %2x %2x\n", pointer
[0], pointer
[1],
418 pointer
[2], pointer
[3]);
420 printf("ignoring missing end section\n");
426 /* figure out size of array */
428 GDS_grid(gds
, bds
, &nx
, &ny
, &nxny
);
430 else if (bms
!= NULL
) {
431 nxny
= nx
= BMS_nxny(bms
);
435 if (BDS_NumBits(bds
) == 0) {
437 fprintf(stderr
,"Missing GDS, constant record .. cannot "
438 "determine number of data points\n");
441 nxny
= nx
= BDS_NValues(bds
);
447 if (gds
&& ! GDS_Harmonic(gds
)) {
448 /* this grib check only works for simple packing */
449 /* turn off if harmonic */
450 if (BDS_NumBits(bds
) != 0) {
451 i
= BDS_NValues(bds
);
453 i
+= missing_points(BMS_bitmap(bms
),nxny
);
456 fprintf(stderr
,"grib header at record %ld: two values of nxny %ld %d\n",
458 fprintf(stderr
," LEN %d DataStart %d UnusedBits %d #Bits %d nxny %ld\n",
459 BDS_LEN(bds
), BDS_DataStart(bds
),BDS_UnusedBits(bds
),
460 BDS_NumBits(bds
), nxny
);
471 printf("%ld:%ld:d=", count
, pos
);
472 PDS_date(pds
,year_4
,v_time
);
473 printf(":%s:", k5toa(pds
));
475 if (verbose
== 0) printf("kpds5=%d:kpds6=%d:kpds7=%d:TR=%d:P1=%d:P2=%d:TimeU=%d:",
476 PDS_PARAM(pds
),PDS_KPDS6(pds
),PDS_KPDS7(pds
),
477 PDS_TimeRange(pds
),PDS_P1(pds
),PDS_P2(pds
),
478 PDS_ForecastTimeUnit(pds
));
479 levels(PDS_KPDS6(pds
), PDS_KPDS7(pds
),PDS_Center(pds
)); printf(":");
480 PDStimes(PDS_TimeRange(pds
),PDS_P1(pds
),PDS_P2(pds
),
481 PDS_ForecastTimeUnit(pds
));
482 if (PDS_Center(pds
) == ECMWF
) EC_ext(pds
,"",":");
483 ensemble(pds
, verbose
);
484 printf("NAve=%d",PDS_NumAve(pds
));
485 if (print_PDS
|| print_PDS10
) print_pds(pds
, print_PDS
, print_PDS10
, verbose
);
486 if (gds
&& (print_GDS
|| print_GDS10
)) print_gds(gds
, print_GDS
, print_GDS10
, verbose
);
489 else if (verbose
== 1) {
490 printf("%ld:%ld:D=", count
, pos
);
491 PDS_date(pds
, 1, v_time
);
492 printf(":%s:", k5toa(pds
));
493 levels(PDS_KPDS6(pds
), PDS_KPDS7(pds
), PDS_Center(pds
)); printf(":");
494 printf("kpds=%d,%d,%d:",
495 PDS_PARAM(pds
),PDS_KPDS6(pds
),PDS_KPDS7(pds
));
496 PDStimes(PDS_TimeRange(pds
),PDS_P1(pds
),PDS_P2(pds
),
497 PDS_ForecastTimeUnit(pds
));
498 if (PDS_Center(pds
) == ECMWF
) EC_ext(pds
,"",":");
499 ensemble(pds
, verbose
);
500 GDS_winds(gds
, verbose
);
501 printf("\"%s", k5_comments(pds
));
502 if (print_PDS
|| print_PDS10
) print_pds(pds
, print_PDS
, print_PDS10
, verbose
);
503 if (gds
&& (print_GDS
|| print_GDS10
)) print_gds(gds
, print_GDS
, print_GDS10
, verbose
);
506 else if (verbose
== 2) {
507 printf("rec %ld:%ld:date ", count
, pos
);
508 PDS_date(pds
, 1, v_time
);
509 printf(" %s kpds5=%d kpds6=%d kpds7=%d levels=(%d,%d) grid=%d ",
510 k5toa(pds
), PDS_PARAM(pds
), PDS_KPDS6(pds
), PDS_KPDS7(pds
),
511 PDS_LEVEL1(pds
), PDS_LEVEL2(pds
), PDS_Grid(pds
));
512 levels(PDS_KPDS6(pds
),PDS_KPDS7(pds
),PDS_Center(pds
));
515 if (PDS_Center(pds
) == ECMWF
) EC_ext(pds
,""," ");
516 ensemble(pds
, verbose
);
517 PDStimes(PDS_TimeRange(pds
),PDS_P1(pds
),PDS_P2(pds
),
518 PDS_ForecastTimeUnit(pds
));
520 printf(" bitmap: %d undef", missing_points(BMS_bitmap(bms
),nxny
));
521 printf("\n %s=%s\n", k5toa(pds
), k5_comments(pds
));
523 printf(" timerange %d P1 %d P2 %d TimeU %d nx %d ny %d GDS grid %d "
524 "num_in_ave %d missing %d\n",
525 PDS_TimeRange(pds
),PDS_P1(pds
),PDS_P2(pds
),
526 PDS_ForecastTimeUnit(pds
), nx
, ny
,
527 gds
== NULL
? -1 : GDS_DataType(gds
),
528 PDS_NumAve(pds
), PDS_NumMissing(pds
));
530 printf(" center %d subcenter %d process %d Table %d",
531 PDS_Center(pds
),PDS_Subcenter(pds
),PDS_Model(pds
),
533 GDS_winds(gds
, verbose
);
536 if (gds
&& GDS_LatLon(gds
) && nx
!= -1)
537 printf(" latlon: lat %f to %f by %f nxny %ld\n"
538 " long %f to %f by %f, (%d x %d) scan %d "
539 "mode %d bdsgrid %d\n",
540 0.001*GDS_LatLon_La1(gds
), 0.001*GDS_LatLon_La2(gds
),
541 0.001*GDS_LatLon_dy(gds
), nxny
, 0.001*GDS_LatLon_Lo1(gds
),
542 0.001*GDS_LatLon_Lo2(gds
), 0.001*GDS_LatLon_dx(gds
),
543 nx
, ny
, GDS_LatLon_scan(gds
), GDS_LatLon_mode(gds
),
545 else if (gds
&& GDS_LatLon(gds
) && nx
== -1) {
546 printf(" thinned latlon: lat %f to %f by %f nxny %ld\n"
547 " long %f to %f, %ld grid pts (%d x %d) scan %d"
548 " mode %d bdsgrid %d\n",
549 0.001*GDS_LatLon_La1(gds
), 0.001*GDS_LatLon_La2(gds
),
550 0.001*GDS_LatLon_dy(gds
), nxny
, 0.001*GDS_LatLon_Lo1(gds
),
551 0.001*GDS_LatLon_Lo2(gds
),
552 nxny
, nx
, ny
, GDS_LatLon_scan(gds
), GDS_LatLon_mode(gds
),
554 GDS_prt_thin_lon(gds
);
556 else if (gds
&& GDS_Gaussian(gds
) && nx
!= -1)
557 printf(" gaussian: lat %f to %f\n"
558 " long %f to %f by %f, (%d x %d) scan %d"
559 " mode %d bdsgrid %d\n",
560 0.001*GDS_LatLon_La1(gds
), 0.001*GDS_LatLon_La2(gds
),
561 0.001*GDS_LatLon_Lo1(gds
), 0.001*GDS_LatLon_Lo2(gds
),
562 0.001*GDS_LatLon_dx(gds
),
563 nx
, ny
, GDS_LatLon_scan(gds
), GDS_LatLon_mode(gds
),
565 else if (gds
&& GDS_Gaussian(gds
) && nx
== -1) {
566 printf(" thinned gaussian: lat %f to %f\n"
567 " lon %f %ld grid pts (%d x %d) scan %d"
568 " mode %d bdsgrid %d nlat:\n",
569 0.001*GDS_LatLon_La1(gds
), 0.001*GDS_LatLon_La2(gds
),
570 0.001*GDS_LatLon_Lo1(gds
),
571 nxny
, nx
, ny
, GDS_LatLon_scan(gds
), GDS_LatLon_mode(gds
),
573 GDS_prt_thin_lon(gds
);
575 else if (gds
&& GDS_Polar(gds
))
576 printf(" polar stereo: Lat1 %f Long1 %f Orient %f\n"
577 " %s pole (%d x %d) Dx %d Dy %d scan %d mode %d\n",
578 0.001*GDS_Polar_La1(gds
),0.001*GDS_Polar_Lo1(gds
),
579 0.001*GDS_Polar_Lov(gds
),
580 GDS_Polar_pole(gds
) == 0 ? "north" : "south", nx
,ny
,
581 GDS_Polar_Dx(gds
),GDS_Polar_Dy(gds
),
582 GDS_Polar_scan(gds
), GDS_Polar_mode(gds
));
583 else if (gds
&& GDS_Lambert(gds
))
584 printf(" Lambert Conf: Lat1 %f Lon1 %f Lov %f\n"
585 " Latin1 %f Latin2 %f LatSP %f LonSP %f\n"
586 " %s (%d x %d) Dx %f Dy %f scan %d mode %d\n",
587 0.001*GDS_Lambert_La1(gds
),0.001*GDS_Lambert_Lo1(gds
),
588 0.001*GDS_Lambert_Lov(gds
),
589 0.001*GDS_Lambert_Latin1(gds
), 0.001*GDS_Lambert_Latin2(gds
),
590 0.001*GDS_Lambert_LatSP(gds
), 0.001*GDS_Lambert_LonSP(gds
),
591 GDS_Lambert_NP(gds
) ? "North Pole": "South Pole",
592 GDS_Lambert_nx(gds
), GDS_Lambert_ny(gds
),
593 0.001*GDS_Lambert_dx(gds
), 0.001*GDS_Lambert_dy(gds
),
594 GDS_Lambert_scan(gds
), GDS_Lambert_mode(gds
));
595 else if (gds
&& GDS_Mercator(gds
))
596 printf(" Mercator: lat %f to %f by %f km nxny %ld\n"
597 " long %f to %f by %f km, (%d x %d) scan %d"
598 " mode %d Latin %f bdsgrid %d\n",
599 0.001*GDS_Merc_La1(gds
), 0.001*GDS_Merc_La2(gds
),
600 0.001*GDS_Merc_dy(gds
), nxny
, 0.001*GDS_Merc_Lo1(gds
),
601 0.001*GDS_Merc_Lo2(gds
), 0.001*GDS_Merc_dx(gds
),
602 nx
, ny
, GDS_Merc_scan(gds
), GDS_Merc_mode(gds
),
603 0.001*GDS_Merc_Latin(gds
), BDS_Grid(bds
));
604 else if (gds
&& GDS_ssEgrid(gds
))
605 printf(" Semi-staggered Arakawa E-Grid: lat0 %f lon0 %f nxny %d\n"
606 " dLat %f dLon %f (%d x %d) scan %d mode %d\n",
607 0.001*GDS_ssEgrid_La1(gds
), 0.001*GDS_ssEgrid_Lo1(gds
),
608 GDS_ssEgrid_n(gds
)*GDS_ssEgrid_n_dum(gds
),
609 0.001*GDS_ssEgrid_dj(gds
), 0.001*GDS_ssEgrid_di(gds
),
610 GDS_ssEgrid_Lo2(gds
), GDS_ssEgrid_La2(gds
),
611 GDS_ssEgrid_scan(gds
), GDS_ssEgrid_mode(gds
));
612 else if (gds
&& GDS_ss2dEgrid(gds
))
613 printf(" Semi-staggered Arakawa E-Grid (2D): lat0 %f lon0 %f nxny %d\n"
614 " dLat %f dLon %f (tlm0d %f tph0d %f) scan %d mode %d\n",
615 0.001*GDS_ss2dEgrid_La1(gds
), 0.001*GDS_ss2dEgrid_Lo1(gds
),
616 GDS_ss2dEgrid_nx(gds
)*GDS_ss2dEgrid_ny(gds
),
617 0.001*GDS_ss2dEgrid_dj(gds
), 0.001*GDS_ss2dEgrid_di(gds
),
618 0.001*GDS_ss2dEgrid_Lo2(gds
), 0.001*GDS_ss2dEgrid_La2(gds
),
619 GDS_ss2dEgrid_scan(gds
), GDS_ss2dEgrid_mode(gds
));
620 else if (gds
&& GDS_fEgrid(gds
))
621 printf(" filled Arakawa E-Grid: lat0 %f lon0 %f nxny %d\n"
622 " dLat %f dLon %f (%d x %d) scan %d mode %d\n",
623 0.001*GDS_fEgrid_La1(gds
), 0.001*GDS_fEgrid_Lo1(gds
),
624 GDS_fEgrid_n(gds
)*GDS_fEgrid_n_dum(gds
),
625 0.001*GDS_fEgrid_dj(gds
), 0.001*GDS_fEgrid_di(gds
),
626 GDS_fEgrid_Lo2(gds
), GDS_fEgrid_La2(gds
),
627 GDS_fEgrid_scan(gds
), GDS_fEgrid_mode(gds
));
628 else if (gds
&& GDS_RotLL(gds
))
629 printf(" rotated LatLon grid lat %f to %f lon %f to %f\n"
630 " nxny %ld (%d x %d) dx %d dy %d scan %d mode %d\n"
631 " transform: south pole lat %f lon %f rot angle %f\n",
632 0.001*GDS_RotLL_La1(gds
), 0.001*GDS_RotLL_La2(gds
),
633 0.001*GDS_RotLL_Lo1(gds
), 0.001*GDS_RotLL_Lo2(gds
),
634 nxny
, GDS_RotLL_nx(gds
), GDS_RotLL_ny(gds
),
635 GDS_RotLL_dx(gds
), GDS_RotLL_dy(gds
),
636 GDS_RotLL_scan(gds
), GDS_RotLL_mode(gds
),
637 0.001*GDS_RotLL_LaSP(gds
), 0.001*GDS_RotLL_LoSP(gds
),
638 GDS_RotLL_RotAng(gds
) );
639 else if (gds
&& GDS_Gnomonic(gds
))
640 printf(" Gnomonic grid\n");
641 else if (gds
&& GDS_Harmonic(gds
))
642 printf(" Harmonic (spectral): pentagonal spectral truncation: nj %d nk %d nm %d\n",
643 GDS_Harmonic_nj(gds
), GDS_Harmonic_nk(gds
),
644 GDS_Harmonic_nm(gds
));
645 if (gds
&& GDS_Harmonic_type(gds
) == 1)
646 printf(" Associated Legendre polynomials\n");
647 else if (gds
&& GDS_Triangular(gds
))
648 printf(" Triangular grid: nd %d ni %d (= 2^%d x 3^%d)\n",
649 GDS_Triangular_nd(gds
), GDS_Triangular_ni(gds
),
650 GDS_Triangular_ni2(gds
), GDS_Triangular_ni3(gds
) );
651 if (print_PDS
|| print_PDS10
)
652 print_pds(pds
, print_PDS
, print_PDS10
, verbose
);
653 if (gds
&& (print_GDS
|| print_GDS10
))
654 print_gds(gds
, print_GDS
, print_GDS10
, verbose
);
657 if (mode
!= INVENTORY
&& output_type
== GRIB
) {
658 if (header
== dwd
) wrtieee_header((int) len_grib
, dump_file
);
659 fwrite((void *) msg
, sizeof(char), len_grib
, dump_file
);
660 if (header
== dwd
) wrtieee_header((int) len_grib
, dump_file
);
664 if ((mode
!= INVENTORY
&& output_type
!= GRIB
) || verbose
> 1) {
665 /* decode numeric data */
667 if ((array
= (float *) malloc(sizeof(float) * nxny
)) == NULL
) {
668 fprintf(stderr
,"memory problems\n");
672 temp
= int_power(10.0, - PDS_DecimalScale(pds
));
674 BDS_unpack(array
, bds
, BMS_bitmap(bms
), BDS_NumBits(bds
), nxny
,
675 temp
*BDS_RefValue(bds
),temp
*int_power(2.0, BDS_BinScale(bds
)));
680 for (i
= 0; i
< nxny
; i
++) {
681 if (fabs(array
[i
]-UNDEFINED
) > 0.0001*UNDEFINED
) {
682 rmin
= min(rmin
,array
[i
]);
683 rmax
= max(rmax
,array
[i
]);
686 printf(" min/max data %g %g num bits %d "
687 " BDS_Ref %g DecScale %d BinScale %d\n",
688 rmin
, rmax
, BDS_NumBits(bds
), BDS_RefValue(bds
),
689 PDS_DecimalScale(pds
), BDS_BinScale(bds
));
692 if (mode
!= INVENTORY
&& output_type
!= GRIB
) {
694 if (output_PDS_GDS
== 1) {
695 /* insert code here */
696 if (output_type
== BINARY
|| output_type
== IEEE
) {
698 i
= PDS_LEN(pds
) + 4;
699 if (header
== simple
&& output_type
== BINARY
)
700 fwrite((void *) &i
, sizeof(int), 1, dump_file
);
701 if (header
== simple
&& output_type
== IEEE
) wrtieee_header(i
, dump_file
);
702 fwrite((void *) "PDS ", 1, 4, dump_file
);
703 fwrite((void *) pds
, 1, i
- 4, dump_file
);
704 if (header
== simple
&& output_type
== BINARY
)
705 fwrite((void *) &i
, sizeof(int), 1, dump_file
);
706 if (header
== simple
&& output_type
== IEEE
) wrtieee_header(i
, dump_file
);
709 i
= (gds
) ? GDS_LEN(gds
) + 4 : 4;
710 if (header
== simple
&& output_type
== BINARY
)
711 fwrite((void *) &i
, sizeof(int), 1, dump_file
);
712 if (header
== simple
&& output_type
== IEEE
) wrtieee_header(i
, dump_file
);
713 fwrite((void *) "GDS ", 1, 4, dump_file
);
714 if (gds
) fwrite((void *) gds
, 1, i
- 4, dump_file
);
715 if (header
== simple
&& output_type
== BINARY
)
716 fwrite((void *) &i
, sizeof(int), 1, dump_file
);
717 if (header
== simple
&& output_type
== IEEE
) wrtieee_header(i
, dump_file
);
721 if (output_type
== BINARY
) {
722 i
= nxny
* sizeof(float);
723 if (header
== simple
) fwrite((void *) &i
, sizeof(int), 1, dump_file
);
724 fwrite((void *) array
, sizeof(float), nxny
, dump_file
);
725 if (header
== simple
) fwrite((void *) &i
, sizeof(int), 1, dump_file
);
727 else if (output_type
== IEEE
) {
728 wrtieee(array
, nxny
, header
, dump_file
);
730 else if (output_type
== TEXT
) {
731 /* number of points in grid */
732 if (header
== simple
) {
733 if (nx
<= 0 || ny
<= 0 || nxny
!= nx
*ny
) {
734 fprintf(dump_file
, "%ld %d\n", nxny
, 1);
737 fprintf(dump_file
, "%d %d\n", nx
, ny
);
740 for (i
= 0; i
< nxny
; i
++) {
741 fprintf(dump_file
,"%g\n", array
[i
]);
747 if (verbose
> 0) printf("\n");
754 if (mode
!= INVENTORY
) {
755 if (header
== dwd
&& output_type
== GRIB
) wrtieee_header(0, dump_file
);
756 if (ferror(dump_file
)) {
757 fprintf(stderr
,"error writing %s\n",dump_file_name
);
762 return (return_code
);
765 void print_pds(unsigned char *pds
, int print_PDS
, int print_PDS10
, int verbose
) {
770 if (print_PDS
&& verbose
< 2) {
772 for (i
= 0; i
< j
; i
++) {
773 printf("%2.2x", (int) pds
[i
]);
776 if (print_PDS10
&& verbose
< 2) {
778 for (i
= 0; i
< j
; i
++) {
779 printf(" %d", (int) pds
[i
]);
785 printf(" PDS(1..%d)=",j
);
786 for (i
= 0; i
< j
; i
++) {
787 if (i
% 20 == 0) printf("\n %4d:",i
+1);
788 printf(" %3.2x", (int) pds
[i
]);
793 printf(" PDS10(1..%d)=",j
);
794 for (i
= 0; i
< j
; i
++) {
795 if (i
% 20 == 0) printf("\n %4d:",i
+1);
796 printf(" %3d", (int) pds
[i
]);
803 void print_gds(unsigned char *gds
, int print_GDS
, int print_GDS10
, int verbose
) {
808 if (print_GDS
&& verbose
< 2) {
810 for (i
= 0; i
< j
; i
++) {
811 printf("%2.2x", (int) gds
[i
]);
814 if (print_GDS10
&& verbose
< 2) {
816 for (i
= 0; i
< j
; i
++) {
817 printf(" %d", (int) gds
[i
]);
823 printf(" GDS(1..%d)=",j
);
824 for (i
= 0; i
< j
; i
++) {
825 if (i
% 20 == 0) printf("\n %4d:",i
+1);
826 printf(" %3.2x", (int) gds
[i
]);
831 printf(" GDS10(1..%d)=",j
);
832 for (i
= 0; i
< j
; i
++) {
833 if (i
% 20 == 0) printf("\n %4d:",i
+1);
834 printf(" %3d", (int) gds
[i
]);