]> Pileus Git - ~andy/rsl/blob - src/uf_to_radar.c
d9d0673b842061b69ebd50b9380f2b2f4c363aa1
[~andy/rsl] / src / uf_to_radar.c
1 /*
2     NASA/TRMM, Code 910.1.
3     This is the TRMM Office Radar Software Library.
4     Copyright (C) 1996, 1997
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 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include "rsl.h"
28
29 extern int radar_verbose_flag;
30 /* Changed old buffer size (16384) for larger dualpol files.  BLK 5/18/2011 */
31 typedef short UF_buffer[20000]; /* Some UF files are bigger than 4096
32                                  * that the UF doc's specify.
33                                  */
34
35 #define UF_MORE 0
36 #define UF_DONE 1
37
38 static float (*f)(Range x);
39 static Range (*invf)(float x);
40
41 Volume *reset_nsweeps_in_volume(Volume *volume)
42 {
43   int i;
44   if (volume == NULL) return NULL;
45   for (i=volume->h.nsweeps; i>0; i--)
46     if (volume->sweep[i-1] != NULL) {
47       volume->h.nsweeps = i;
48       break;
49     }
50   return volume;
51 }
52 Radar *reset_nsweeps_in_all_volumes(Radar *radar)
53 {
54   int i;
55   if (radar == NULL) return NULL;
56   for (i=0; i<radar->h.nvolumes; i++)
57     radar->v[i] = reset_nsweeps_in_volume(radar->v[i]);
58   return radar;
59 }
60
61 Volume *copy_sweeps_into_volume(Volume *new_volume, Volume *old_volume)
62 {
63   int i;
64   int nsweeps;
65   if (old_volume == NULL) return new_volume;
66   if (new_volume == NULL) return new_volume;
67   nsweeps = new_volume->h.nsweeps; /* Save before copying old header. */
68   new_volume->h = old_volume->h;
69   new_volume->h.nsweeps = nsweeps;
70   for (i=0; i<old_volume->h.nsweeps; i++)
71     new_volume->sweep[i] = old_volume->sweep[i]; /* Just copy pointers. */
72   /* Free the old sweep array, not the pointers to sweeps. */
73   free(old_volume->sweep);
74   return new_volume;
75 }
76
77 void swap2(short *buf, int n)
78 {
79   short *end_addr;
80   end_addr = buf + n;
81   while (buf < end_addr) {
82     swap_2_bytes(buf);
83     buf++;
84   }
85 }
86
87
88 /********************************************************************/
89 /*********************************************************************/
90 /*                                                                   */
91 /*                  uf_into_radar                                    */
92 /*                                                                   */
93 /*  By: John Merritt                                                 */
94 /*      Space Applications Corporation                               */
95 /*      August 26, 1994                                              */
96 /*********************************************************************/
97 int uf_into_radar(UF_buffer uf, Radar **the_radar)
98 {
99   
100 /* Missing data flag : -32768 when a signed short. */
101 #define UF_NO_DATA 0X8000
102   
103   /* Any convensions may be observed, however, Radial Velocity must be VE. */
104   /* Typically:
105    *    DM = Reflectivity (dB(mW)).
106    *    DZ = Reflectivity (dBZ).
107    *    VR = Radial Velocity.
108    *    CZ = Corrected Reflectivity. (Quality controlled: AP removed, etc.)
109    *    SW = Spectrum Width.
110    *    DR = Differential Reflectivity.
111    *    XZ = X-band Reflectivity.
112    *
113    * These fields may appear in any order in the UF file.
114    *
115    * RETURN:
116    *   UF_DONE if we're done with the UF ingest.
117    *   UF_MORE if we need more UF data.
118    */
119   
120   /* These are pointers to various locations within the UF buffer 'uf'.
121    * They are used to index the different components of the UF structure in
122    * a manor consistant with the UF documentation.  For instance, uf_ma[1]
123    * will be equivalenced to the second word (2 bytes/each) of the UF
124    * buffer.
125    */
126   short *uf_ma;  /* Mandatory header block. */
127   short *uf_lu;  /* Local Use header block.  */
128   short *uf_dh;  /* Data header.  */
129   short *uf_fh;  /* Field header. */
130   short *uf_data; /* Data. */
131   
132   /* The length of each header. */
133   int len_data, len_lu;
134   
135   int current_fh_index; 
136   float scale_factor;
137   
138   int nfields, isweep, ifield, iray, i, j, m;
139   static int pulled_time_from_first_ray = 0;
140   static int need_scan_mode = 1;
141   char *field_type; /* For printing the field type upon error. */
142   short proj_name[4];
143   Ray *ray;
144   Sweep *sweep;
145   Radar *radar;
146   float x;
147   short missing_data;
148   Volume *new_volume;
149   int nbins;
150   extern int rsl_qfield[];
151   extern int *rsl_qsweep; /* See RSL_read_these_sweeps in volume.c */
152   extern int rsl_qsweep_max;
153
154   radar = *the_radar;
155
156 /*
157  * The organization of the Radar structure is by volumes, then sweeps, then
158  * rays, then gates.  This is different from the UF file organization.
159  * The UF format is sweeps, rays, then gates for all field types (volumes).
160  */
161
162
163 /* Set up all the UF pointers. */
164   uf_ma = uf;
165   uf_lu = uf + uf_ma[3] - 1;
166   uf_dh = uf + uf_ma[4] - 1;
167
168   nfields =  uf_dh[0];
169   isweep = uf_ma[9] - 1;
170
171   if (rsl_qsweep != NULL) {
172     if (isweep > rsl_qsweep_max) return UF_DONE;
173     if (rsl_qsweep[isweep] == 0) return UF_MORE;
174   }
175
176
177 /* Here is a sticky part.  We must make sure that if we encounter any
178  * additional fields that were not previously present, that we are able
179  * to load them.  This will require us to copy the entire radar structure
180  * and whack off the old one.  But, we must be sure that it really is a
181  * new field.  This is not so trivial as a couple of lines of code; I will
182  * have to think about this a little bit more.  See STICKYSOLVED below.
183  */
184 #ifdef STICKYSOLVED
185   if (radar == NULL) radar = RSL_new_radar(nfields);
186   /* Sticky solution here. */
187 #else
188   if (radar == NULL) {
189     radar = RSL_new_radar(MAX_RADAR_VOLUMES);
190     *the_radar = radar;
191     pulled_time_from_first_ray = 0;
192     for (i=0; i<MAX_RADAR_VOLUMES; i++)
193       if (rsl_qfield[i]) /* See RSL_select_fields in volume.c */
194         radar->v[i] = RSL_new_volume(20);
195   }
196   
197 #endif
198
199   if (need_scan_mode) {
200     /* PPI and RHI are enum constants defined in rsl.h */
201     if (uf_ma[34] == 1) radar->h.scan_mode = PPI;
202     else if (uf_ma[34] == 3) radar->h.scan_mode = RHI;
203     else {
204       fprintf(stderr,"Warning: UF sweep mode = %d\n", uf_ma[34]);
205       fprintf(stderr,"    Expected 1 or 3 (PPI or RHI)\n");
206       fprintf(stderr,"    Setting radar->h.scan_mode to PPI\n");
207       radar->h.scan_mode = PPI;
208     }
209     need_scan_mode = 0;
210   }
211
212 /* For LITTLE ENDIAN:
213  * WE "UNSWAP" character strings.  Because there are so few of them,
214  * it is easier to catch them here.  The entire UF buffer is swapped prior
215  * to entry to here, therefore, undo-ing these swaps; sets the
216  * character strings right.
217  */
218
219   for (i=0; i<nfields; i++) {
220     if (little_endian()) swap_2_bytes(&uf_dh[3+2*i]); /* Unswap. */
221     ifield = -1;
222     field_type = (char *)&uf_dh[3+2*i];
223     for (j=0; j<MAX_RADAR_VOLUMES; j++) {
224       if (strncmp(field_type, RSL_ftype[j], 2) == 0) {
225         ifield = j;
226         break;
227       }
228     }
229     if (ifield < 0) { /* DON'T know how to handle this yet. */
230       fprintf(stderr, "Unknown field type %c%c\n", (char)field_type[0],
231               (char)field_type[1]);
232       continue;
233     }
234
235     f = RSL_f_list[ifield];
236     invf = RSL_invf_list[ifield];
237
238     /* Do we place the data into this volume? */
239     if (radar->v[ifield] == NULL) continue; /* Nope. */
240
241     if (isweep >= radar->v[ifield]->h.nsweeps) { /* Exceeded sweep limit.
242                                                   * Allocate more sweeps.
243                                                   * Copy all previous sweeps.
244                                                   */
245       if (radar_verbose_flag)
246         fprintf(stderr,"Exceeded sweep allocation of %d. Adding 20 more.\n", isweep);
247       new_volume = RSL_new_volume(radar->v[ifield]->h.nsweeps+20);
248       new_volume = copy_sweeps_into_volume(new_volume, radar->v[ifield]);
249       radar->v[ifield] = new_volume;
250     }
251
252     if (radar->v[ifield]->sweep[isweep] == NULL) {
253       if (radar_verbose_flag)
254         fprintf(stderr,"Allocating new sweep for field %d, isweep %d\n", ifield, isweep);
255       radar->v[ifield]->sweep[isweep] = RSL_new_sweep(1000);
256       radar->v[ifield]->sweep[isweep]->h.nrays = 0; /* Increment this for each
257                                                      * ray encountered.
258                                                      */
259       radar->v[ifield]->h.f = f;
260       radar->v[ifield]->h.invf = invf;
261       radar->v[ifield]->sweep[isweep]->h.f = f;
262       radar->v[ifield]->sweep[isweep]->h.invf = invf;
263       radar->v[ifield]->sweep[isweep]->h.sweep_num = uf_ma[9];
264       radar->v[ifield]->sweep[isweep]->h.elev = uf_ma[35] / 64.0;
265     }
266     
267     
268
269     current_fh_index = uf_dh[4+2*i];
270     uf_fh = uf + current_fh_index - 1;
271     sweep = radar->v[ifield]->sweep[isweep];
272     iray =  sweep->h.nrays;
273     nbins = uf_fh[5];
274     radar->v[ifield]->sweep[isweep]->ray[iray] = RSL_new_ray(nbins);
275     ray   = radar->v[ifield]->sweep[isweep]->ray[iray];
276     sweep->h.nrays += 1;
277
278
279     if (ray) {
280         /* 
281          * ---- Beginning of MANDATORY HEADER BLOCK.
282          */
283       ray->h.ray_num = uf_ma[7];
284       if (little_endian()) swap2(&uf_ma[10], 8);
285       memcpy(radar->h.radar_name, &uf_ma[10], 8);
286       if (little_endian()) swap2(&uf_ma[10], 8/2);
287       memcpy(radar->h.name, &uf_ma[14], 8);
288       if (little_endian()) swap2(&uf_ma[14], 8/2);
289         
290       /* All components of lat/lon are the same sign.  If not, then
291        * what ever wrote the UF was in error.  A simple RSL program
292        * can repair the damage, however, not here.
293        */
294       ray->h.lat = uf_ma[18] + uf_ma[19]/60.0 + uf_ma[20]/64.0/3600;
295       ray->h.lon = uf_ma[21] + uf_ma[22]/60.0 + uf_ma[23]/64.0/3600;
296       ray->h.alt      = uf_ma[24];
297       ray->h.year     = uf_ma[25];
298       if (ray->h.year < 1900) {
299         ray->h.year += 1900;
300         if (ray->h.year < 1980) ray->h.year += 100; /* Year >= 2000. */
301       }
302       ray->h.month    = uf_ma[26];
303       ray->h.day      = uf_ma[27];
304       ray->h.hour     = uf_ma[28];
305       ray->h.minute   = uf_ma[29];
306       ray->h.sec      = uf_ma[30];
307       ray->h.azimuth  = uf_ma[32] / 64.0;
308
309       /* If Local Use Header is present and contains azimuth, use that
310        * azimuth for VR and SW. This is for WSR-88D, which runs separate
311        * scans for DZ and VR/SW at the lower elevations, which means DZ
312        * VR/SW and have different azimuths in the "same" ray.
313        */
314       len_lu = uf_ma[4] - uf_ma[3];
315       if (len_lu == 2 && (ifield == VR_INDEX || ifield == SW_INDEX)) {
316           if (strncmp((char *)uf_lu,"ZA",2) == 0 ||
317               strncmp((char *)uf_lu,"AZ",2) == 0)
318           ray->h.azimuth = uf_lu[1] / 64.0;
319       }
320       if (ray->h.azimuth < 0.) ray->h.azimuth += 360.; /* make it 0 to 360. */
321       ray->h.elev     = uf_ma[33] / 64.0;
322       ray->h.elev_num = sweep->h.sweep_num;
323       ray->h.fix_angle  = sweep->h.elev = uf_ma[35] / 64.0;
324       ray->h.azim_rate  = uf_ma[36] / 64.0;
325       ray->h.sweep_rate = ray->h.azim_rate * (60.0/360.0);
326       missing_data      = uf_ma[44];
327
328       if (pulled_time_from_first_ray == 0) {
329         radar->h.height = uf_ma[24];
330         radar->h.latd = uf_ma[18];
331         radar->h.latm = uf_ma[19];
332         radar->h.lats = uf_ma[20] / 64.0;
333         radar->h.lond = uf_ma[21];
334         radar->h.lonm = uf_ma[22];
335         radar->h.lons = uf_ma[23] / 64.0;
336         radar->h.year  = ray->h.year;
337         radar->h.month = ray->h.month;
338         radar->h.day   = ray->h.day;
339         radar->h.hour  = ray->h.hour;
340         radar->h.minute = ray->h.minute;
341         radar->h.sec    = ray->h.sec;
342         strcpy(radar->h.radar_type, "uf");
343         pulled_time_from_first_ray = 1;
344       }
345       /*
346        * ---- End of MANDATORY HEADER BLOCK.
347        */
348       
349       /* ---- Optional header used for MCTEX files. */
350         /* If this is a MCTEX file, the first 4 words following the
351              mandatory header contain the string 'MCTEX'. */
352       memcpy(proj_name, (short *)(uf + uf_ma[2] - 1), 8);
353       if (little_endian()) swap2(proj_name, 4);
354
355
356       /* ---- Local Use Header (if present) was checked during Mandatory
357        *      Header processing above.
358        */
359       
360       /* ---- Begining of FIELD HEADER. */
361       uf_fh = uf+current_fh_index - 1;
362       scale_factor      = uf_fh[1];
363       ray->h.range_bin1 = uf_fh[2] * 1000.0 + uf_fh[3]; 
364       ray->h.gate_size  = uf_fh[4];
365
366       ray->h.nbins      = uf_fh[5];
367       ray->h.pulse_width  = uf_fh[6]/(RSL_SPEED_OF_LIGHT/1.0e6);
368
369         if (strncmp((char *)proj_name, "MCTEX", 5) == 0)  /* MCTEX? */
370         {
371             /* The beamwidth values are not correct in Mctex UF files. */
372             ray->h.beam_width = 1.0;
373             sweep->h.beam_width = ray->h.beam_width;
374             sweep->h.horz_half_bw = ray->h.beam_width/2.0;
375             sweep->h.vert_half_bw = ray->h.beam_width/2.0;
376         }
377         else  /* Not MCTEX */
378         {
379             ray->h.beam_width = uf_fh[7] / 64.0;
380             sweep->h.beam_width = uf_fh[7]  / 64.0;
381             sweep->h.horz_half_bw = uf_fh[7] / 128.0; /* DFF 4/4/95 */
382             sweep->h.vert_half_bw = uf_fh[8] / 128.0; /* DFF 4/4/95 */
383         }           
384         /*      fprintf (stderr, "uf_fh[7] = %d, [8] = %d\n", (int)uf_fh[7], (int)uf_fh[8]); */
385         if((int)uf_fh[7] == -32768) {
386             ray->h.beam_width     = 1;
387             sweep->h.beam_width   = 1;
388             sweep->h.horz_half_bw = .5;
389             sweep->h.vert_half_bw = .5;
390         }
391           
392       ray->h.frequency    = uf_fh[9]  / 64.0;
393       ray->h.wavelength   = uf_fh[11] / 64.0 / 100.0;  /* cm to m. */
394       ray->h.pulse_count  = uf_fh[12];
395       if (ifield == DZ_INDEX || ifield == ZT_INDEX) {
396         radar->v[ifield]->h.calibr_const  = uf_fh[16] / 100.0;
397                             /* uf value scaled by 100 */
398       }
399       else {
400         radar->v[ifield]->h.calibr_const  = 0.0;
401       }
402       if (uf_fh[17] == (short)UF_NO_DATA) x = 0;
403       else x = uf_fh[17] / 1000000.0;  /* PRT in seconds. */
404       if (x != 0) {
405         ray->h.prf = 1/x;
406         ray->h.unam_rng = RSL_SPEED_OF_LIGHT / (2.0 * ray->h.prf * 1000.0);
407       }
408       else {
409         ray->h.prf = 0.0;
410         ray->h.unam_rng = 0.0;
411       }
412
413       if (VR_INDEX == ifield || VE_INDEX == ifield) {
414         ray->h.nyq_vel = uf_fh[19] / scale_factor;
415       }
416       
417       /* ---- End of FIELD HEADER. */
418       
419       ray->h.f = f;
420       ray->h.invf = invf;
421
422       /* ---- Begining of FIELD DATA. */
423       uf_data = uf+uf_fh[0] - 1;
424
425       len_data = ray->h.nbins;  /* Known because of RSL_new_ray. */
426       for (m=0; m<len_data; m++) {
427         if (uf_data[m] == (short)UF_NO_DATA)
428           ray->range[m] = invf(BADVAL); /* BADVAL */
429         else {
430           if(uf_data[m] == missing_data)
431             ray->range[m] = invf(NOECHO); /* NOECHO */
432           else
433             ray->range[m] = invf((float)uf_data[m]/scale_factor);
434         }
435       }
436     }
437   }
438   return UF_MORE;
439 }
440
441
442 /*********************************************************************/
443 /*                                                                   */
444 /*                  swap_uf_buffer                                   */
445 /*                                                                   */
446 /*  By: John Merritt                                                 */
447 /*      Space Applications Corporation                               */
448 /*      October 4, 1994                                              */
449 /*********************************************************************/
450 void swap_uf_buffer(UF_buffer uf)
451 {
452   short *addr_end;
453
454   addr_end = uf + sizeof(UF_buffer)/sizeof(short);
455   while (uf < addr_end)
456     swap_2_bytes(uf++);
457 }
458
459 enum UF_type {NOT_UF, TRUE_UF, TWO_BYTE_UF, FOUR_BYTE_UF};
460
461
462 /*********************************************************************/
463 /*                                                                   */
464 /*                  RSL_uf_to_radar_fp                               */
465 /*                                                                   */
466 /*  By: John Merritt                                                 */
467 /*      Space Applications Corporation                               */
468 /*      September 22, 1995                                           */
469 /*********************************************************************/
470 Radar *RSL_uf_to_radar_fp(FILE *fp)
471 {
472   union {
473     char buf[6];
474     short sword;
475     int word;
476   } magic;
477   Radar *radar;
478   int nbytes;
479   short sbytes;
480   UF_buffer uf;
481   enum UF_type uf_type;
482 #define NEW_BUFSIZ 16384
483
484
485   radar = NULL;
486   /* setvbuf(fp,NULL,_IOFBF,(size_t)NEW_BUFSIZ); * Faster i/o? */
487   if (fread(magic.buf, sizeof(char), 6, fp) <= 0) return NULL;
488 /*
489  * Check for fortran record length delimeters, NCAR kludge.
490  */
491   if (strncmp("UF", magic.buf, 2) == 0) uf_type = TRUE_UF;
492   else if (strncmp("UF", &magic.buf[2], 2) == 0) uf_type = TWO_BYTE_UF;
493   else if (strncmp("UF", &magic.buf[4], 2) == 0) uf_type = FOUR_BYTE_UF;
494   else uf_type = NOT_UF;
495   
496   switch (uf_type) {
497   case FOUR_BYTE_UF:
498     if (radar_verbose_flag) fprintf(stderr,"UF file with 4 byte FORTRAN record delimeters.\n");
499     /* Handle first record specially, since we needed magic information. */
500     nbytes = magic.word;
501     if (little_endian()) swap_4_bytes(&nbytes);
502     memcpy(uf, &magic.buf[4], 2);
503     if (fread(&uf[1], sizeof(char), nbytes-2, fp) !=  nbytes-2)
504         perror("RSL_uf_to_radar_fp: short read");
505     if (little_endian()) swap_uf_buffer(uf);
506     if (fread(&nbytes, sizeof(int), 1, fp) !=  1)
507         perror("RSL_uf_to_radar_fp: short read");
508     if (uf_into_radar(uf, &radar) == UF_DONE) break;
509     /* Now the rest of the file. */
510     while(fread(&nbytes, sizeof(int), 1, fp) > 0) {
511       if (little_endian()) swap_4_bytes(&nbytes);
512       
513       if (fread(uf, sizeof(char), nbytes, fp) !=  nbytes)
514         perror("RSL_uf_to_radar_fp: short read");
515       if (little_endian()) swap_uf_buffer(uf);
516       
517       if (fread(&nbytes, sizeof(int), 1, fp) !=  1)
518         perror("RSL_uf_to_radar_fp: short read");
519       
520       if (uf_into_radar(uf, &radar) == UF_DONE) break;
521     }
522     break;
523
524   case TWO_BYTE_UF:
525     if (radar_verbose_flag) fprintf(stderr,"UF file with 2 byte FORTRAN record delimeters.\n");
526     /* Handle first record specially, since we needed magic information. */
527     sbytes = magic.sword;
528     if (little_endian()) swap_2_bytes(&sbytes);
529     memcpy(uf, &magic.buf[2], 4);
530     if (fread(&uf[2], sizeof(char), sbytes-4, fp) !=  sbytes-4)
531         perror("RSL_uf_to_radar_fp: short read");
532     if (little_endian()) swap_uf_buffer(uf);
533     if (fread(&sbytes, sizeof(short), 1, fp) !=  1)
534         perror("RSL_uf_to_radar_fp: short read");
535     uf_into_radar(uf, &radar);
536     /* Now the rest of the file. */
537     while(fread(&sbytes, sizeof(short), 1, fp) > 0) {
538       if (little_endian()) swap_2_bytes(&sbytes);
539       
540       if (fread(uf, sizeof(char), sbytes, fp) !=  sbytes)
541         perror("RSL_uf_to_radar_fp: short read");
542       if (little_endian()) swap_uf_buffer(uf);
543       
544       if (fread(&sbytes, sizeof(short), 1, fp) !=  1)
545         perror("RSL_uf_to_radar_fp: short read");
546       
547       if (uf_into_radar(uf, &radar) == UF_DONE) break;
548     }
549     break;
550
551   case TRUE_UF:
552     if (radar_verbose_flag) fprintf(stderr,"UF file with no FORTRAN record delimeters.  Good.\n");
553     /* Handle first record specially, since we needed magic information. */
554     memcpy(&sbytes, &magic.buf[2], 2); /* Record length is in word #2. */
555     if (little_endian()) swap_2_bytes(&sbytes); /* # of 2 byte words. */
556
557     memcpy(uf, &magic.buf[0], 6);
558     if (fread(&uf[3], sizeof(short), sbytes-3, fp) !=  sbytes-3)
559         perror("RSL_uf_to_radar_fp: short read");
560     if (little_endian()) swap_uf_buffer(uf);
561     uf_into_radar(uf, &radar);
562     /* Now the rest of the file. */
563     while(fread(uf, sizeof(short), 2, fp) > 0) {
564       memcpy(&sbytes, &uf[1], 2);  /* Record length is in word #2. */
565       if (little_endian()) swap_2_bytes(&sbytes);
566       
567       if (fread(&uf[2], sizeof(short), sbytes-2, fp) !=  sbytes-2)
568         perror("RSL_uf_to_radar_fp: short read");  /* Have words 1,2. */
569       if (little_endian()) swap_uf_buffer(uf);
570       
571       if (uf_into_radar(uf, &radar) == UF_DONE) break;
572     }
573     break;
574     
575   case NOT_UF: return NULL; break;
576   }
577   radar = reset_nsweeps_in_all_volumes(radar);
578   radar = RSL_prune_radar(radar);
579
580   return radar;
581 }
582
583
584 /*********************************************************************/
585 /*                                                                   */
586 /*                  RSL_uf_to_radar                                  */
587 /*                                                                   */
588 /*  By: John Merritt                                                 */
589 /*      Space Applications Corporation                               */
590 /*      September 22, 1995                                           */
591 /*********************************************************************/
592 Radar *RSL_uf_to_radar(char *infile)
593 {
594 /*
595  * This routine ingests a UF file and fills the Radar structure.
596  * This routine allocates space via the system routine malloc.
597  *
598  * If *infile is NULL, read from stdin.
599  */
600   FILE *fp;
601   Radar *radar;
602   
603   radar = NULL;
604   if (infile == NULL) {
605     int save_fd;
606     save_fd = dup(0);
607     fp = fdopen(save_fd, "r");
608   }  else if ((fp = fopen(infile, "r")) == NULL) {
609     perror(infile);
610     return radar;
611   }
612   fp = uncompress_pipe(fp); /* Transparently gunzip. */
613   radar = RSL_uf_to_radar_fp(fp);
614   rsl_pclose(fp);
615     
616   return radar;
617 }