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.
29 #include <netinet/in.h>
31 #include "win32compat.h"
34 int dorade_verbose = 0;
36 void dorade_verbose_on()
40 void dorade_verbose_off()
45 static int do_swap = 0;
47 /**********************************************************************/
49 /* read_extra_bytes */
51 /**********************************************************************/
52 int read_extra_bytes(int nbytes, FILE *in)
57 * Read and discard nbytes bytes. The return value is the byte count
58 * returned by fread, unless there is an error, then it is 0.
60 extra = (char *) malloc(nbytes);
62 perror("\nError: read_extra_bytes");
63 fprintf(stderr,"Tried to allocate %d bytes\n", nbytes);
66 nread = fread(extra, sizeof(char), nbytes, in);
71 /**********************************************************************/
73 /* dorade_read_comment_block */
75 /**********************************************************************/
76 Comment_block *dorade_read_comment_block(FILE *in)
79 cb = (Comment_block *) calloc(1, sizeof(Comment_block));
81 perror("dorade_read_comment_block");
84 if (fread(cb->code, sizeof(cb->code), 1, in) != 1) {
85 perror("dorade_read_comment_block: fread");
88 if (fread(&cb->len, sizeof(cb->len), 1, in) != 1) {
89 perror("dorade_read_comment_block: fread");
93 /* Check for big endian data on little endian platform. The smallest value
94 * cb->len could have is 8 (length of cb->code + cb->len), so we put that in
95 * first byte of test value, and also test for negative, since sign bit could
96 * be set in a larger value.
98 if (cb->len > 0x08000000 || cb->len < 0) do_swap = 1;
99 if (do_swap) cb->len = ntohl(cb->len);
101 /* Length of cb->comment is cb->len-8 since cb->code and cb->len have
104 cb->comment = (char *) calloc(cb->len-8, sizeof(char));
105 if (cb->comment == NULL) {
106 perror("dorade_read_comment_block: cb->comment");
109 if (fread(cb->comment, sizeof(char), cb->len-8, in) != cb->len){
110 perror("dorade_read_comment_block: fread");
116 /**********************************************************************/
118 /* dorade_read_volume_desc */
120 /**********************************************************************/
121 Volume_desc *dorade_read_volume_desc (FILE *in)
125 vd = (Volume_desc *) calloc(1, sizeof(Volume_desc));
127 perror("dorade_read_volume_desc");
131 if (fread(vd, sizeof(Volume_desc), 1, in) != 1) {
132 perror("dorade_read_volume_desc: fread");
136 /* Now, convert from Big Endian. */
138 vd->len = ntohl(vd->len);
139 vd->version = ntohs(vd->version);
140 vd->volume_number = ntohs(vd->volume_number);
141 vd->max_bytes = ntohl(vd->max_bytes);
142 vd->year = ntohs(vd->year);
143 vd->month = ntohs(vd->month);
144 vd->day = ntohs(vd->day);
145 vd->hour = ntohs(vd->hour);
146 vd->minute = ntohs(vd->minute);
147 vd->second = ntohs(vd->second);
148 vd->gen_year = ntohs(vd->gen_year);
149 vd->gen_month = ntohs(vd->gen_month);
150 vd->gen_day = ntohs(vd->gen_day);
151 vd->nsensors = ntohs(vd->nsensors);
156 extern int little_endian(void);
157 extern void swap_4_bytes(void *word);
158 extern void swap_2_bytes(void *word);
161 /* Sensor descriptor routines. */
162 /**********************************************************************/
164 /* dorade_read_radar_desc */
166 /**********************************************************************/
167 Radar_desc *dorade_read_radar_desc (FILE *in)
172 rd = (Radar_desc *) calloc(1, sizeof(Radar_desc));
174 perror("dorade_read_radar_desc");
178 if (fread(rd, sizeof(Radar_desc), 1, in) != 1) {
179 perror("dorade_read_radar_desc: fread");
182 /* Now, convert from Big Endian. */
184 swap_4_bytes(&rd->len);
185 swap_4_bytes(&rd->radar_constant); /* Yes, even the ieee floating values. */
186 swap_4_bytes(&rd->peak_power);
187 swap_4_bytes(&rd->noise_power);
188 swap_4_bytes(&rd->rcvr_gain);
189 swap_4_bytes(&rd->ant_gain);
190 swap_4_bytes(&rd->radar_system_gain);
191 swap_4_bytes(&rd->horizontal_beam_width);
192 swap_4_bytes(&rd->vertical_beam_width);
193 swap_2_bytes(&rd->radar_type);
194 swap_2_bytes(&rd->scan_mode);
195 swap_4_bytes(&rd->scan_rate);
196 swap_4_bytes(&rd->start_angle);
197 swap_4_bytes(&rd->stop_angle);
198 swap_2_bytes(&rd->nparam_desc);
199 swap_2_bytes(&rd->ndesc);
200 swap_2_bytes(&rd->compress_code);
201 swap_2_bytes(&rd->compress_algo);
202 swap_4_bytes(&rd->data_reduction_param1);
203 swap_4_bytes(&rd->data_reduction_param2);
204 swap_4_bytes(&rd->longitude);
205 swap_4_bytes(&rd->latitude);
206 swap_4_bytes(&rd->altitude);
207 swap_4_bytes(&rd->unambiguous_velocity);
208 swap_4_bytes(&rd->unambiguous_range);
209 swap_2_bytes(&rd->nfreq);
210 swap_2_bytes(&rd->npulse_periods);
211 for (i=0; i<5; i++) {
212 swap_4_bytes(&rd->freq[i]);
213 swap_4_bytes(&rd->period[i]);
216 /* If RADD block is longer than structure, read through extra bytes.
217 * This sometimes happens.
219 if (rd->len > sizeof(Radar_desc)) {
220 if (read_extra_bytes(rd->len - sizeof(Radar_desc), in) <= 0)
221 fprintf(stderr,"Called from %s, line: %d\n", __FILE__, __LINE__ - 1);
225 /**********************************************************************/
227 /* dorade_read_parameter_desc */
229 /**********************************************************************/
230 Parameter_desc *dorade_read_parameter_desc (FILE *in)
234 pd = (Parameter_desc *) calloc(1, sizeof(Parameter_desc));
236 perror("dorade_read_parameter_desc");
240 if (fread(pd, sizeof(Parameter_desc), 1, in) != 1) {
241 perror("dorade_read_parameter_desc: fread");
244 /* Now, convert from Big Endian. */
246 swap_4_bytes(&pd->len);
247 swap_2_bytes(&pd->ipp);
248 swap_2_bytes(&pd->xmit_freq);
249 swap_4_bytes(&pd->rcvr_bandwidth);
250 swap_2_bytes(&pd->pulse_width);
251 swap_2_bytes(&pd->polarization);
252 swap_2_bytes(&pd->nsamp_in_dwell_time);
253 swap_2_bytes(&pd->parameter_type);
254 swap_4_bytes(&pd->threshold_value);
255 swap_4_bytes(&pd->scale_factor);
256 swap_4_bytes(&pd->offset_factor);
257 swap_4_bytes(&pd->missing_data_flag);
259 /* If the descriptor block is longer than the structure, read past the extra bytes.
261 if (pd->len > sizeof(Parameter_desc)) {
262 if (read_extra_bytes(pd->len - sizeof(Parameter_desc), in) <= 0)
263 fprintf(stderr,"Called from %s, line: %d\n", __FILE__, __LINE__ - 1);
268 /**********************************************************************/
270 /* dorade_read_cell_range_vector */
272 /**********************************************************************/
273 Cell_range_vector *dorade_read_cell_range_vector (FILE *in)
275 Cell_range_vector *cv;
279 cv = (Cell_range_vector *) calloc(1, sizeof(Cell_range_vector));
281 perror("dorade_read_cell_range_vector");
285 if (fread(&cv->code, sizeof(cv->code), 1, in) != 1 ||
286 fread(&cv->len, sizeof(cv->len), 1, in) != 1 ||
287 fread(&cv->ncells, sizeof(cv->ncells), 1, in) != 1) {
288 perror("dorade_read_cell_range_vector: fread");
292 swap_4_bytes(&cv->len);
293 swap_4_bytes(&cv->ncells);
295 cv->range_cell = (float *)calloc(cv->ncells, sizeof(float));
296 if (!cv->range_cell) {
297 perror("dorade_read_cell_range_vector: cv->range_cell");
300 if (fread(cv->range_cell, sizeof(float), cv->ncells, in) != cv->ncells) {
301 perror("dorade_read_cell_range_vector: fread");
306 for (i=0; i<cv->ncells; i++)
307 swap_4_bytes(&cv->range_cell[i]);
310 /* Usually reading the range cells does not read to the end
311 * of the Cell_range_vector structure. We may be reading
312 * a non seekable device!
314 i = cv->len /* Remove a few bytes that precede. */
319 buff = (char *)malloc(i);
320 if (!buff) return cv;
321 if (fread(buff, sizeof(char), i, in) != i) {
322 perror("dorade_read_cell_range_vector: fread");
329 /**********************************************************************/
331 /* dorade_read_correction_factor_desc */
333 /**********************************************************************/
334 Correction_factor_desc *dorade_read_correction_factor_desc(FILE *in)
336 Correction_factor_desc *cf;
340 cf = (Correction_factor_desc *) calloc(1, sizeof(Correction_factor_desc));
342 perror("dorade_read_correction_factor_desc");
346 /* Make sure we have Correction Factor Descriptor. */
348 if (fread(cf->code, sizeof(cf->code), 1, in) != 1) {
349 perror("dorade_read_correction_factor_desc: fread");
352 if (strncmp(cf->code, "CFAC", 4) == 0)
355 if (fread(&cf->len, sizeof(cf->len), 1, in) != 1) {
356 perror("dorade_read_correction_factor_desc: fread");
359 if (do_swap) swap_4_bytes(&cf->len);
360 remaining = (char *) malloc(cf->len-8);
362 perror("\ndorade_read_correction_factor_desc");
363 fprintf(stderr,"cf->len = %d\n\n", cf->len);
366 if (fread(remaining, sizeof(char), cf->len-8, in) != 1) {
367 perror("dorade_read_correction_factor_desc: fread");
373 if (fread(&cf->len, sizeof(Correction_factor_desc)-4, 1, in) != 1) {
374 perror("dorade_read_correction_factor_desc: fread");
377 /* Now, convert from Big Endian. */
379 swap_4_bytes(&cf->len);
380 swap_4_bytes(&cf->azimuth);
381 swap_4_bytes(&cf->elevation);
382 swap_4_bytes(&cf->range);
383 swap_4_bytes(&cf->longitude);
384 swap_4_bytes(&cf->latitude);
385 swap_4_bytes(&cf->altitude);
386 swap_4_bytes(&cf->height);
387 swap_4_bytes(&cf->speed_east_west);
388 swap_4_bytes(&cf->speed_north_south);
389 swap_4_bytes(&cf->vertical_velocity);
390 swap_4_bytes(&cf->heading);
391 swap_4_bytes(&cf->roll);
392 swap_4_bytes(&cf->pitch);
393 swap_4_bytes(&cf->drift);
394 swap_4_bytes(&cf->rotation_angle);
395 swap_4_bytes(&cf->tilt_angle);
400 /**********************************************************************/
402 /* dorade_read_sensor */
404 /**********************************************************************/
405 Sensor_desc *dorade_read_sensor (FILE *in)
407 /* Read one 'Sensor #n' descriptor from FILE. */
412 sd = (Sensor_desc *) calloc (1, sizeof(Sensor_desc));
414 perror("dorade_read_sensor");
418 sd->radar_desc = dorade_read_radar_desc(in);
419 sd->nparam = sd->radar_desc->nparam_desc;
421 sd->p_desc = (Parameter_desc **) calloc(sd->nparam, sizeof(Parameter_desc *));
423 perror("dorade_read_sensor: sd->p_desc");
426 for (i=0; i<sd->nparam; i++) {
427 sd->p_desc[i] = dorade_read_parameter_desc(in);
430 sd->cell_range_vector = dorade_read_cell_range_vector(in);
431 sd->correction_factor_desc = dorade_read_correction_factor_desc(in);
436 /**********************************************************************/
438 /* dorade_read_sweep_info */
440 /**********************************************************************/
441 Sweep_info *dorade_read_sweep_info(FILE *in)
445 si = (Sweep_info *) calloc(1, sizeof(Sweep_info));
447 perror("dorade_read_sweep_info");
451 if (fread(si, sizeof(Sweep_info), 1, in) != 1) {
452 perror("dorade_read_sweep_info: fread");
455 /* FIXME: ?? For now, VOLD is what we expect when there
456 * are no more SWIB. This is a data driven EOF.
457 * Returning NULL should suffice.
459 if(strncmp(si->code, "SWIB", 4) != 0) {
460 /* Ignore the rest of the file. */
465 /* Now, convert from Big Endian. */
467 swap_4_bytes(&si->len);
468 swap_4_bytes(&si->sweep_num);
469 swap_4_bytes(&si->nrays);
470 swap_4_bytes(&si->start_angle);
471 swap_4_bytes(&si->stop_angle);
472 swap_4_bytes(&si->fixed_angle);
473 swap_4_bytes(&si->filter_flag);
479 /* Data Ray routines. */
481 /**********************************************************************/
483 /* dorade_read_ray_info */
485 /**********************************************************************/
486 Ray_info *dorade_read_ray_info (FILE *in)
490 ri = (Ray_info *) calloc(1, sizeof(Ray_info));
492 perror("dorade_read_ray_info");
496 if (fread(ri, sizeof(Ray_info), 1, in) != 1) {
497 perror("dorade_read_ray_info: fread");
500 /* Now, convert from Big Endian. */
502 swap_4_bytes(&ri->len);
503 swap_4_bytes(&ri->sweep_num);
504 swap_4_bytes(&ri->jday);
505 swap_2_bytes(&ri->hour);
506 swap_2_bytes(&ri->minute);
507 swap_2_bytes(&ri->second);
508 swap_2_bytes(&ri->msec);
509 swap_4_bytes(&ri->azimuth);
510 swap_4_bytes(&ri->elevation);
511 swap_4_bytes(&ri->peak_power);
512 swap_4_bytes(&ri->scan_rate);
513 swap_4_bytes(&ri->status);
519 /**********************************************************************/
521 /* dorade_read_platform_info */
523 /**********************************************************************/
524 Platform_info *dorade_read_platform_info (FILE *in)
529 pi = (Platform_info *) calloc(1, sizeof(Platform_info));
531 perror("dorade_read_platform_info");
535 /* Read the id code to make sure we have "ASIB" for platform info. If
536 * id is ASIB, then read data into the Platform_info structure. If it is
537 * XSTF, read and discard remainder of block, which will have a different
538 * size than Platform_info. XSTF is undocumented, but apparently it takes
539 * the place of ASIB when radar is grounded.
542 if (fread(pi->code, sizeof(pi->code), 1, in) != 1 ||
543 fread(&pi->len, sizeof(pi->len), 1, in) != 1) {
544 perror("dorade_read_platform_info: fread");
547 if (do_swap) swap_4_bytes(&pi->len);
548 len_first_two = sizeof(pi->code) + sizeof(pi->len);
550 if (strncmp(pi->code, "ASIB", 4) == 0) {
551 if (fread(&pi->longitude, sizeof(Platform_info)-len_first_two, 1, in) != 1) {
552 perror("dorade_read_platform_info: fread");
555 /* Read past any extra bytes. */
556 if (pi->len > sizeof(Platform_info)) {
557 if (read_extra_bytes(pi->len - sizeof(Platform_info), in) <= 0)
558 fprintf(stderr,"Called from %s, line: %d\n",__FILE__,__LINE__-1);
560 /* Now, convert from Big Endian. */
562 swap_4_bytes(&pi->longitude);
563 swap_4_bytes(&pi->latitude);
564 swap_4_bytes(&pi->altitude);
565 swap_4_bytes(&pi->height);
566 swap_4_bytes(&pi->ew_speed);
567 swap_4_bytes(&pi->ns_speed);
568 swap_4_bytes(&pi->v_speed);
569 swap_4_bytes(&pi->heading);
570 swap_4_bytes(&pi->roll);
571 swap_4_bytes(&pi->pitch);
572 swap_4_bytes(&pi->drift);
573 swap_4_bytes(&pi->rotation);
574 swap_4_bytes(&pi->tilt);
575 swap_4_bytes(&pi->ew_wind_speed);
576 swap_4_bytes(&pi->ns_wind_speed);
577 swap_4_bytes(&pi->v_wind_speed);
578 swap_4_bytes(&pi->heading_rate);
579 swap_4_bytes(&pi->pitch_rate);
581 } else if (strncmp(pi->code, "XSTF", 4) == 0) {
582 /* Read to end of XSTF block. */
583 if (read_extra_bytes(pi->len - len_first_two, in) <= 0)
584 fprintf(stderr,"Called from %s, line: %d\n", __FILE__, __LINE__ - 1);
586 fprintf(stderr,"Unexpected block id: \"%s\"."
587 " Expected \"ASIB\" or \"XSTF\"\n", pi->code);
593 /**********************************************************************/
595 /* dorade_read_parameter_data */
597 /**********************************************************************/
599 Parameter_data *dorade_read_parameter_data(FILE *in)
604 pd = (Parameter_data *) calloc(1, sizeof(Parameter_data));
606 perror("dorade_read_parameter_data: pd");
610 if (fread(&pd->code, sizeof(pd->code), 1, in) != 1 ||
611 fread(&pd->len, sizeof(pd->len), 1, in) != 1 ||
612 fread(&pd->name, sizeof(pd->name), 1, in) != 1) {
613 perror("dorade_read_parameter_data: fread");
616 if (do_swap) swap_4_bytes(&pd->len);
617 /* Length is in parameter data block? or calculate if from pd->len. */
619 len = pd->len /* Use pd->len for now. */
620 - sizeof(pd->code) /* Remove a few bytes from */
621 - sizeof(pd->len) /* the count. */
623 pd->data = (char *)calloc(len, sizeof(char));
625 perror("dorade_read_parameter_data: pd->data");
628 if (fread(pd->data, sizeof(char), len, in) != len) {
629 perror("dorade_read_parameter_data: fread");
633 /* FIXME: Big endian conversion in caller? Is that the right place? */
637 /**********************************************************************/
639 /* dorade_read_sweep */
641 /**********************************************************************/
642 Sweep_record *dorade_read_sweep(FILE *fp, Sensor_desc **sd)
650 Parameter_desc **parameter_desc;
655 sr = (Sweep_record *) calloc (1, sizeof(Sweep_record));
657 perror("dorade_read_sweep");
661 nparam = sd[0]->nparam;
662 parameter_desc = sd[0]->p_desc;
665 sr->s_info = si = dorade_read_sweep_info(fp);
668 return NULL; /* EOF or error. */
670 sr->nrays = si->nrays;
671 if (dorade_verbose) {
672 printf("=====< NEW SWIB >=====\n");
673 dorade_print_sweep_info(si);
675 sr->data_ray = (Data_ray **) calloc(si->nrays, sizeof(Data_ray *));
678 return NULL; /* EOF or error. */
681 for (i=0; i<si->nrays; i++) {
682 if (dorade_verbose) printf("---------- Ray %d ----------\n", i);
683 sr->data_ray[i] = (Data_ray *) calloc(1, sizeof(Data_ray));
684 if (!sr->data_ray[0]) {
686 return NULL; /* EOF or error. */
688 ri = dorade_read_ray_info(fp);
689 if (dorade_verbose) {
690 dorade_print_ray_info(ri);
692 pi = dorade_read_platform_info(fp);
693 if (dorade_verbose) {
694 dorade_print_platform_info(pi);
696 sr->data_ray[i]->ray_info = ri;
697 sr->data_ray[i]->platform_info = pi;
698 sr->data_ray[i]->parameter_data = (Parameter_data **) calloc(nparam, sizeof(Parameter_data *));
699 sr->data_ray[i]->data_len = (int *) calloc(nparam, sizeof(int));
700 sr->data_ray[i]->word_size = (int *) calloc(nparam, sizeof(int));
701 sr->data_ray[i]->nparam = nparam;
703 for (j=0; j<nparam; j++) {
704 pd = dorade_read_parameter_data(fp);
705 /* Perform big endian conversion. */
706 len = pd->len /* Use pd->len for now. */
707 - sizeof(pd->code) /* Remove a few bytes from */
708 - sizeof(pd->len) /* the count. */
710 sr->data_ray[i]->parameter_data[j] = pd;
711 sr->data_ray[i]->data_len[j] = len;
712 if (parameter_desc[j]->parameter_type == 2)
713 sr->data_ray[i]->word_size[j] = 2; /* 2 bytes per word */
714 else if (parameter_desc[j]->parameter_type == 3 ||
715 parameter_desc[j]->parameter_type == 4)
716 sr->data_ray[i]->word_size[j] = 4; /* 4 bytes per word */
718 if (do_swap) { /* Numbers were read big-endian. */
719 if (sr->data_ray[i]->word_size[j] == 2)
720 for (k=0; k<len; k+=2)
721 swap_2_bytes(&pd->data[k]);
722 else if (sr->data_ray[i]->word_size[j] == 4)
723 for (k=0; k<len; k+=4)
724 swap_4_bytes(&pd->data[k]);
732 /* MEMORY MANAGEMENT ROUTINES */
734 /**********************************************************************/
736 /* dorade_free_data_ray */
738 /**********************************************************************/
739 void dorade_free_data_ray(Data_ray *r)
742 if (r == NULL) return;
745 free(r->platform_info);
746 if (r->parameter_data) {
747 for (i=0; i<r->nparam; i++)
748 free(r->parameter_data[i]);
749 free(r->parameter_data);
754 /**********************************************************************/
756 /* dorade_free_sweep */
758 /**********************************************************************/
759 void dorade_free_sweep(Sweep_record *s)
762 if (s == NULL) return;
765 for (i=0; i<s->nrays; i++)
766 dorade_free_data_ray(s->data_ray[i]);
769 if (s->s_info) free(s->s_info);