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
37 struct dms deg_to_dms(float deg)
39 /* Convert value in degrees to degrees-minutes-seconds. */
41 int sign, ideg, iminute, sec;
42 float fminute; /* minute with fractional part */
45 sign = (deg < 0.) ? -1 : 1;
46 deg = sign * deg; /* absolute value */
47 ideg = deg; /* truncated degree */
48 iminute = fminute = (deg - ideg) * 60.;
49 sec = (fminute - iminute) * 60. + .5;
50 dms.deg = sign * ideg;
51 dms.minute = sign * iminute;
56 static float (*f)(Range x);
57 static Range (*invf)(float x);
59 /**********************************************************/
61 /* RSL_rainbow_to_radar */
63 /**********************************************************/
65 Radar *RSL_rainbow_to_radar(char *infile)
67 /* This function reads the Rainbow format scan data file and returns a
75 Rainbow_hdr rainbow_hdr;
76 struct dms latdms, londms;
78 void read_rainbow_header(Rainbow_hdr *, FILE *);
80 /* These next lines allow program to read from a regular file, a
81 * compressed file, or standard input. I lifted them from RSL_uf_to_radar
88 fp = fdopen(save_fd, "rb");
90 else if ((fp = fopen(infile, "rb")) == NULL) {
94 fp = uncompress_pipe(fp); /* Transparently gunzip. */
96 /* Read first character and verify file format. */
98 if ((c = fgetc(fp)) != SOH) {
99 fprintf(stderr,"%s is not a valid Rainbow format file.\n",infile);
103 /* Read Rainbow file header and check for correct product. */
105 read_rainbow_header(&rainbow_hdr, fp);
107 if (rainbow_hdr.filetype != SCAN_DATA ) {
108 fprintf(stderr,"ERROR: File is not a scan data file.\n");
109 fprintf(stderr,"File type number (header label H3) is %d\n",
110 rainbow_hdr.filetype);
111 fprintf(stderr,"See Rainbow File Format Document for details on "
115 if (rainbow_hdr.product != VOLUME_SCAN) {
116 fprintf(stderr,"WARNING: Product is not volume scan as expected.\n");
117 fprintf(stderr,"Header label N is %d, expected %d\n",
118 rainbow_hdr.product, VOLUME_SCAN);
119 fprintf(stderr,"See Rainbow File Format Document for details on "
122 if (rainbow_hdr.compressed) {
123 fprintf(stderr,"RSL_rainbow_to_radar: Label F3 indicates data "
125 fprintf(stderr,"This routine can not handle compressed data.\n");
126 fprintf(stderr,"See Rainbow File Format Document for details on "
131 /* Make radar structure and assign header information. */
133 nvolumes = 1; /* There is only one raw data type in a volume scan file. */
134 radar = RSL_new_radar(MAX_RADAR_VOLUMES);
136 perror("RSL_new_radar returned NUL to RSL_rainbow_to_radar");
139 radar->h.nvolumes = nvolumes;
140 strcpy(radar->h.radar_name, rainbow_hdr.radarname);
141 strcpy(radar->h.radar_type, "rainbow");
142 radar->h.month = rainbow_hdr.month;
143 radar->h.day = rainbow_hdr.day;
144 radar->h.year = rainbow_hdr.year;
145 radar->h.hour = rainbow_hdr.hour;
146 radar->h.minute = rainbow_hdr.minute;
147 radar->h.sec = (float) rainbow_hdr.sec;
148 latdms = deg_to_dms(rainbow_hdr.lat);
149 londms = deg_to_dms(rainbow_hdr.lon);
150 radar->h.latd = latdms.deg;
151 radar->h.latm = latdms.minute;
152 radar->h.lats = latdms.sec;
153 radar->h.lond = londms.deg;
154 radar->h.lonm = londms.minute;
155 radar->h.lons = londms.sec;
157 /* Read the data portion of the file into the radar structure. */
159 if (rainbow_data_to_radar(radar, rainbow_hdr, fp) < 1)
165 /**********************************************************/
167 /* rainbow_data_to_radar */
169 /**********************************************************/
171 int rainbow_data_to_radar(Radar *radar, Rainbow_hdr rainbow_hdr, FILE *fp)
173 /* Read Rainbow data into the radar structure. Data in the file is stored
174 * as bytes, where each byte contains the value for one range bin. The
175 * data is ordered as follows: The first byte corresponds to the first bin
176 * of the first ray, followed by the remaining bins of that ray, followed
177 * by the remaining rays of the first sweep. This sequence of bins, rays,
178 * and sweeps continues for the remainder of sweeps in the volume scan.
181 int iray, isweep, nread, nsweeps, nrays, nbins;
182 unsigned char *rainbow_ray;
187 float azim_rate, beam_width, dz, elev_angle, prf, unam_rng;
188 int vol_index = VR_INDEX;
190 beam_width = 1.0; /* for now */
192 switch (rainbow_hdr.datatype) {
193 /* TODO: Add f and invf for each field */
195 vol_index = VR_INDEX;
200 vol_index = DZ_INDEX;
205 vol_index = SW_INDEX;
208 vol_index = ZT_INDEX;
211 vol_index = DR_INDEX;
214 /* TODO: remove the following if-statement once the code for other data
215 * types has been implemented. Currently only handles reflectivity (DZ).
217 if (vol_index != DZ_INDEX) {
218 fprintf(stderr, "RSL_rainbow_to_radar: currently only handles "
220 fprintf(stderr,"Rainbow data type value (label F9) is %d\n",
221 rainbow_hdr.datatype);
222 fprintf(stderr,"Corresponding vol_INDEX number is %d\n", vol_index);
226 nsweeps = rainbow_hdr.nsweeps;
227 nrays = (rainbow_hdr.az_stop - rainbow_hdr.az_start + 1) /
228 rainbow_hdr.az_step + .5;
229 nbins = rainbow_hdr.nbins;
231 fprintf(stderr,"WARNING: number of rays computed is not the number "
233 fprintf(stderr,"Computed = nrays: "
234 "azstart = %d, az_stop = %d, az_step = %f\n",
235 rainbow_hdr.az_start, rainbow_hdr.az_stop, rainbow_hdr.az_step);
236 fprintf(stderr,"Expected 360\n");
238 radar->v[vol_index] = RSL_new_volume(nsweeps);
239 v = radar->v[vol_index];
240 v->h.nsweeps = nsweeps;
243 if (vol_index == DZ_INDEX) v->h.type_str = strdup("Reflectivity");
244 rainbow_ray = (unsigned char *) malloc(nbins);
248 for (isweep = 0; isweep < nsweeps; isweep++) {
249 sweep = RSL_new_sweep(nrays);
250 prf = rainbow_hdr.elev_params[isweep]->prf_high;
251 unam_rng = RSL_SPEED_OF_LIGHT / (2. * prf * 1000.);
252 azim_rate = rainbow_hdr.elev_params[isweep]->az_rate;
253 elev_angle = rainbow_hdr.elev_params[isweep]->elev_angle;
257 for (iray = 0; iray < nrays; iray++) {
258 nread = fread(rainbow_ray, 1, nbins, fp);
259 if (nread != nbins) {
260 fprintf(stderr, "ERROR: Could not read enough bytes to fill "
262 fprintf(stderr, "Sweep = %d, ray = %d, number read = %d\n",
263 isweep, iray, nread);
266 ray = RSL_new_ray(nbins);
268 /* TODO: Add code for other fields. */
270 if (vol_index == DZ_INDEX) {
271 for (i=0; i < ray->h.nbins; i++) {
272 dz = -31.5 + (rainbow_ray[i] - 1) * 0.5;
274 ray->range[i] = invf(BADVAL);
276 ray->range[i] = invf(dz);
279 /* Load ray header. Note: the rainbow data file has only one time
280 * stamp, which is the data acquisition time at the start of the
281 * volume scan. For now, that is the time assigned to all rays.
283 ray->h.month = rainbow_hdr.month;
284 ray->h.day = rainbow_hdr.day;
285 ray->h.year = rainbow_hdr.year;
286 ray->h.hour = rainbow_hdr.hour;
287 ray->h.minute = rainbow_hdr.minute;
288 ray->h.sec = rainbow_hdr.sec;
291 ray->h.unam_rng = unam_rng;
293 ray->h.azim_rate = azim_rate;
294 ray->h.elev = elev_angle;
295 ray->h.elev_num = isweep + 1;
296 ray->h.fix_angle = elev_angle;
297 ray->h.azimuth = rainbow_hdr.az_start + iray * rainbow_hdr.az_step;
298 ray->h.ray_num = iray + 1;
299 ray->h.range_bin1 = rainbow_hdr.range_start;
300 ray->h.gate_size = rainbow_hdr.range_step * 1000.;
301 ray->h.beam_width = beam_width;
302 sweep->ray[iray] = ray;
304 sweep->h.sweep_num = isweep + 1;
305 sweep->h.beam_width = beam_width;
306 sweep->h.vert_half_bw = sweep->h.beam_width * 0.5;
307 sweep->h.horz_half_bw = sweep->h.beam_width * 0.5;
308 sweep->h.nrays = nrays;
310 sweep->h.invf = invf;
311 v->sweep[isweep] = sweep;