]> Pileus Git - ~andy/rsl/blob - dorade.c
Initial import
[~andy/rsl] / dorade.c
1 /*
2     NASA/TRMM, Code 910.1.
3     This is the TRMM Office Radar Software Library.
4     Copyright (C) 1999
5             John H. Merritt
6             Space Applications Corporation
7             Vienna, Virginia
8
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.
13
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.
18
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.
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <netinet/in.h>
27 #include <string.h>
28 #include "dorade.h"
29
30 int dorade_verbose = 0;
31
32 void dorade_verbose_on()
33 {
34   dorade_verbose = 1;
35 }
36 void dorade_verbose_off()
37 {
38   dorade_verbose = 0;
39 }
40
41 /**********************************************************************/
42 /*                                                                    */
43 /*                      dorade_read_comment_block                     */
44 /*                                                                    */
45 /**********************************************************************/
46 Comment_block *dorade_read_comment_block(FILE *in)
47 {
48   Comment_block *cb;
49   cb = (Comment_block *) calloc(1, sizeof(Comment_block));
50   if (cb == NULL) {
51         perror("dorade_read_comment_block");
52         return NULL;
53   }
54   fread(cb->code, sizeof(cb->code), 1, in);
55   fread(&cb->len, sizeof(cb->len), 1, in);   cb->len = ntohl(cb->len);
56   cb->comment = (char *) calloc(cb->len, sizeof(char));
57   if (cb->comment == NULL) {
58         perror("dorade_read_comment_block: cb->comment");
59         return cb;
60   }
61   fread(cb->comment, sizeof(char), cb->len, in);
62   return cb;
63 }
64
65 /**********************************************************************/
66 /*                                                                    */
67 /*                      dorade_read_volume_desc                       */
68 /*                                                                    */
69 /**********************************************************************/
70 Volume_desc    *dorade_read_volume_desc    (FILE *in)
71 {
72   Volume_desc *vd;
73
74   vd = (Volume_desc *) calloc(1, sizeof(Volume_desc));
75   if(!vd) {
76         perror("dorade_read_volume_desc");
77         return NULL;
78   }
79
80   fread(vd, sizeof(Volume_desc), 1, in);
81   /* Now, convert from Big Endian. */
82   vd->len = ntohl(vd->len);
83   vd->version = ntohs(vd->version);
84   vd->volume_number = ntohs(vd->volume_number);
85   vd->max_bytes = ntohl(vd->max_bytes);
86   vd->year = ntohs(vd->year);
87   vd->month = ntohs(vd->month);
88   vd->day = ntohs(vd->day);
89   vd->hour = ntohs(vd->hour);
90   vd->minute = ntohs(vd->minute);
91   vd->second = ntohs(vd->second);
92   vd->gen_year = ntohs(vd->gen_year);
93   vd->gen_month = ntohs(vd->gen_month);
94   vd->gen_day = ntohs(vd->gen_day);
95   vd->nsensors = ntohs(vd->nsensors);
96   return vd;
97 }
98
99 extern int little_endian(void);
100 extern void swap_4_bytes(void *word);
101 extern void swap_2_bytes(void *word);
102
103
104 /* Sensor descriptor routines. */
105 /**********************************************************************/
106 /*                                                                    */
107 /*                      dorade_read_radar_desc                        */
108 /*                                                                    */
109 /**********************************************************************/
110 Radar_desc     *dorade_read_radar_desc     (FILE *in)
111 {
112   Radar_desc *rd;
113   int i;
114
115   rd = (Radar_desc *) calloc(1, sizeof(Radar_desc));
116   if(!rd) {
117         perror("dorade_read_radar_desc");
118         return NULL;
119   }
120
121   fread(rd, sizeof(Radar_desc), 1, in);
122   /* Now, convert from Big Endian. */
123   if (little_endian()) {
124         swap_4_bytes(&rd->len);
125         swap_4_bytes(&rd->radar_constant); /* Yes, even the ieee floating values. */
126         swap_4_bytes(&rd->peak_power);
127         swap_4_bytes(&rd->noise_power);
128         swap_4_bytes(&rd->rcvr_gain);
129         swap_4_bytes(&rd->ant_gain);
130         swap_4_bytes(&rd->radar_system_gain);
131         swap_4_bytes(&rd->horizontal_beam_width);
132         swap_4_bytes(&rd->vertical_beam_width);
133         swap_2_bytes(&rd->radar_type);
134         swap_2_bytes(&rd->scan_mode);
135         swap_4_bytes(&rd->scan_rate);
136         swap_4_bytes(&rd->start_angle);
137         swap_4_bytes(&rd->stop_angle);
138         swap_2_bytes(&rd->nparam_desc);
139         swap_2_bytes(&rd->ndesc);
140         swap_2_bytes(&rd->compress_code);
141         swap_2_bytes(&rd->compress_algo);
142         swap_4_bytes(&rd->data_reduction_param1);
143         swap_4_bytes(&rd->data_reduction_param2);
144         swap_4_bytes(&rd->longitude);
145         swap_4_bytes(&rd->latitude);
146         swap_4_bytes(&rd->altitude);
147         swap_4_bytes(&rd->unambiguous_velocity);
148         swap_4_bytes(&rd->unambiguous_range);
149         swap_2_bytes(&rd->nfreq);
150         swap_2_bytes(&rd->npulse_periods);
151         for (i=0; i<5; i++) {
152           swap_4_bytes(&rd->freq[i]);
153           swap_4_bytes(&rd->period[i]);
154         }
155   }
156   return rd;
157 }
158 /**********************************************************************/
159 /*                                                                    */
160 /*                      dorade_read_parameter_desc                    */
161 /*                                                                    */
162 /**********************************************************************/
163 Parameter_desc *dorade_read_parameter_desc (FILE *in)
164 {
165   Parameter_desc *pd;
166
167   pd = (Parameter_desc *) calloc(1, sizeof(Parameter_desc));
168   if(!pd) {
169         perror("dorade_read_parameter_desc");
170         return NULL;
171   }
172
173   fread(pd, sizeof(Parameter_desc), 1, in);
174   /* Now, convert from Big Endian. */
175   if (little_endian()) {
176         swap_4_bytes(&pd->len);
177         swap_2_bytes(&pd->ipp);
178         swap_2_bytes(&pd->xmit_freq);
179         swap_4_bytes(&pd->rcvr_bandwidth);
180         swap_2_bytes(&pd->pulse_width);
181         swap_2_bytes(&pd->polarization);
182         swap_2_bytes(&pd->nsamp_in_dwell_time);
183         swap_2_bytes(&pd->parameter_type);
184         swap_4_bytes(&pd->threshold_value);
185         swap_4_bytes(&pd->scale_factor);
186         swap_4_bytes(&pd->offset_factor);
187         swap_4_bytes(&pd->missing_data_flag);
188   }
189   return pd;
190 }
191
192 /**********************************************************************/
193 /*                                                                    */
194 /*                      dorade_read_cell_range_vector                 */
195 /*                                                                    */
196 /**********************************************************************/
197 Cell_range_vector      *dorade_read_cell_range_vector     (FILE *in)
198 {
199   Cell_range_vector *cv;
200   char *buff;
201   int i;
202
203   cv = (Cell_range_vector *) calloc(1, sizeof(Cell_range_vector));
204   if(!cv) {
205         perror("dorade_read_cell_range_vector");
206         return NULL;
207   }
208
209   fread(&cv->code, sizeof(cv->code), 1, in);
210   fread(&cv->len, sizeof(cv->len), 1, in);
211   fread(&cv->ncells, sizeof(cv->ncells), 1, in);
212   if (little_endian()) {
213         swap_4_bytes(&cv->len);
214         swap_4_bytes(&cv->ncells);
215   }
216   cv->range_cell = (float *)calloc(cv->ncells, sizeof(float));
217   if (!cv->range_cell) {
218         perror("dorade_read_cell_range_vector: cv->range_cell");
219         return cv;
220   }
221   fread(cv->range_cell, sizeof(float), cv->ncells, in);
222
223   if (little_endian()) {
224         for (i=0; i<cv->ncells; i++)
225           swap_4_bytes(&cv->range_cell[i]);
226   }
227
228   /* Usually reading the range cells does not read to the end
229    * of the Cell_range_vector structure.  We may be reading
230    * a non seekable device!
231    */
232   i = cv->len            /* Remove a few bytes that precede. */
233         - sizeof(cv->code)
234         - sizeof(cv->len)
235         - sizeof(cv->ncells)
236         - cv->ncells*4;
237   buff = (char *)malloc(i);
238   if (!buff) return cv;
239   fread(buff, sizeof(char), i, in);
240   free(buff);
241   return cv;
242 }
243
244 /**********************************************************************/
245 /*                                                                    */
246 /*                      dorade_read_correction_factor_desc            */
247 /*                                                                    */
248 /**********************************************************************/
249 Correction_factor_desc *dorade_read_correction_factor_desc(FILE *in)
250 {
251   Correction_factor_desc *cf;
252
253   cf = (Correction_factor_desc *) calloc(1, sizeof(Correction_factor_desc));
254   if(!cf) {
255         perror("dorade_read_correction_factor_desc");
256         return NULL;
257   }
258
259   fread(cf, sizeof(Correction_factor_desc), 1, in);
260   /* Now, convert from Big Endian. */
261   if (little_endian()) {
262         swap_4_bytes(&cf->len);
263         swap_4_bytes(&cf->azimuth);
264         swap_4_bytes(&cf->elevation);
265         swap_4_bytes(&cf->range);
266         swap_4_bytes(&cf->longitude);
267         swap_4_bytes(&cf->latitude);
268         swap_4_bytes(&cf->altitude);
269         swap_4_bytes(&cf->height);
270         swap_4_bytes(&cf->speed_east_west);
271         swap_4_bytes(&cf->speed_north_south);
272         swap_4_bytes(&cf->vertical_velocity);
273         swap_4_bytes(&cf->heading);
274         swap_4_bytes(&cf->roll);
275         swap_4_bytes(&cf->pitch);
276         swap_4_bytes(&cf->drift);
277         swap_4_bytes(&cf->rotation_angle);
278         swap_4_bytes(&cf->tilt_angle);
279   }
280   return cf;
281 }
282
283 /**********************************************************************/
284 /*                                                                    */
285 /*                      dorade_read_sensor                            */
286 /*                                                                    */
287 /**********************************************************************/
288 Sensor_desc            *dorade_read_sensor (FILE *in)
289
290          /* Read one 'Sensor #n' descriptor from FILE. */
291 {
292   Sensor_desc            *sd;
293   int i;
294
295   sd = (Sensor_desc *) calloc (1, sizeof(Sensor_desc));
296   if (!sd) {
297         perror("dorade_read_sensor");
298         return NULL;
299   }
300
301   sd->radar_desc = dorade_read_radar_desc(in);
302   sd->nparam = sd->radar_desc->nparam_desc;
303
304   sd->p_desc = (Parameter_desc **) calloc(sd->nparam, sizeof(Parameter_desc *));
305   if (!sd->p_desc) {
306         perror("dorade_read_sensor: sd->p_desc");
307         return sd;
308   }
309   for (i=0; i<sd->nparam; i++) {
310         sd->p_desc[i] = dorade_read_parameter_desc(in);
311   }
312
313   sd->cell_range_vector = dorade_read_cell_range_vector(in);
314   sd->correction_factor_desc = dorade_read_correction_factor_desc(in);
315   return sd;
316 }
317
318
319 /**********************************************************************/
320 /*                                                                    */
321 /*                      dorade_read_sweep_info                        */
322 /*                                                                    */
323 /**********************************************************************/
324 Sweep_info *dorade_read_sweep_info(FILE *in)
325 {
326   Sweep_info *si;
327
328   si = (Sweep_info *) calloc(1, sizeof(Sweep_info));
329   if(!si) {
330         perror("dorade_read_sweep_info");
331         return NULL;
332   }
333
334   fread(si, sizeof(Sweep_info), 1, in);
335   /* FIXME: ?? For now, VOLD is what we expect when there
336    *           are no more SWIB.  This is a data driven EOF.
337    *           Returning NULL should suffice.
338    */
339   if(strncmp(si->code, "SWIB", 4) != 0) {
340         /* Ignore the rest of the file. */
341         free(si);
342         return NULL;
343   }
344
345   /* Now, convert from Big Endian. */
346   if (little_endian()) {
347         swap_4_bytes(&si->len);
348         swap_4_bytes(&si->sweep_num);
349         swap_4_bytes(&si->nrays);
350         swap_4_bytes(&si->start_angle);
351         swap_4_bytes(&si->stop_angle);
352         swap_4_bytes(&si->fixed_angle);
353         swap_4_bytes(&si->filter_flag);
354   }
355
356   return si;
357 }
358
359 /* Data Ray routines. */
360
361 /**********************************************************************/
362 /*                                                                    */
363 /*                      dorade_read_ray_info                          */
364 /*                                                                    */
365 /**********************************************************************/
366 Ray_info       *dorade_read_ray_info      (FILE *in)
367 {
368   Ray_info *ri;
369
370   ri = (Ray_info *) calloc(1, sizeof(Ray_info));
371   if(!ri) {
372         perror("dorade_read_ray_info");
373         return NULL;
374   }
375
376   fread(ri, sizeof(Ray_info), 1, in);
377   /* Now, convert from Big Endian. */
378   if (little_endian()) {
379         swap_4_bytes(&ri->len);
380         swap_4_bytes(&ri->sweep_num);
381         swap_4_bytes(&ri->jday);
382         swap_2_bytes(&ri->hour);
383         swap_2_bytes(&ri->minute);
384         swap_2_bytes(&ri->second);
385         swap_2_bytes(&ri->msec);
386         swap_4_bytes(&ri->azimuth);
387         swap_4_bytes(&ri->elevation);
388         swap_4_bytes(&ri->peak_power);
389         swap_4_bytes(&ri->scan_rate);
390         swap_4_bytes(&ri->status);
391   }
392
393   return ri;
394 }
395
396 /**********************************************************************/
397 /*                                                                    */
398 /*                      dorade_read_platform_info                     */
399 /*                                                                    */
400 /**********************************************************************/
401 Platform_info  *dorade_read_platform_info (FILE *in)
402 {
403   Platform_info *pi;
404
405   pi = (Platform_info *) calloc(1, sizeof(Platform_info));
406   if(!pi) {
407         perror("dorade_read_platform_info");
408         return NULL;
409   }
410
411   fread(pi, sizeof(Platform_info), 1, in);
412   /* Now, convert from Big Endian. */
413   if (little_endian()) {
414         swap_4_bytes(&pi->len);
415         swap_4_bytes(&pi->longitude);
416         swap_4_bytes(&pi->latitude);
417         swap_4_bytes(&pi->altitude);
418         swap_4_bytes(&pi->height);
419         swap_4_bytes(&pi->ew_speed);
420         swap_4_bytes(&pi->ns_speed);
421         swap_4_bytes(&pi->v_speed);
422         swap_4_bytes(&pi->heading);
423         swap_4_bytes(&pi->roll);
424         swap_4_bytes(&pi->pitch);
425         swap_4_bytes(&pi->drift);
426         swap_4_bytes(&pi->rotation);
427         swap_4_bytes(&pi->tilt);
428         swap_4_bytes(&pi->ew_wind_speed);
429         swap_4_bytes(&pi->ns_wind_speed);
430         swap_4_bytes(&pi->v_wind_speed);
431         swap_4_bytes(&pi->heading_rate);
432         swap_4_bytes(&pi->pitch_rate);
433   }
434
435   return pi;
436 }
437 /**********************************************************************/
438 /*                                                                    */
439 /*                      dorade_read_parameter_info                    */
440 /*                                                                    */
441 /**********************************************************************/
442
443 Parameter_data *dorade_read_parameter_data(FILE *in)
444 {
445   Parameter_data *pd;
446   int len;
447
448   pd = (Parameter_data *) calloc(1, sizeof(Parameter_data));
449   if(!pd) {
450         perror("dorade_read_parameter_data: pd");
451         return NULL;
452   }
453
454   fread(&pd->code, sizeof(pd->code), 1, in);
455   fread(&pd->len, sizeof(pd->len), 1, in);
456   fread(&pd->name, sizeof(pd->name), 1, in);
457   if (little_endian()) swap_4_bytes(&pd->len);
458   /* Length is in parameter data block? or calculate if from pd->len. */
459
460   len = pd->len  /* Use pd->len for now. */
461         - sizeof(pd->code) /* Remove a few bytes from */
462         - sizeof(pd->len)  /* the count.              */
463         - sizeof(pd->name);
464   pd->data = (char *)calloc(len, sizeof(char));
465   if (!pd->data) {
466         perror("dorade_read_parameter_data: pd->data");
467         return pd;
468   }
469   fread(pd->data, sizeof(char), len, in);
470   
471   /* FIXME: Big endian conversion in caller?  Is that the right place? */
472
473   return pd;
474 }
475 /**********************************************************************/
476 /*                                                                    */
477 /*                      dorade_read_sweep                             */
478 /*                                                                    */
479 /**********************************************************************/
480 Sweep_record *dorade_read_sweep(FILE *fp, Sensor_desc **sd)
481 {
482   Sweep_record   *sr;
483
484   Sweep_info     *si;
485   Ray_info       *ri;
486   Platform_info  *pi;
487   Parameter_data *pd;
488   Parameter_desc **parameter_desc;
489
490   int i, j, k,len;
491   int nparam;
492
493   sr = (Sweep_record *) calloc (1, sizeof(Sweep_record));
494   if (!sr) {
495         perror("dorade_read_sweep");
496         return NULL;
497   }
498
499   nparam         = sd[0]->nparam;
500   parameter_desc = sd[0]->p_desc;
501
502  /* Expect SWIB */
503   sr->s_info = si = dorade_read_sweep_info(fp);
504   if (!si) {
505         free(sr);
506         return NULL;  /* EOF or error. */
507   }
508   sr->nrays = si->nrays;
509   if (dorade_verbose) {
510         printf("=====< NEW SWIB >=====\n");
511         dorade_print_sweep_info(si);
512   }
513   sr->data_ray = (Data_ray **) calloc(si->nrays, sizeof(Data_ray *));
514   if (!sr->data_ray) {
515         free(sr);
516         return NULL;  /* EOF or error. */
517   }
518
519   for (i=0; i<si->nrays; i++) {
520         if (dorade_verbose) printf("---------- Ray %d ----------\n", i);
521         sr->data_ray[i] = (Data_ray *) calloc(1, sizeof(Data_ray));
522         if (!sr->data_ray[0]) {
523           free(sr);
524           return NULL;  /* EOF or error. */
525         }
526         ri = dorade_read_ray_info(fp);
527         if (dorade_verbose) {
528           dorade_print_ray_info(ri);
529         }
530         pi = dorade_read_platform_info(fp);
531         if (dorade_verbose) {
532           dorade_print_platform_info(pi);
533         }
534         sr->data_ray[i]->ray_info = ri;
535         sr->data_ray[i]->platform_info = pi;
536         sr->data_ray[i]->parameter_data = (Parameter_data **) calloc(nparam, sizeof(Parameter_data *));
537         sr->data_ray[i]->data_len  = (int *) calloc(nparam, sizeof(int));
538         sr->data_ray[i]->word_size = (int *) calloc(nparam, sizeof(int));
539         sr->data_ray[i]->nparam    = nparam;
540
541         for (j=0; j<nparam; j++) {
542           pd = dorade_read_parameter_data(fp);
543           /* Perform big endian conversion. */
544           len = pd->len  /* Use pd->len for now. */
545                 - sizeof(pd->code) /* Remove a few bytes from */
546                 - sizeof(pd->len)  /* the count.              */
547                 - sizeof(pd->name);
548           sr->data_ray[i]->parameter_data[j] = pd;
549           sr->data_ray[i]->data_len[j] = len;
550           if (parameter_desc[j]->parameter_type == 2)
551                 sr->data_ray[i]->word_size[j] = 2; /* 2 bytes per word */
552           else if (parameter_desc[j]->parameter_type == 3 ||
553                            parameter_desc[j]->parameter_type == 4)
554                 sr->data_ray[i]->word_size[j] = 4; /* 4 bytes per word */
555                 
556           if (little_endian()) { /* Numbers were read big-endian. */
557                 if (sr->data_ray[i]->word_size[j] == 2)
558                   for (k=0; k<len; k+=2)
559                         swap_2_bytes(&pd->data[k]);
560                 else if (sr->data_ray[i]->word_size[j] == 4)
561                   for (k=0; k<len; k+=4)
562                         swap_4_bytes(&pd->data[k]);
563           }
564         }
565   }
566   return sr;
567 }
568
569 /**********************************************************************/
570 /*                                                                    */
571 /*                      dorade_read_ray                               */
572 /*                                                                    */
573 /**********************************************************************/
574 Data_ray       *dorade_read_ray           (FILE *in);
575
576
577 /* MEMORY MANAGEMENT ROUTINES */
578
579 /**********************************************************************/
580 /*                                                                    */
581 /*                      dorade_free_data_ray                          */
582 /*                                                                    */
583 /**********************************************************************/
584 void dorade_free_data_ray(Data_ray *r)
585 {
586   int i;
587   if (r == NULL) return;
588
589   free(r->ray_info);
590   free(r->platform_info);
591   if (r->parameter_data) {
592         for (i=0; i<r->nparam; i++)
593           free(r->parameter_data[i]);
594         free(r->parameter_data);
595   }
596   free(r);
597 }
598
599 /**********************************************************************/
600 /*                                                                    */
601 /*                      dorade_free_sweep                             */
602 /*                                                                    */
603 /**********************************************************************/
604 void dorade_free_sweep(Sweep_record *s)
605 {
606   int i;
607   if (s == NULL) return;
608   
609   if (s->data_ray) {
610         for (i=0; i<s->nrays; i++)
611           dorade_free_data_ray(s->data_ray[i]);
612         free(s->data_ray);
613   }
614   if (s->s_info) free(s->s_info);
615   free(s);
616 }