PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/wrfv2_fire/external/io_grib1/WGRIB/wgrib_main.c

http://github.com/jbeezley/wrf-fire
C | 839 lines | 700 code | 54 blank | 85 comment | 353 complexity | 28179927f1ebd94e70ca7797f9e1b197 MD5 | raw file
Possible License(s): AGPL-1.0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stddef.h>
  5. #include <math.h>
  6. #include <float.h>
  7. #include "pds4.h"
  8. #include "gds.h"
  9. #include "bms.h"
  10. #include "bds.h"
  11. #include "cnames.h"
  12. #include "grib.h"
  13. #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)"
  14. #define CHECK_GRIB
  15. /*
  16. * wgrib.c extract/inventory grib records
  17. *
  18. * Wesley Ebisuzaki
  19. *
  20. * 11/94 - v1.0
  21. * 11/94 - v1.1: arbitary size grids, -i option
  22. * 11/94 - v1.2: bug fixes, ieee option, more info
  23. * 1/95 - v1.2.4: fix headers for SUN acc
  24. * 2/95 - v1.2.5: add num_ave in -s listing
  25. * 2/95 - v1.2.6: change %d to %ld
  26. * 2/95 - v1.2.7: more output, added some polar stereographic support
  27. * 2/95 - v1.2.8: max min format changed %f to %g, tidying up more info
  28. * 3/95 - v1.3.0: fix bug with bitmap, allow numbers > UNDEFINED
  29. * 3/95 - v1.3.1: print number of missing points (verbose)
  30. * 3/95 - v1.3.2: -append option added
  31. * 4/95 - v1.3.2a,b: more output, polar stereo support (-V option)
  32. * 4/95 - v1.3.3: added ECMWF parameter table (prelim)
  33. * 6/95 - v1.3.4: nxny from BDS rather than gds?
  34. * 9/95 - v1.3.4d: speedup in grib write
  35. * 11/95 - v1.3.4f: new ECMWF parameter table (from Mike Fiorino), EC logic
  36. * 2/96 - v1.3.4g-h: prelim fix for GDS-less grib files
  37. * 2/96 - v1.3.4i: faster missing(), -V: "pos n" -> "n" (field 2)
  38. * 3/96 - v1.4: fix return code (!inventory), and short records near EOF
  39. * 6/96 - v1.4.1a: faster grib->binary decode, updated ncep parameter table, mod. in clim. desc
  40. * 7/96 - v1.5.0: parameter-table aware, -v option changed, added "comments"
  41. * increased NTRY to 100 in seek_grib
  42. * 11/96 - v1.5.0b: added ECMWF parameter table 128
  43. * 1/97 - v1.5.0b2: if nxny != nx*ny { nx = nxny; ny = 1 }
  44. * 3/97 - v1.5.0b5: added: -PDS -GDS, Lambert Conformal
  45. * 3/97 - v1.5.0b6: added: -verf
  46. * 4/97 - v1.5.0b7: added -PDS10, -GDS10 and enhanced -PDS -GDS
  47. * 4/97 - v1.5.0b8: "bitmap missing x" -> "bitmap: x undef"
  48. * 5/97 - v1.5.0b9: thinned grids meta data
  49. * 5/97 - v1.5.0b10: changed 0hr fcst to anal for TR=10 and P1=P2=0
  50. * 5/97 - v1.5.0b10: added -H option
  51. * 6/97 - v1.5.0b12: thinned lat-long grids -V option
  52. * 6/97 - v1.5.0b13: -4yr
  53. * 6/97 - v1.5.0b14: fix century mark Y=100 not 0
  54. * 7/97 - v1.5.0b15: add ncep opn grib table
  55. * 12/97 - v1.6.1.a: made ncep_opn the default table
  56. * 12/97 - v1.6.1.b: changed 03TOT to O3TOT in operational ncep table
  57. * 1/98 - v1.6.2: added Arakawa E grid meta-data
  58. * 1/98 - v1.6.2.1: added some mode data, Scan -> scan
  59. * 4/98 - v1.6.2.4: reanalysis id code: subcenter==0 && process==180
  60. * 5/98 - v1.6.2.5: fix -H code to write all of GDS
  61. * 7/98 - v1.7: fix decoding bug for bitmap and no. bits > 24 (theoretical bug)
  62. * 7/98 - v1.7.0.b1: add km to Mercator meta-data
  63. * 5/99 - v1.7.2: bug with thinned grids & bitmaps (nxny != nx*ny)
  64. * 5/99 - v1.7.3: updated NCEP opn grib table
  65. * 8/99 - v1.7.3.1: updated level information
  66. * 9/00 - v1.7.3.4a: check for missing grib file
  67. * 2/01 - v1.7.3.5: handle data with precision greater than 31 bits
  68. * 8/01 - vDWD : added DWD GRIB tables 201, 202, 203, Helmut P. Frank
  69. * 9/01 - vDWD : added output "Triangular grid", Helmut P. Frank
  70. * 9/01 - v1.7.4: merged Hemut P. Frank's changes to current wgrib source code
  71. * 3/02 - vMPIfM: added support for spectral data type
  72. * 4/02 - v1.8: merge vMPIfM changes, some fixes/generalizations
  73. * 10/02 - v1.8.0.1: added cptec table 254
  74. * 10/02 - v1.8.0.2: no test of grib test if no gds, level 117 redone
  75. * 10/02 - v1.8.0.3: update ncep_opn grib and levels
  76. * 11/02 - v1.8.0.3a: updated ncep_opn and ncep table 129
  77. * 9/03 - v1.8.0.4: update dwd tables (Helmut P. Frank), -dwdgrib option
  78. * 9/03 - v1.8.0.5: fix scan mode and change format
  79. * 10/03 - v1.8.0.7: Changes from Norwegian Met. Inst (ec tab #131, ex_ext)
  80. * 10/03 - v1.8.0.8: added -ncep_ens option
  81. *
  82. */
  83. /*
  84. * MSEEK = I/O buffer size for seek_grib
  85. */
  86. #define MSEEK 1024
  87. #define BUFF_ALLOC0 40000
  88. #ifndef min
  89. #define min(a,b) ((a) < (b) ? (a) : (b))
  90. #define max(a,b) ((a) < (b) ? (b) : (a))
  91. #endif
  92. #ifndef DEF_T62_NCEP_TABLE
  93. #define DEF_T62_NCEP_TABLE rean
  94. #endif
  95. enum Def_NCEP_Table def_ncep_table = DEF_T62_NCEP_TABLE;
  96. int minute = 0;
  97. int ncep_ens = 0;
  98. int main(int argc, char **argv) {
  99. unsigned char *buffer;
  100. float *array;
  101. double temp, rmin, rmax;
  102. int i, nx, ny, file_arg;
  103. long int len_grib, pos = 0, nxny, buffer_size, n_dump, count = 1;
  104. unsigned char *msg, *pds, *gds, *bms, *bds, *pointer;
  105. FILE *input, *dump_file = NULL;
  106. char line[200];
  107. enum {BINARY, TEXT, IEEE, GRIB, NONE} output_type = NONE;
  108. enum {DUMP_ALL, DUMP_RECORD, DUMP_POSITION, DUMP_LIST, INVENTORY}
  109. mode = INVENTORY;
  110. enum {none, dwd, simple} header = simple;
  111. long int dump = -1;
  112. int verbose = 0, append = 0, v_time = 0, year_4 = 0, output_PDS_GDS = 0;
  113. int print_GDS = 0, print_GDS10 = 0, print_PDS = 0, print_PDS10 = 0;
  114. char *dump_file_name = "dump", open_parm[3];
  115. int return_code = 0;
  116. if (argc == 1) {
  117. fprintf(stderr, "\nPortable Grib decoder for %s etc.\n",
  118. (def_ncep_table == opn_nowarn || def_ncep_table == opn) ?
  119. "NCEP Operations" : "NCEP/NCAR Reanalysis");
  120. fprintf(stderr, " it slices, dices %s\n", VERSION);
  121. fprintf(stderr, " usage: %s [grib file] [options]\n\n", argv[0]);
  122. fprintf(stderr, "Inventory/diagnostic-output selections\n");
  123. fprintf(stderr, " -s/-v short/verbose inventory\n");
  124. fprintf(stderr, " -V diagnostic output (not inventory)\n");
  125. fprintf(stderr, " (none) regular inventory\n");
  126. fprintf(stderr, " Options\n");
  127. fprintf(stderr, " -PDS/-PDS10 print PDS in hex/decimal\n");
  128. fprintf(stderr, " -GDS/-GDS10 print GDS in hex/decimal\n");
  129. fprintf(stderr, " -verf print forecast verification time\n");
  130. fprintf(stderr, " -ncep_opn/-ncep_rean default T62 NCEP grib table\n");
  131. fprintf(stderr, " -4yr print year using 4 digits\n");
  132. fprintf(stderr, " -min print minutes\n");
  133. fprintf(stderr, " -ncep_ens ensemble info encoded in ncep format\n");
  134. fprintf(stderr, "Decoding GRIB selection\n");
  135. fprintf(stderr, " -d [record number|all] decode record number\n");
  136. fprintf(stderr, " -p [byte position] decode record at byte position\n");
  137. fprintf(stderr, " -i decode controlled by stdin (inventory list)\n");
  138. fprintf(stderr, " (none) no decoding\n");
  139. fprintf(stderr, " Options\n");
  140. fprintf(stderr, " -text/-ieee/-grib/-bin convert to text/ieee/grib/bin (default)\n");
  141. fprintf(stderr, " -nh/-h output will have no headers/headers (default)\n");
  142. fprintf(stderr, " -dwdgrib output dwd headers, grib (do not append)\n");
  143. fprintf(stderr, " -H output will include PDS and GDS (-bin/-ieee only)\n");
  144. fprintf(stderr, " -append append to output file\n");
  145. fprintf(stderr, " -o [file] output file name, 'dump' is default\n");
  146. exit(8);
  147. }
  148. file_arg = 0;
  149. for (i = 1; i < argc; i++) {
  150. if (strcmp(argv[i],"-PDS") == 0) {
  151. print_PDS = 1;
  152. continue;
  153. }
  154. if (strcmp(argv[i],"-PDS10") == 0) {
  155. print_PDS10 = 1;
  156. continue;
  157. }
  158. if (strcmp(argv[i],"-GDS") == 0) {
  159. print_GDS = 1;
  160. continue;
  161. }
  162. if (strcmp(argv[i],"-GDS10") == 0) {
  163. print_GDS10 = 1;
  164. continue;
  165. }
  166. if (strcmp(argv[i],"-v") == 0) {
  167. verbose = 1;
  168. continue;
  169. }
  170. if (strcmp(argv[i],"-V") == 0) {
  171. verbose = 2;
  172. continue;
  173. }
  174. if (strcmp(argv[i],"-s") == 0) {
  175. verbose = -1;
  176. continue;
  177. }
  178. if (strcmp(argv[i],"-text") == 0) {
  179. output_type = TEXT;
  180. continue;
  181. }
  182. if (strcmp(argv[i],"-bin") == 0) {
  183. output_type = BINARY;
  184. continue;
  185. }
  186. if (strcmp(argv[i],"-ieee") == 0) {
  187. output_type = IEEE;
  188. continue;
  189. }
  190. if (strcmp(argv[i],"-grib") == 0) {
  191. output_type = GRIB;
  192. continue;
  193. }
  194. if (strcmp(argv[i],"-nh") == 0) {
  195. header = none;
  196. continue;
  197. }
  198. if (strcmp(argv[i],"-h") == 0) {
  199. header = simple;
  200. continue;
  201. }
  202. if (strcmp(argv[i],"-dwdgrib") == 0) {
  203. header = dwd;
  204. output_type = GRIB;
  205. continue;
  206. }
  207. if (strcmp(argv[i],"-append") == 0) {
  208. append = 1;
  209. continue;
  210. }
  211. if (strcmp(argv[i],"-verf") == 0) {
  212. v_time = 1;
  213. continue;
  214. }
  215. if (strcmp(argv[i],"-d") == 0) {
  216. if (strcmp(argv[i+1],"all") == 0) {
  217. mode = DUMP_ALL;
  218. }
  219. else {
  220. dump = atol(argv[i+1]);
  221. mode = DUMP_RECORD;
  222. }
  223. i++;
  224. if (output_type == NONE) output_type = BINARY;
  225. continue;
  226. }
  227. if (strcmp(argv[i],"-p") == 0) {
  228. pos = atol(argv[i+1]);
  229. i++;
  230. dump = 1;
  231. if (output_type == NONE) output_type = BINARY;
  232. mode = DUMP_POSITION;
  233. continue;
  234. }
  235. if (strcmp(argv[i],"-i") == 0) {
  236. if (output_type == NONE) output_type = BINARY;
  237. mode = DUMP_LIST;
  238. continue;
  239. }
  240. if (strcmp(argv[i],"-H") == 0) {
  241. output_PDS_GDS = 1;
  242. continue;
  243. }
  244. if (strcmp(argv[i],"-NH") == 0) {
  245. output_PDS_GDS = 0;
  246. continue;
  247. }
  248. if (strcmp(argv[i],"-4yr") == 0) {
  249. year_4 = 1;
  250. continue;
  251. }
  252. if (strcmp(argv[i],"-ncep_opn") == 0) {
  253. def_ncep_table = opn_nowarn;
  254. continue;
  255. }
  256. if (strcmp(argv[i],"-ncep_rean") == 0) {
  257. def_ncep_table = rean_nowarn;
  258. continue;
  259. }
  260. if (strcmp(argv[i],"-o") == 0) {
  261. dump_file_name = argv[i+1];
  262. i++;
  263. continue;
  264. }
  265. if (strcmp(argv[i],"--v") == 0) {
  266. printf("wgrib: %s\n", VERSION);
  267. exit(0);
  268. }
  269. if (strcmp(argv[i],"-min") == 0) {
  270. minute = 1;
  271. continue;
  272. }
  273. if (strcmp(argv[i],"-ncep_ens") == 0) {
  274. ncep_ens = 1;
  275. continue;
  276. }
  277. if (file_arg == 0) {
  278. file_arg = i;
  279. }
  280. else {
  281. fprintf(stderr,"argument: %s ????\n", argv[i]);
  282. }
  283. }
  284. if (file_arg == 0) {
  285. fprintf(stderr,"no GRIB file to process\n");
  286. exit(8);
  287. }
  288. if ((input = fopen(argv[file_arg],"rb")) == NULL) {
  289. fprintf(stderr,"could not open file: %s\n", argv[file_arg]);
  290. exit(7);
  291. }
  292. if ((buffer = (unsigned char *) malloc(BUFF_ALLOC0)) == NULL) {
  293. fprintf(stderr,"not enough memory\n");
  294. }
  295. buffer_size = BUFF_ALLOC0;
  296. /* open output file */
  297. if (mode != INVENTORY) {
  298. open_parm[0] = append ? 'a' : 'w'; open_parm[1] = 'b'; open_parm[2] = '\0';
  299. if (output_type == TEXT) open_parm[1] = '\0';
  300. if ((dump_file = fopen(dump_file_name,open_parm)) == NULL) {
  301. fprintf(stderr,"could not open dump file\n");
  302. exit(8);
  303. }
  304. if (header == dwd && output_type == GRIB) wrtieee_header(0, dump_file);
  305. }
  306. /* skip dump - 1 records */
  307. for (i = 1; i < dump; i++) {
  308. msg = seek_grib(input, &pos, &len_grib, buffer, MSEEK);
  309. if (msg == NULL) {
  310. fprintf(stderr, "ran out of data or bad file\n");
  311. exit(8);
  312. }
  313. pos += len_grib;
  314. }
  315. if (dump > 0) count += dump - 1;
  316. n_dump = 0;
  317. for (;;) {
  318. if (n_dump == 1 && (mode == DUMP_RECORD || mode == DUMP_POSITION)) break;
  319. if (mode == DUMP_LIST) {
  320. if (fgets(line,sizeof(line), stdin) == NULL) break;
  321. line[sizeof(line) - 1] = 0;
  322. if (sscanf(line,"%ld:%ld:", &count, &pos) != 2) {
  323. fprintf(stderr,"bad input from stdin\n");
  324. fprintf(stderr," %s\n", line);
  325. exit(8);
  326. }
  327. }
  328. msg = seek_grib(input, &pos, &len_grib, buffer, MSEEK);
  329. if (msg == NULL) {
  330. if (mode == INVENTORY || mode == DUMP_ALL) break;
  331. fprintf(stderr,"missing GRIB record(s)\n");
  332. exit(8);
  333. }
  334. /* read all whole grib record */
  335. if (len_grib + msg - buffer > buffer_size) {
  336. buffer_size = len_grib + msg - buffer + 1000;
  337. buffer = (unsigned char *) realloc((void *) buffer, buffer_size);
  338. if (buffer == NULL) {
  339. fprintf(stderr,"ran out of memory\n");
  340. exit(8);
  341. }
  342. }
  343. read_grib(input, pos, len_grib, buffer);
  344. /* parse grib message */
  345. msg = buffer;
  346. pds = (msg + 8);
  347. pointer = pds + PDS_LEN(pds);
  348. #ifdef DEBUG
  349. printf("LEN_GRIB= 0x%x\n", len_grib);
  350. printf("PDS_LEN= 0x%x: at 0x%x\n", PDS_LEN(pds),pds-msg);
  351. #endif
  352. if (PDS_HAS_GDS(pds)) {
  353. gds = pointer;
  354. pointer += GDS_LEN(gds);
  355. #ifdef DEBUG
  356. printf("GDS_LEN= 0x%x: at 0x%x\n", GDS_LEN(gds), gds-msg);
  357. #endif
  358. }
  359. else {
  360. gds = NULL;
  361. }
  362. if (PDS_HAS_BMS(pds)) {
  363. bms = pointer;
  364. pointer += BMS_LEN(bms);
  365. #ifdef DEBUG
  366. printf("BMS_LEN= 0x%x: at 0x%x\n", BMS_LEN(bms),bms-msg);
  367. #endif
  368. }
  369. else {
  370. bms = NULL;
  371. }
  372. bds = pointer;
  373. pointer += BDS_LEN(bds);
  374. #ifdef DEBUG
  375. printf("BDS_LEN= 0x%x: at 0x%x\n", BDS_LEN(bds),bds-msg);
  376. #endif
  377. #ifdef DEBUG
  378. printf("END_LEN= 0x%x: at 0x%x\n", 4,pointer-msg);
  379. if (pointer-msg+4 != len_grib) {
  380. fprintf(stderr,"Len of grib message is inconsistent.\n");
  381. }
  382. #endif
  383. /* end section - "7777" in ascii */
  384. if (pointer[0] != 0x37 || pointer[1] != 0x37 ||
  385. pointer[2] != 0x37 || pointer[3] != 0x37) {
  386. fprintf(stderr,"\n\n missing end section\n");
  387. fprintf(stderr, "%2x %2x %2x %2x\n", pointer[0], pointer[1],
  388. pointer[2], pointer[3]);
  389. #ifdef DEBUG
  390. printf("ignoring missing end section\n");
  391. #else
  392. exit(8);
  393. #endif
  394. }
  395. /* figure out size of array */
  396. if (gds != NULL) {
  397. GDS_grid(gds, bds, &nx, &ny, &nxny);
  398. }
  399. else if (bms != NULL) {
  400. nxny = nx = BMS_nxny(bms);
  401. ny = 1;
  402. }
  403. else {
  404. if (BDS_NumBits(bds) == 0) {
  405. nxny = nx = 1;
  406. fprintf(stderr,"Missing GDS, constant record .. cannot "
  407. "determine number of data points\n");
  408. }
  409. else {
  410. nxny = nx = BDS_NValues(bds);
  411. }
  412. ny = 1;
  413. }
  414. #ifdef CHECK_GRIB
  415. if (gds && ! GDS_Harmonic(gds)) {
  416. /* this grib check only works for simple packing */
  417. /* turn off if harmonic */
  418. if (BDS_NumBits(bds) != 0) {
  419. i = BDS_NValues(bds);
  420. if (bms != NULL) {
  421. i += missing_points(BMS_bitmap(bms),nxny);
  422. }
  423. if (i != nxny) {
  424. fprintf(stderr,"grib header at record %ld: two values of nxny %ld %d\n",
  425. count,nxny,i);
  426. fprintf(stderr," LEN %d DataStart %d UnusedBits %d #Bits %d nxny %ld\n",
  427. BDS_LEN(bds), BDS_DataStart(bds),BDS_UnusedBits(bds),
  428. BDS_NumBits(bds), nxny);
  429. return_code = 15;
  430. nxny = nx = i;
  431. ny = 1;
  432. }
  433. }
  434. }
  435. #endif
  436. if (verbose <= 0) {
  437. printf("%ld:%ld:d=", count, pos);
  438. PDS_date(pds,year_4,v_time);
  439. printf(":%s:", k5toa(pds));
  440. if (verbose == 0) printf("kpds5=%d:kpds6=%d:kpds7=%d:TR=%d:P1=%d:P2=%d:TimeU=%d:",
  441. PDS_PARAM(pds),PDS_KPDS6(pds),PDS_KPDS7(pds),
  442. PDS_TimeRange(pds),PDS_P1(pds),PDS_P2(pds),
  443. PDS_ForecastTimeUnit(pds));
  444. levels(PDS_KPDS6(pds), PDS_KPDS7(pds),PDS_Center(pds)); printf(":");
  445. PDStimes(PDS_TimeRange(pds),PDS_P1(pds),PDS_P2(pds),
  446. PDS_ForecastTimeUnit(pds));
  447. if (PDS_Center(pds) == ECMWF) EC_ext(pds,"",":");
  448. ensemble(pds, verbose);
  449. printf("NAve=%d",PDS_NumAve(pds));
  450. if (print_PDS || print_PDS10) print_pds(pds, print_PDS, print_PDS10, verbose);
  451. if (gds && (print_GDS || print_GDS10)) print_gds(gds, print_GDS, print_GDS10, verbose);
  452. printf("\n");
  453. }
  454. else if (verbose == 1) {
  455. printf("%ld:%ld:D=", count, pos);
  456. PDS_date(pds, 1, v_time);
  457. printf(":%s:", k5toa(pds));
  458. levels(PDS_KPDS6(pds), PDS_KPDS7(pds), PDS_Center(pds)); printf(":");
  459. printf("kpds=%d,%d,%d:",
  460. PDS_PARAM(pds),PDS_KPDS6(pds),PDS_KPDS7(pds));
  461. PDStimes(PDS_TimeRange(pds),PDS_P1(pds),PDS_P2(pds),
  462. PDS_ForecastTimeUnit(pds));
  463. if (PDS_Center(pds) == ECMWF) EC_ext(pds,"",":");
  464. ensemble(pds, verbose);
  465. GDS_winds(gds, verbose);
  466. printf("\"%s", k5_comments(pds));
  467. if (print_PDS || print_PDS10) print_pds(pds, print_PDS, print_PDS10, verbose);
  468. if (gds && (print_GDS || print_GDS10)) print_gds(gds, print_GDS, print_GDS10, verbose);
  469. printf("\n");
  470. }
  471. else if (verbose == 2) {
  472. printf("rec %ld:%ld:date ", count, pos);
  473. PDS_date(pds, 1, v_time);
  474. printf(" %s kpds5=%d kpds6=%d kpds7=%d levels=(%d,%d) grid=%d ",
  475. k5toa(pds), PDS_PARAM(pds), PDS_KPDS6(pds), PDS_KPDS7(pds),
  476. PDS_LEVEL1(pds), PDS_LEVEL2(pds), PDS_Grid(pds));
  477. levels(PDS_KPDS6(pds),PDS_KPDS7(pds),PDS_Center(pds));
  478. printf(" ");
  479. if (PDS_Center(pds) == ECMWF) EC_ext(pds,""," ");
  480. ensemble(pds, verbose);
  481. PDStimes(PDS_TimeRange(pds),PDS_P1(pds),PDS_P2(pds),
  482. PDS_ForecastTimeUnit(pds));
  483. if (bms != NULL)
  484. printf(" bitmap: %d undef", missing_points(BMS_bitmap(bms),nxny));
  485. printf("\n %s=%s\n", k5toa(pds), k5_comments(pds));
  486. printf(" timerange %d P1 %d P2 %d TimeU %d nx %d ny %d GDS grid %d "
  487. "num_in_ave %d missing %d\n",
  488. PDS_TimeRange(pds),PDS_P1(pds),PDS_P2(pds),
  489. PDS_ForecastTimeUnit(pds), nx, ny,
  490. gds == NULL ? -1 : GDS_DataType(gds),
  491. PDS_NumAve(pds), PDS_NumMissing(pds));
  492. printf(" center %d subcenter %d process %d Table %d",
  493. PDS_Center(pds),PDS_Subcenter(pds),PDS_Model(pds),
  494. PDS_Vsn(pds));
  495. GDS_winds(gds, verbose);
  496. printf("\n");
  497. if (gds && GDS_LatLon(gds) && nx != -1)
  498. printf(" latlon: lat %f to %f by %f nxny %ld\n"
  499. " long %f to %f by %f, (%d x %d) scan %d "
  500. "mode %d bdsgrid %d\n",
  501. 0.001*GDS_LatLon_La1(gds), 0.001*GDS_LatLon_La2(gds),
  502. 0.001*GDS_LatLon_dy(gds), nxny, 0.001*GDS_LatLon_Lo1(gds),
  503. 0.001*GDS_LatLon_Lo2(gds), 0.001*GDS_LatLon_dx(gds),
  504. nx, ny, GDS_LatLon_scan(gds), GDS_LatLon_mode(gds),
  505. BDS_Grid(bds));
  506. else if (gds && GDS_LatLon(gds) && nx == -1) {
  507. printf(" thinned latlon: lat %f to %f by %f nxny %ld\n"
  508. " long %f to %f, %ld grid pts (%d x %d) scan %d"
  509. " mode %d bdsgrid %d\n",
  510. 0.001*GDS_LatLon_La1(gds), 0.001*GDS_LatLon_La2(gds),
  511. 0.001*GDS_LatLon_dy(gds), nxny, 0.001*GDS_LatLon_Lo1(gds),
  512. 0.001*GDS_LatLon_Lo2(gds),
  513. nxny, nx, ny, GDS_LatLon_scan(gds), GDS_LatLon_mode(gds),
  514. BDS_Grid(bds));
  515. GDS_prt_thin_lon(gds);
  516. }
  517. else if (gds && GDS_Gaussian(gds) && nx != -1)
  518. printf(" gaussian: lat %f to %f\n"
  519. " long %f to %f by %f, (%d x %d) scan %d"
  520. " mode %d bdsgrid %d\n",
  521. 0.001*GDS_LatLon_La1(gds), 0.001*GDS_LatLon_La2(gds),
  522. 0.001*GDS_LatLon_Lo1(gds), 0.001*GDS_LatLon_Lo2(gds),
  523. 0.001*GDS_LatLon_dx(gds),
  524. nx, ny, GDS_LatLon_scan(gds), GDS_LatLon_mode(gds),
  525. BDS_Grid(bds));
  526. else if (gds && GDS_Gaussian(gds) && nx == -1) {
  527. printf(" thinned gaussian: lat %f to %f\n"
  528. " lon %f %ld grid pts (%d x %d) scan %d"
  529. " mode %d bdsgrid %d nlat:\n",
  530. 0.001*GDS_LatLon_La1(gds), 0.001*GDS_LatLon_La2(gds),
  531. 0.001*GDS_LatLon_Lo1(gds),
  532. nxny, nx, ny, GDS_LatLon_scan(gds), GDS_LatLon_mode(gds),
  533. BDS_Grid(bds));
  534. GDS_prt_thin_lon(gds);
  535. }
  536. else if (gds && GDS_Polar(gds))
  537. printf(" polar stereo: Lat1 %f Long1 %f Orient %f\n"
  538. " %s pole (%d x %d) Dx %d Dy %d scan %d mode %d\n",
  539. 0.001*GDS_Polar_La1(gds),0.001*GDS_Polar_Lo1(gds),
  540. 0.001*GDS_Polar_Lov(gds),
  541. GDS_Polar_pole(gds) == 0 ? "north" : "south", nx,ny,
  542. GDS_Polar_Dx(gds),GDS_Polar_Dy(gds),
  543. GDS_Polar_scan(gds), GDS_Polar_mode(gds));
  544. else if (gds && GDS_Lambert(gds))
  545. printf(" Lambert Conf: Lat1 %f Lon1 %f Lov %f\n"
  546. " Latin1 %f Latin2 %f LatSP %f LonSP %f\n"
  547. " %s (%d x %d) Dx %f Dy %f scan %d mode %d\n",
  548. 0.001*GDS_Lambert_La1(gds),0.001*GDS_Lambert_Lo1(gds),
  549. 0.001*GDS_Lambert_Lov(gds),
  550. 0.001*GDS_Lambert_Latin1(gds), 0.001*GDS_Lambert_Latin2(gds),
  551. 0.001*GDS_Lambert_LatSP(gds), 0.001*GDS_Lambert_LonSP(gds),
  552. GDS_Lambert_NP(gds) ? "North Pole": "South Pole",
  553. GDS_Lambert_nx(gds), GDS_Lambert_ny(gds),
  554. 0.001*GDS_Lambert_dx(gds), 0.001*GDS_Lambert_dy(gds),
  555. GDS_Lambert_scan(gds), GDS_Lambert_mode(gds));
  556. else if (gds && GDS_Mercator(gds))
  557. printf(" Mercator: lat %f to %f by %f km nxny %ld\n"
  558. " long %f to %f by %f km, (%d x %d) scan %d"
  559. " mode %d Latin %f bdsgrid %d\n",
  560. 0.001*GDS_Merc_La1(gds), 0.001*GDS_Merc_La2(gds),
  561. 0.001*GDS_Merc_dy(gds), nxny, 0.001*GDS_Merc_Lo1(gds),
  562. 0.001*GDS_Merc_Lo2(gds), 0.001*GDS_Merc_dx(gds),
  563. nx, ny, GDS_Merc_scan(gds), GDS_Merc_mode(gds),
  564. 0.001*GDS_Merc_Latin(gds), BDS_Grid(bds));
  565. else if (gds && GDS_ssEgrid(gds))
  566. printf(" Semi-staggered Arakawa E-Grid: lat0 %f lon0 %f nxny %d\n"
  567. " dLat %f dLon %f (%d x %d) scan %d mode %d\n",
  568. 0.001*GDS_ssEgrid_La1(gds), 0.001*GDS_ssEgrid_Lo1(gds),
  569. GDS_ssEgrid_n(gds)*GDS_ssEgrid_n_dum(gds),
  570. 0.001*GDS_ssEgrid_dj(gds), 0.001*GDS_ssEgrid_di(gds),
  571. GDS_ssEgrid_Lo2(gds), GDS_ssEgrid_La2(gds),
  572. GDS_ssEgrid_scan(gds), GDS_ssEgrid_mode(gds));
  573. else if (gds && GDS_ss2dEgrid(gds))
  574. printf(" Semi-staggered Arakawa E-Grid (2D): lat0 %f lon0 %f nxny %d\n"
  575. " dLat %f dLon %f (tlm0d %f tph0d %f) scan %d mode %d\n",
  576. 0.001*GDS_ss2dEgrid_La1(gds), 0.001*GDS_ss2dEgrid_Lo1(gds),
  577. GDS_ss2dEgrid_nx(gds)*GDS_ss2dEgrid_ny(gds),
  578. 0.001*GDS_ss2dEgrid_dj(gds), 0.001*GDS_ss2dEgrid_di(gds),
  579. 0.001*GDS_ss2dEgrid_Lo2(gds), 0.001*GDS_ss2dEgrid_La2(gds),
  580. GDS_ss2dEgrid_scan(gds), GDS_ss2dEgrid_mode(gds));
  581. else if (gds && GDS_fEgrid(gds))
  582. printf(" filled Arakawa E-Grid: lat0 %f lon0 %f nxny %d\n"
  583. " dLat %f dLon %f (%d x %d) scan %d mode %d\n",
  584. 0.001*GDS_fEgrid_La1(gds), 0.001*GDS_fEgrid_Lo1(gds),
  585. GDS_fEgrid_n(gds)*GDS_fEgrid_n_dum(gds),
  586. 0.001*GDS_fEgrid_dj(gds), 0.001*GDS_fEgrid_di(gds),
  587. GDS_fEgrid_Lo2(gds), GDS_fEgrid_La2(gds),
  588. GDS_fEgrid_scan(gds), GDS_fEgrid_mode(gds));
  589. else if (gds && GDS_RotLL(gds))
  590. printf(" rotated LatLon grid lat %f to %f lon %f to %f\n"
  591. " nxny %ld (%d x %d) dx %d dy %d scan %d mode %d\n"
  592. " transform: south pole lat %f lon %f rot angle %f\n",
  593. 0.001*GDS_RotLL_La1(gds), 0.001*GDS_RotLL_La2(gds),
  594. 0.001*GDS_RotLL_Lo1(gds), 0.001*GDS_RotLL_Lo2(gds),
  595. nxny, GDS_RotLL_nx(gds), GDS_RotLL_ny(gds),
  596. GDS_RotLL_dx(gds), GDS_RotLL_dy(gds),
  597. GDS_RotLL_scan(gds), GDS_RotLL_mode(gds),
  598. 0.001*GDS_RotLL_LaSP(gds), 0.001*GDS_RotLL_LoSP(gds),
  599. GDS_RotLL_RotAng(gds) );
  600. else if (gds && GDS_Gnomonic(gds))
  601. printf(" Gnomonic grid\n");
  602. else if (gds && GDS_Harmonic(gds))
  603. printf(" Harmonic (spectral): pentagonal spectral truncation: nj %d nk %d nm %d\n",
  604. GDS_Harmonic_nj(gds), GDS_Harmonic_nk(gds),
  605. GDS_Harmonic_nm(gds));
  606. if (gds && GDS_Harmonic_type(gds) == 1)
  607. printf(" Associated Legendre polynomials\n");
  608. else if (gds && GDS_Triangular(gds))
  609. printf(" Triangular grid: nd %d ni %d (= 2^%d x 3^%d)\n",
  610. GDS_Triangular_nd(gds), GDS_Triangular_ni(gds),
  611. GDS_Triangular_ni2(gds), GDS_Triangular_ni3(gds) );
  612. if (print_PDS || print_PDS10)
  613. print_pds(pds, print_PDS, print_PDS10, verbose);
  614. if (gds && (print_GDS || print_GDS10))
  615. print_gds(gds, print_GDS, print_GDS10, verbose);
  616. }
  617. if (mode != INVENTORY && output_type == GRIB) {
  618. if (header == dwd) wrtieee_header((int) len_grib, dump_file);
  619. fwrite((void *) msg, sizeof(char), len_grib, dump_file);
  620. if (header == dwd) wrtieee_header((int) len_grib, dump_file);
  621. n_dump++;
  622. }
  623. if ((mode != INVENTORY && output_type != GRIB) || verbose > 1) {
  624. /* decode numeric data */
  625. if ((array = (float *) malloc(sizeof(float) * nxny)) == NULL) {
  626. fprintf(stderr,"memory problems\n");
  627. exit(8);
  628. }
  629. temp = int_power(10.0, - PDS_DecimalScale(pds));
  630. BDS_unpack(array, bds, BMS_bitmap(bms), BDS_NumBits(bds), nxny,
  631. temp*BDS_RefValue(bds),temp*int_power(2.0, BDS_BinScale(bds)));
  632. if (verbose > 1) {
  633. rmin = FLT_MAX;
  634. rmax = -FLT_MAX;
  635. for (i = 0; i < nxny; i++) {
  636. if (fabs(array[i]-UNDEFINED) > 0.0001*UNDEFINED) {
  637. rmin = min(rmin,array[i]);
  638. rmax = max(rmax,array[i]);
  639. }
  640. }
  641. printf(" min/max data %g %g num bits %d "
  642. " BDS_Ref %g DecScale %d BinScale %d\n",
  643. rmin, rmax, BDS_NumBits(bds), BDS_RefValue(bds),
  644. PDS_DecimalScale(pds), BDS_BinScale(bds));
  645. }
  646. if (mode != INVENTORY && output_type != GRIB) {
  647. /* dump code */
  648. if (output_PDS_GDS == 1) {
  649. /* insert code here */
  650. if (output_type == BINARY || output_type == IEEE) {
  651. /* write PDS */
  652. i = PDS_LEN(pds) + 4;
  653. if (header == simple && output_type == BINARY)
  654. fwrite((void *) &i, sizeof(int), 1, dump_file);
  655. if (header == simple && output_type == IEEE) wrtieee_header(i, dump_file);
  656. fwrite((void *) "PDS ", 1, 4, dump_file);
  657. fwrite((void *) pds, 1, i - 4, dump_file);
  658. if (header == simple && output_type == BINARY)
  659. fwrite((void *) &i, sizeof(int), 1, dump_file);
  660. if (header == simple && output_type == IEEE) wrtieee_header(i, dump_file);
  661. /* write GDS */
  662. i = (gds) ? GDS_LEN(gds) + 4 : 4;
  663. if (header == simple && output_type == BINARY)
  664. fwrite((void *) &i, sizeof(int), 1, dump_file);
  665. if (header == simple && output_type == IEEE) wrtieee_header(i, dump_file);
  666. fwrite((void *) "GDS ", 1, 4, dump_file);
  667. if (gds) fwrite((void *) gds, 1, i - 4, dump_file);
  668. if (header == simple && output_type == BINARY)
  669. fwrite((void *) &i, sizeof(int), 1, dump_file);
  670. if (header == simple && output_type == IEEE) wrtieee_header(i, dump_file);
  671. }
  672. }
  673. if (output_type == BINARY) {
  674. i = nxny * sizeof(float);
  675. if (header == simple) fwrite((void *) &i, sizeof(int), 1, dump_file);
  676. fwrite((void *) array, sizeof(float), nxny, dump_file);
  677. if (header == simple) fwrite((void *) &i, sizeof(int), 1, dump_file);
  678. }
  679. else if (output_type == IEEE) {
  680. wrtieee(array, nxny, header, dump_file);
  681. }
  682. else if (output_type == TEXT) {
  683. /* number of points in grid */
  684. if (header == simple) {
  685. if (nx <= 0 || ny <= 0 || nxny != nx*ny) {
  686. fprintf(dump_file, "%ld %d\n", nxny, 1);
  687. }
  688. else {
  689. fprintf(dump_file, "%d %d\n", nx, ny);
  690. }
  691. }
  692. for (i = 0; i < nxny; i++) {
  693. fprintf(dump_file,"%g\n", array[i]);
  694. }
  695. }
  696. n_dump++;
  697. }
  698. free(array);
  699. if (verbose > 0) printf("\n");
  700. }
  701. pos += len_grib;
  702. count++;
  703. }
  704. if (mode != INVENTORY) {
  705. if (header == dwd && output_type == GRIB) wrtieee_header(0, dump_file);
  706. if (ferror(dump_file)) {
  707. fprintf(stderr,"error writing %s\n",dump_file_name);
  708. exit(8);
  709. }
  710. }
  711. fclose(input);
  712. return (return_code);
  713. }
  714. void print_pds(unsigned char *pds, int print_PDS, int print_PDS10, int verbose) {
  715. int i, j;
  716. j = PDS_LEN(pds);
  717. if (verbose < 2) {
  718. if (print_PDS && verbose < 2) {
  719. printf(":PDS=");
  720. for (i = 0; i < j; i++) {
  721. printf("%2.2x", (int) pds[i]);
  722. }
  723. }
  724. if (print_PDS10 && verbose < 2) {
  725. printf(":PDS10=");
  726. for (i = 0; i < j; i++) {
  727. printf(" %d", (int) pds[i]);
  728. }
  729. }
  730. }
  731. else {
  732. if (print_PDS) {
  733. printf(" PDS(1..%d)=",j);
  734. for (i = 0; i < j; i++) {
  735. if (i % 20 == 0) printf("\n %4d:",i+1);
  736. printf(" %3.2x", (int) pds[i]);
  737. }
  738. printf("\n");
  739. }
  740. if (print_PDS10) {
  741. printf(" PDS10(1..%d)=",j);
  742. for (i = 0; i < j; i++) {
  743. if (i % 20 == 0) printf("\n %4d:",i+1);
  744. printf(" %3d", (int) pds[i]);
  745. }
  746. printf("\n");
  747. }
  748. }
  749. }
  750. void print_gds(unsigned char *gds, int print_GDS, int print_GDS10, int verbose) {
  751. int i, j;
  752. j = GDS_LEN(gds);
  753. if (verbose < 2) {
  754. if (print_GDS && verbose < 2) {
  755. printf(":GDS=");
  756. for (i = 0; i < j; i++) {
  757. printf("%2.2x", (int) gds[i]);
  758. }
  759. }
  760. if (print_GDS10 && verbose < 2) {
  761. printf(":GDS10=");
  762. for (i = 0; i < j; i++) {
  763. printf(" %d", (int) gds[i]);
  764. }
  765. }
  766. }
  767. else {
  768. if (print_GDS) {
  769. printf(" GDS(1..%d)=",j);
  770. for (i = 0; i < j; i++) {
  771. if (i % 20 == 0) printf("\n %4d:",i+1);
  772. printf(" %3.2x", (int) gds[i]);
  773. }
  774. printf("\n");
  775. }
  776. if (print_GDS10) {
  777. printf(" GDS10(1..%d)=",j);
  778. for (i = 0; i < j; i++) {
  779. if (i % 20 == 0) printf("\n %4d:",i+1);
  780. printf(" %3d", (int) gds[i]);
  781. }
  782. printf("\n");
  783. }
  784. }
  785. }