3 This is the TRMM Office Radar Software Library.
6 George Mason University
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 Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 struct dms deg_to_dms(float deg)
37 /* Convert value in degrees to degrees-minutes-seconds. */
39 int sign, ideg, iminute, sec;
40 float fminute; /* minute with fractional part */
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;
54 static float (*f)(Range x);
55 static Range (*invf)(float x);
57 /**********************************************************/
59 /* RSL_rainbow_to_radar */
61 /**********************************************************/
63 Radar *RSL_rainbow_to_radar(char *infile)
65 /* This function reads the Rainbow format scan data file and returns a
73 Rainbow_hdr rainbow_hdr;
74 struct dms latdms, londms;
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
84 fp = fdopen(save_fd, "r");
86 else if ((fp = fopen(infile, "r")) == NULL) {
90 fp = uncompress_pipe(fp); /* Transparently gunzip. */
92 /* Read first character and verify file format. */
94 if ((c = fgetc(fp)) != SOH) {
95 fprintf(stderr,"%s is not a valid Rainbow format file.\n",infile);
99 /* Read Rainbow file header and check for correct product. */
101 read_rainbow_header(&rainbow_hdr, fp);
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 "
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 "
118 if (rainbow_hdr.compressed) {
119 fprintf(stderr,"RSL_rainbow_to_radar: Label F3 indicates data "
121 fprintf(stderr,"This routine can not handle compressed data.\n");
122 fprintf(stderr,"See Rainbow File Format Document for details on "
127 /* Make radar structure and assign header information. */
129 nvolumes = 1; /* There is only one raw data type in a volume scan file. */
130 radar = RSL_new_radar(MAX_RADAR_VOLUMES);
132 perror("RSL_new_radar returned NUL to RSL_rainbow_to_radar");
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;
153 /* Read the data portion of the file into the radar structure. */
155 if (rainbow_data_to_radar(radar, rainbow_hdr, fp) < 1)
161 /**********************************************************/
163 /* rainbow_data_to_radar */
165 /**********************************************************/
167 int rainbow_data_to_radar(Radar *radar, Rainbow_hdr rainbow_hdr, FILE *fp)
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.
177 int iray, isweep, nread, nsweeps, nrays, nbins, vol_index;
178 unsigned char *rainbow_ray;
183 float azim_rate, beam_width, dz, elev_angle, prf, unam_rng;
185 beam_width = 1.0; /* for now */
187 switch (rainbow_hdr.datatype) {
188 /* TODO: Add f and invf for each field */
190 vol_index = VR_INDEX;
195 vol_index = DZ_INDEX;
200 vol_index = SW_INDEX;
203 vol_index = ZT_INDEX;
206 vol_index = DR_INDEX;
209 /* TODO: remove the following if-statement once the code for other data
210 * types has been implemented. Currently only handles reflectivity (DZ).
212 if (vol_index != DZ_INDEX) {
213 fprintf(stderr, "RSL_rainbow_to_radar: currently only handles "
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);
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;
226 fprintf(stderr,"WARNING: number of rays computed is not the number "
228 fprintf(stderr,"Computed = nrays: azstart = %d, az_stop = %d, "
230 fprintf(stderr,"Expected 360\n");
232 radar->v[vol_index] = RSL_new_volume(nsweeps);
233 v = radar->v[vol_index];
234 v->h.nsweeps = nsweeps;
237 if (vol_index == DZ_INDEX) v->h.type_str = strdup("Reflectivity");
238 rainbow_ray = (unsigned char *) malloc(nbins);
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;
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 "
256 fprintf(stderr, "Sweep = %d, ray = %d, number read = %d\n",
257 isweep, iray, nread);
260 ray = RSL_new_ray(nbins);
262 /* TODO: Add code for other fields. */
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;
268 ray->range[i] = invf(BADVAL);
270 ray->range[i] = invf(dz);
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.
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;
285 ray->h.unam_rng = unam_rng;
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;
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;
304 sweep->h.invf = invf;
305 v->sweep[isweep] = sweep;