]> Pileus Git - ~andy/rsl/blob - rainbow_to_radar.c
Changes from Bart (2009-10-28)
[~andy/rsl] / rainbow_to_radar.c
1 /*
2     NASA/TRMM, Code 912
3     This is the TRMM Office Radar Software Library.
4     Copyright (C) 2004
5             Bart Kelley
6             George Mason University
7             Fairfax, 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 Software
21     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 */
23
24 #include <stdio.h>
25 #include <string.h>
26 #include "rsl.h"
27 #include "rainbow.h"
28
29 struct dms {
30     int deg;
31     int minute;
32     int sec;
33 };
34
35 struct dms deg_to_dms(float deg)
36 {
37     /* Convert value in degrees to degrees-minutes-seconds. */
38
39     int sign, ideg, iminute, sec;
40     float fminute;  /* minute with fractional part */
41     struct dms dms;
42
43     sign = (deg < 0.) ? -1 : 1;
44     deg = sign * deg;  /* absolute value */
45     ideg = deg;        /* truncated degree */
46     iminute = fminute = (deg - ideg) * 60.;
47     sec = (fminute - iminute) * 60. + .5;
48     dms.deg = sign * ideg;
49     dms.minute = sign * iminute;
50     dms.sec = sign * sec;
51     return dms;
52 }
53
54 static float (*f)(Range x);
55 static Range (*invf)(float x);
56
57 /**********************************************************/
58 /*                                                        */
59 /*                  RSL_rainbow_to_radar                  */
60 /*                                                        */
61 /**********************************************************/
62
63 Radar *RSL_rainbow_to_radar(char *infile)
64 {
65     /* This function reads the Rainbow format scan data file and returns a
66      * radar structure.
67      */
68
69     Radar *radar;
70     FILE *fp;
71     int c;
72     int nvolumes;
73     Rainbow_hdr rainbow_hdr;
74     struct dms latdms, londms;
75
76     /* These next lines allow program to read from a regular file, a
77      * compressed file, or standard input.  I lifted them from RSL_uf_to_radar
78      * by John Merritt.
79      */
80
81     if (infile == NULL) {
82         int save_fd;
83         save_fd = dup(0);
84         fp = fdopen(save_fd, "r");
85     }
86     else if ((fp = fopen(infile, "r")) == NULL) {
87         perror(infile);
88         return NULL;
89     }
90     fp = uncompress_pipe(fp); /* Transparently gunzip. */
91
92     /* Read first character and verify file format. */
93
94     if ((c = fgetc(fp)) != SOH) {
95         fprintf(stderr,"%s is not a valid Rainbow format file.\n",infile);
96         return NULL;
97     }
98
99     /* Read Rainbow file header and check for correct product. */
100
101     read_rainbow_header(&rainbow_hdr, fp);
102
103     if (rainbow_hdr.filetype != SCAN_DATA ) {
104         fprintf(stderr,"ERROR: File is not a scan data file.\n");
105         fprintf(stderr,"File type number (header label H3) is %d\n",
106                 rainbow_hdr.filetype);
107         fprintf(stderr,"See Rainbow File Format Document for details on "
108                 "header labels.\n");
109         return NULL;
110     }
111     if (rainbow_hdr.product != VOLUME_SCAN) {
112         fprintf(stderr,"WARNING: Product is not volume scan as expected.\n");
113         fprintf(stderr,"Header label N is %d, expected %d\n",
114                 rainbow_hdr.product, VOLUME_SCAN);
115         fprintf(stderr,"See Rainbow File Format Document for details on "
116                 "header labels.\n");
117     }
118     if (rainbow_hdr.compressed) {
119         fprintf(stderr,"RSL_rainbow_to_radar: Label F3 indicates data "
120                 "compression.\n");
121         fprintf(stderr,"This routine can not handle compressed data.\n");
122         fprintf(stderr,"See Rainbow File Format Document for details on "
123                 "header labels.\n");
124         return NULL;
125     }
126
127     /* Make radar structure and assign header information.  */
128
129     nvolumes = 1; /* There is only one raw data type in a volume scan file. */
130     radar = RSL_new_radar(MAX_RADAR_VOLUMES);
131     if (radar == NULL) {
132         perror("RSL_new_radar returned NUL to RSL_rainbow_to_radar");
133         return NULL;
134     }
135     radar->h.nvolumes = nvolumes;
136     strcpy(radar->h.radar_name, rainbow_hdr.radarname);
137     strcpy(radar->h.radar_type, "rainbow");
138     radar->h.month = rainbow_hdr.month;
139     radar->h.day = rainbow_hdr.day;
140     radar->h.year = rainbow_hdr.year;
141     radar->h.hour = rainbow_hdr.hour;
142     radar->h.minute = rainbow_hdr.minute;
143     radar->h.sec = (float) rainbow_hdr.sec;
144     latdms = deg_to_dms(rainbow_hdr.lat);
145     londms = deg_to_dms(rainbow_hdr.lon);
146     radar->h.latd = latdms.deg;
147     radar->h.latm = latdms.minute;
148     radar->h.lats = latdms.sec;
149     radar->h.lond = londms.deg;
150     radar->h.lonm = londms.minute;
151     radar->h.lons = londms.sec;
152
153     /* Read the data portion of the file into the radar structure. */
154
155     if (rainbow_data_to_radar(radar, rainbow_hdr, fp) < 1)
156         radar = NULL;
157
158     return radar;
159 }
160
161 /**********************************************************/
162 /*                                                        */
163 /*                 rainbow_data_to_radar                  */
164 /*                                                        */
165 /**********************************************************/
166
167 int rainbow_data_to_radar(Radar *radar, Rainbow_hdr rainbow_hdr, FILE *fp)
168 {
169     /* Read Rainbow data into the radar structure.  Data in the file is stored
170      * as bytes, where each byte contains the value for one range bin.  The
171      * data is ordered as follows: The first byte corresponds to the first bin
172      * of the first ray, followed by the remaining bins of that ray, followed
173      * by the remaining rays of the first sweep.  This sequence of bins, rays,
174      * and sweeps continues for the remainder of sweeps in the volume scan.
175      */
176
177     int iray, isweep, nread, nsweeps, nrays, nbins, vol_index;
178     unsigned char *rainbow_ray;
179     Volume *v;
180     Sweep *sweep;
181     Ray *ray;
182     int i;
183     float azim_rate, beam_width, dz, elev_angle, prf, unam_rng;
184
185     beam_width = 1.0; /* for now */
186
187     switch (rainbow_hdr.datatype) {
188         /* TODO: Add f and invf for each field */
189         case 0:
190             vol_index = VR_INDEX;
191             f = VR_F;
192             invf = VR_INVF;
193             break;
194         case 1:
195             vol_index = DZ_INDEX;
196             f = DZ_F;
197             invf = DZ_INVF;
198             break;
199         case 2:
200             vol_index = SW_INDEX;
201             break;
202         case 3:
203             vol_index = ZT_INDEX;
204             break;
205         case 5:
206             vol_index = DR_INDEX;
207             break;
208     }
209     /* TODO: remove the following if-statement once the code for other data
210      * types has been implemented.  Currently only handles reflectivity (DZ).
211      */
212     if (vol_index != DZ_INDEX) {
213         fprintf(stderr, "RSL_rainbow_to_radar: currently only handles "
214                 "field type DZ\n");
215         fprintf(stderr,"Rainbow data type value (label F9) is %d\n",
216                 rainbow_hdr.datatype);
217         fprintf(stderr,"Corresponding vol_INDEX number is %d\n", vol_index);
218         return 0;
219     }
220
221     nsweeps = rainbow_hdr.nsweeps;
222     nrays = (rainbow_hdr.az_stop - rainbow_hdr.az_start + 1) /
223         rainbow_hdr.az_step + .5;
224     nbins = rainbow_hdr.nbins;
225     if (nrays != 360) {
226         fprintf(stderr,"WARNING: number of rays computed is not the number "
227                 "expected.\n");
228         fprintf(stderr,"Computed = nrays: azstart = %d, az_stop = %d, "
229                 "az_step = %f\n");
230         fprintf(stderr,"Expected 360\n");
231     }
232     radar->v[vol_index] = RSL_new_volume(nsweeps);
233     v = radar->v[vol_index];
234     v->h.nsweeps = nsweeps;
235     v->h.f = f;
236     v->h.invf = invf;
237     if (vol_index == DZ_INDEX) v->h.type_str = strdup("Reflectivity");
238     rainbow_ray = (unsigned char *) malloc(nbins);
239     
240     /* Load sweeps. */
241
242     for (isweep = 0; isweep < nsweeps; isweep++) {
243         sweep = RSL_new_sweep(nrays);
244         prf = rainbow_hdr.elev_params[isweep]->prf_high;
245         unam_rng = RSL_SPEED_OF_LIGHT / (2. * prf * 1000.);
246         azim_rate = rainbow_hdr.elev_params[isweep]->az_rate;
247         elev_angle = rainbow_hdr.elev_params[isweep]->elev_angle;
248
249         /* Load rays. */
250
251         for (iray = 0; iray < nrays; iray++) {
252             nread = fread(rainbow_ray, 1, nbins, fp);
253             if (nread != nbins) {
254                 fprintf(stderr, "ERROR: Could not read enough bytes to fill "
255                         "ray.\n");
256                 fprintf(stderr, "Sweep = %d, ray = %d, number read = %d\n",
257                         isweep, iray, nread);
258                 return 0;
259             }
260             ray = RSL_new_ray(nbins);
261
262             /* TODO: Add code for other fields. */
263
264             if (vol_index == DZ_INDEX) {
265                 for (i=0; i < ray->h.nbins; i++) {
266                     dz = -31.5 + (rainbow_ray[i] - 1) * 0.5;
267                     if (dz < -31.5)
268                         ray->range[i] = invf(BADVAL);
269                     else
270                         ray->range[i] = invf(dz);
271                 }
272             }
273             /* Load ray header. Note: the rainbow data file has only one time
274              * stamp, which is the data acquisition time at the start of the
275              * volume scan. For now, that is the time assigned to all rays.
276              */
277             ray->h.month = rainbow_hdr.month;
278             ray->h.day = rainbow_hdr.day;
279             ray->h.year = rainbow_hdr.year;
280             ray->h.hour = rainbow_hdr.hour;
281             ray->h.minute = rainbow_hdr.minute;
282             ray->h.sec = rainbow_hdr.sec;
283             ray->h.f = f;
284             ray->h.invf = invf;
285             ray->h.unam_rng = unam_rng;
286             ray->h.prf = prf;
287             ray->h.azim_rate = azim_rate;
288             ray->h.elev = elev_angle;
289             ray->h.elev_num = isweep + 1;
290             ray->h.fix_angle = elev_angle;
291             ray->h.azimuth = rainbow_hdr.az_start + iray * rainbow_hdr.az_step;
292             ray->h.ray_num = iray + 1;
293             ray->h.range_bin1 = rainbow_hdr.range_start;
294             ray->h.gate_size = rainbow_hdr.range_step * 1000.;
295             ray->h.beam_width = beam_width;
296             sweep->ray[iray] = ray;
297         } /* iray */
298         sweep->h.sweep_num = isweep + 1;
299         sweep->h.beam_width = beam_width;
300         sweep->h.vert_half_bw = sweep->h.beam_width * 0.5;
301         sweep->h.horz_half_bw = sweep->h.beam_width * 0.5;
302         sweep->h.nrays = nrays;
303         sweep->h.f = f;
304         sweep->h.invf = invf;
305         v->sweep[isweep] = sweep;
306     } /* isweep */
307     return 1;
308 }