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