3 This is the TRMM Office Radar Software Library.
6 Space Applications Corporation
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public
11 License as published by the Free Software Foundation; either
12 version 2 of the License, or (at your option) any later version.
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
19 You should have received a copy of the GNU Library General Public
20 License along with this library; if not, write to the Free
21 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "rapic_routines.h"
31 int rapicerror(char *s);
32 int rapicwrap(char *s);
33 int rapicwrap(char *s);
39 Radar *radar, *rapic_radar = NULL;
44 /* Rapic format declarations. */
45 Rapic_sweep_header rh;
48 unsigned char outbuf[2000000];
55 int ivolume, isweep, iray;
60 extern int radar_verbose_flag;
64 /* 2/18/98 - John Merritt
66 * This grammar parses the NT Rapic radar format. The grammar
67 * is not minimal, however, it is self documenting; it closely matches
68 * the brief documentation.
71 /*-----------------------------------------------------------------
72 * NT Rapic Volume Structure:
73 * NOTE: '*' marked tokens are preent only in versions > 10.0
76 * The header contains a set of tokens followed by data.
77 * Each token is seperated by '\n' and all the data is
80 * Scan header has the scan details like fieldname,
81 * date/time azimuth,elevation etc.
82 * The different sets of Tokens together with the data
83 * are seperate by '\0'.
85 * This represents the field data in runlehgth code.
86 * Each Ray data contains azimuth,elevation,delta time
87 * since start of this scan and the actual data.
89 * Here is a brief explanation of each of the Tokens.
94 * 1 /IMAGE: <seqno> <imgno>
95 * <seqno> 4 digit number
96 * <imgno> 10 digit number
98 * 2 /IMAGESCANS: <nscans>
99 * <nscans> Number of scans in this volume
101 * 3 /IMAGESIZE: <size>
102 * <size> Size of image in bytes
104 * 4 /SCAN <scanno:> <seqno> <datetime> <???> <elev> <fieldno> <???> <offset> <size>
105 * <scanno:> 1 - <number of scans>
106 * <seqno> seqnum as given in /IMAGE:
107 * <datetime> yymoddhhmm
108 * <???> Don't care ( I don't know )
109 * <elev> Target Elevation in degrees.
111 * 0 Reflectivity ?? Index? haven't seen this yet. ??
112 * 1 Velocity Confirmed this index.
114 * 3 ZDR ?? Index? haven't seen this yet. ??
115 * 4 Uncorrected Reflectivity. Confirmed.
117 * <offset> Offset to start of scan header
118 * <size> Size of this scan
119 * add offset to size to get to the next scan
120 * /SCAN is repeated for each scan in the volume.
122 * Unlike other formats each scan need not represent a seperate
125 * 5 /IMAGEHEADER END:
126 * Indicates the end of Image header.
131 * <code> is a country code number
134 * <Name> 8 char long station name
137 * <idno> A unique number indexing into station details
139 * LATITUDE: <lat.lat> *
140 * <lat.lat> Latitude in degrees
142 * LONGITUDE: <lon.lon> *
143 * <lon.lon> Longitude in degrees
146 * <alt> Radar height in meters
149 * <datno> year = datno % 100
150 * if year > 80 year += 1900
153 * Get the julian Number from year,1,1 and add doy -1
154 * Use Julian date conversion to get calendar date.
155 * NOTE: As simple as remembering your partner's DOB.
158 * <hh.mm> Hour and minute
160 * TIMESTAMP: <yyyymoddhhmmss> *
161 * <yyyymoddhhmmss> year,month,day,hour,min,sec
163 * VERS: <versionNumber>
164 * <versionNumber> 10.01
166 * FREQUENCY: <freq> *
167 * <freq> Radar Frequency.
170 * <prf> Pulse repetition Frequency
172 * PULSELENGTH: <len> *
175 * RNGRES: <gatewidth>
176 * <gatewidth> Range between gates
179 * <angle> BeamWidth in degrees.
181 * CLEARAIR: ON or OFF
184 * <res> Video Resolution can be
188 * <rng> Range to First gate in meters.
191 * <rng> Maximum range.
193 * PRODUCT: <type> <[id]>
200 * PASS: <no> of <nscans>
201 * <no> Number of this scan
202 * <nscans> Max scan no.
205 * <type> PPI,RHI etc.
208 * <elev> Elevation in degrees
211 * <field> Field Name Vel,Refl,Vel,UnCorRefl,Zdr,Wid
214 * <level> Velocity Level
217 * <nyq> Nyquist Velocity
219 * UNFOLDING: <ratio> *
220 * <ratio> None or x:y
224 * <data> AAA.A,EEE.E,TTT=LEN16D1D1D1NLD1D1D1NLNL
226 * AAA.A Azimuth in degrees
227 * EEE.E Elevation in degress
228 * TTT Delta time in seconds since the start of this scan
229 * LEN16 2 byte long length of radial
231 * D1 Run length coded Data.
232 * NL Null The Next Byte is count of NULL data.
233 * NLNL End of this Radial
235 * eg. There will be no white space in the actual radial data.
237 * @066.1,010.6,004=002082B2817F8C84830048D72D0038
238 * 999C0036202D35FD2C00238A99008AFE920000
241 * Dt = 4 sec since the start
242 * 0020 = Bytes to follow
243 * Data = 82,B2,81,7F,8C,84,83
244 * 0048 = 48H null bytes
246 * 0038 = 38H null bytes
248 * 0036 = 36H Null bytes
249 * ........................
250 * 0000 = End of Data.
251 * In versions before 10.1
253 * <data> AAALEN16D1D1D1NLD1D1D1NLNL
255 * AAA Azimuth in degrees
256 * LEN16 2 byte long length of radial
258 * D1 Run length coded Data.
259 * NL Null The Next Byte is count of NULL data.
260 * NLNL End of this Radial
262 * eg. There will be no white space in the actual radial data.
264 * @066002082B2817F8C84830048D72D0038
265 * 999C0036202D35FD2C00238A99008AFE920000
267 * 0020 = Bytes to follow
268 * Data = 82,B2,81,7F,8C,84,83
269 * 0048 = 48H null bytes
271 * 0038 = 38H null bytes
273 * 0036 = 36H Null bytes
274 * ........................
275 * 0000 = End of Data.
277 * Please see the attached sample.vol to give a overall picture of the data.
278 * This is the dump of the volume with white space inserted to make it readable.
279 * Radial data dump is in hex.
282 %token IMAGE IMAGESCANS IMAGESIZE IMAGEEND
283 %token SCAN IMAGEHEADEREND
305 %token CLEARAIR ON OFF
321 %token REFL VEL UNCORREFL ZDR WID
334 rapic_recognized : complete_header sweeps imageend
336 if (radar_verbose_flag) fprintf(stderr, "SUCCESSFUL parse\n");
337 sprintf(radar->h.name, "%s", rh.namestr);
338 sprintf(radar->h.radar_name, "%s", rh.namestr);
340 radar = fill_header(radar);
341 radar = RSL_prune_radar(radar);
349 sweep : sweepheader rays ENDRADARIMAGE
351 /* Attach the sweep to the volume. */
352 if (radar_verbose_flag) fprintf(stderr, "Attach the sweep %d to the volume %d.\n",
354 radar->v[ivolume]->sweep[isweep] = sweep;
355 radar->v[ivolume]->h.f = sweep->h.f;
356 radar->v[ivolume]->h.invf = sweep->h.invf;
359 sweepheader : scanheader
361 /* float c = RSL_SPEED_OF_LIGHT; */
362 if (rh.angle_resolution != 0)
363 sweep = RSL_new_sweep((int)(360.0/rh.angle_resolution+0.5));
364 if (fabs(rh.elev - save_elev) > .5) { /* New sweep elevation. */
369 /* rapic_nyquist = c*((float)rh.prf/10.)/(4.*(float)rh.freq*100000.0); */
372 imageend : IMAGEEND seqno imgno
374 complete_header : imageheader IMAGEHEADEREND
376 if (radar_verbose_flag) fprintf(stderr, "sweepcount[0] = %d\n", sweepcount[0]);
377 if (sweepcount[0] > 0) {
378 radar->v[DZ_INDEX] = RSL_new_volume(sweepcount[0]);
379 radar->v[DZ_INDEX]->h.type_str = strdup("Reflectivity");
381 if (radar_verbose_flag) fprintf(stderr, "sweepcount[1] = %d\n", sweepcount[1]);
382 if (sweepcount[1] > 0) {
383 volume = radar->v[VR_INDEX] = RSL_new_volume(sweepcount[1]);
384 volume->h.type_str = strdup("Velocity");
385 volume->h.calibr_const = 0.0;
387 if (radar_verbose_flag) fprintf(stderr, "sweepcount[2] = %d\n", sweepcount[2]);
388 if (sweepcount[2] > 0) {
389 radar->v[SW_INDEX] = RSL_new_volume(sweepcount[2]);
390 volume->h.type_str = strdup("Spectral Width");
391 volume->h.calibr_const = 0.0;
393 if (radar_verbose_flag) fprintf(stderr, "sweepcount[3] = %d\n", sweepcount[3]);
394 if (sweepcount[3] > 0) {
395 radar->v[ZD_INDEX] = RSL_new_volume(sweepcount[3]);
396 volume->h.type_str = strdup("Reflectivity Depolarization Ratio");
397 volume->h.calibr_const = 0.0;
399 if (radar_verbose_flag) fprintf(stderr, "sweepcount[4] = %d\n", sweepcount[4]);
400 if (sweepcount[4] > 0) {
401 radar->v[ZT_INDEX] = RSL_new_volume(sweepcount[4]);
402 volume->h.type_str = strdup("Total Reflectivity");
403 volume->h.calibr_const = 0.0;
405 isweep = -1; /* It keeps track of the sweep number across all field
406 * types; volumes. It is immediately bumped to 0 when
407 * the sweepheader is parsed.
413 imageheader : imageheader_item
414 | imageheader imageheader_item
418 imageheader_item : IMAGE seqno imgno
420 radar = RSL_new_radar(MAX_RADAR_VOLUMES);
426 radar->h.number = atoi($<token.s>2);
432 if (atoi($<token.s>2) <= 0) {
433 fprintf(stderr, "RAPIC: /IMAGESIZE == %d. RAPIC ingest returning NULL.\n", atoi($<token.s>2));
440 scanlist : SCAN scanno ':' seqno datetime dc elev fieldno dc offset size
442 ifield = atoi($<token.s>8);
443 sweepcount[ifield]++;
447 * Now, describe some scan header fields.
458 /* fprintf(stderr, "YACC len=%d text=<", yylval.token.len); */
459 /* binprint(yylval.token.s, yylval.token.len); */
460 /* fprintf(stderr, ">\n"); */
462 /* Quiet the compilier, because I only use the rsl_f_list and rsl_invf_list. */
463 RSL_ftype[0] = RSL_ftype[0];
465 /* Use yylval.token.s and yylval.token.len */
466 memset(outbuf, sizeof(outbuf), '\0');
467 rapic_decode((unsigned char *)yylval.token.s, yylval.token.len, outbuf, &outbytes,
468 &azim, &elev, &delta_time);
469 /* fprintf(stderr, "RAYDATA: ray %d, ivol %d, isweep %d, azim %f, elev %f, dtime %d, size=%d\n", nray, ivolume, isweep, azim, elev, delta_time, outbytes); */
471 ray = RSL_new_ray(outbytes);
472 rapic_load_ray_header(rh, nray, isweep, elev, azim, &ray->h); /* Mostly from the scanheader (rh). */
473 ray->h.azimuth = azim;
474 /* if (39<azim && azim <40) { */
476 ray->h.sec += delta_time;
477 ray->h.f = RSL_f_list[ivolume]; /* Data conversion function. f(x). */
478 ray->h.invf = RSL_invf_list[ivolume]; /* invf(x). */
481 rapic_load_ray_data(outbuf, outbytes, ivolume, ray);
485 if (ray->h.ray_num == 0 && ivolume == 1 && isweep == 0)
487 fprintf(stderr, "RAYDATA: ray %d, ivol %d, isweep %d, azim %f, elev %f, dtime %d, size=%d\n", nray, ivolume, isweep, azim, elev, delta_time, outbytes);
488 for (i=0; i<ray->h.nbins; i++) {
489 fprintf(stderr,"YACCray->range[%d] = %d %f\n", i, (int)ray->range[i],
490 ray->h.f(ray->range[i]));
494 /* Attach the ray to the sweep. */
495 sweep->ray[nray] = ray;
496 sweep->h.beam_width = ray->h.beam_width;
497 sweep->h.vert_half_bw = sweep->h.beam_width / 2.0;
498 sweep->h.horz_half_bw = sweep->h.beam_width / 2.0;
499 sweep->h.sweep_num = isweep;
500 sweep->h.elev = ray->h.elev;
501 sweep->h.f = ray->h.f;
502 sweep->h.invf = ray->h.invf;
507 scanheader : scanheaditem
508 | scanheader scanheaditem
512 /* Each of these items are the header for a sweep. */
515 : NAME namestr { memmove(rh.namestr,$<token.s>2,$<token.len>2); }
516 | COUNTRY code { rh.country = atoi($<token.s>2); }
517 | STNID idno { rh.station_id_no = atoi($<token.s>2); }
518 | LATITUDE lat { rh.lat = atof($<token.s>2); }
519 | LONGITUDE lon { rh.lon = atof($<token.s>2); }
520 | HEIGHT alt { rh.height = atof($<token.s>2); }
521 | DATE datno { rh.datno = atoi($<token.s>2); }
522 | TIME hhmm { rh.hhmm = atof($<token.s>2); }
523 | TIMESTAMP yyyymoddhhmmss { memmove(rh.yyyymoddhhmmss,$<token.s>2,$<token.len>2); }
524 | VERS versionNumber { rh.versionNumber = atof($<token.s>2); }
525 | FREQUENCY freq { rh.freq = atoi($<token.s>2); }
526 | PRF prf { rh.prf = atoi($<token.s>2); }
527 | PULSELENGTH len { rh.pulselen = atof($<token.s>2); }
528 | RNGRES gatewidth { rh.range_resolution = atoi($<token.s>2); }
529 | ANGLERATE anglerate { rh.anglerate = atof($<token.s>2); }
530 | CLEARAIR clearair { memmove(rh.clearair,$<token.s>2,$<token.len>2);}
531 | ANGRES angle { rh.angle_resolution = atof($<token.s>2); }
532 | VIDRES res { rh.video_resolution = atoi($<token.s>2); }
533 | STARTRNG rng { rh.start_range = atoi($<token.s>2); }
534 | ENDRNG rng { rh.end_range = atoi($<token.s>2); }
535 | PRODUCT typeid BRACKETNUM { memmove(rh.product_type,$<token.s>2,$<token.len>2); }
538 | ELEV elev { rh.elev = atof($<token.s>2); }
539 | VELLVL level { rh.vellvl = atof($<token.s>2); }
542 rh.nyquist = atof($<token.s>2);
543 rapic_nyquist = rh.nyquist;
545 | VIDEO field { memmove(rh.video,$<token.s>2,$<token.len>2); }
546 | IMGFMT type { memmove(rh.imgfmt,$<token.s>2,$<token.len>2); }
547 | UNFOLDING ratio /* Already loaded: rh.ratio1, rh.ratio2 */
575 yyyymoddhhmmss : number
591 noofnscans : no OF nscans
592 no : number {rh.scannum = atoi($<token.s>1);}
593 nscans : number {rh.ofscans = atoi($<token.s>1);}
596 field : REFL {ivolume = DZ_INDEX; volume = radar->v[ivolume];}
597 | VEL {ivolume = VR_INDEX; volume = radar->v[ivolume];}
598 | UNCORREFL {ivolume = ZT_INDEX; volume = radar->v[ivolume];}
599 | ZDR {ivolume = ZD_INDEX; volume = radar->v[ivolume];}
600 | WID {ivolume = SW_INDEX; volume = radar->v[ivolume];}
605 ratio : NONE {rh.ratio1 = 0; rh.ratio2 = 0;}
606 | number ':' number {rh.ratio1 = atoi($<token.s>1); rh.ratio2 = atoi($<token.s>3);}
612 int rapicerror(char *s)
614 fprintf(stderr, "RAPIC ERROR: <%s> on token <", s);
615 binprint(yylval.token.s, yylval.token.len);
616 fprintf(stderr, ">\n");
620 int rapicwrap(char *s)