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
36 struct dms deg_to_dms(float deg)
38 /* Convert value in degrees to degrees-minutes-seconds. */
40 int sign, ideg, iminute, sec;
41 float fminute; /* minute with fractional part */
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;
55 static float (*f)(Range x);
56 static Range (*invf)(float x);
58 /**********************************************************/
60 /* RSL_rainbow_to_radar */
62 /**********************************************************/
64 Radar *RSL_rainbow_to_radar(char *infile)
66 /* This function reads the Rainbow format scan data file and returns a
74 Rainbow_hdr rainbow_hdr;
75 struct dms latdms, londms;
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
85 fp = fdopen(save_fd, "r");
87 else if ((fp = fopen(infile, "r")) == NULL) {
91 fp = uncompress_pipe(fp); /* Transparently gunzip. */
93 /* Read first character and verify file format. */
95 if ((c = fgetc(fp)) != SOH) {
96 fprintf(stderr,"%s is not a valid Rainbow format file.\n",infile);
100 /* Read Rainbow file header and check for correct product. */
102 read_rainbow_header(&rainbow_hdr, fp);
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 "
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 "
119 if (rainbow_hdr.compressed) {
120 fprintf(stderr,"RSL_rainbow_to_radar: Label F3 indicates data "
122 fprintf(stderr,"This routine can not handle compressed data.\n");
123 fprintf(stderr,"See Rainbow File Format Document for details on "
128 /* Make radar structure and assign header information. */
130 nvolumes = 1; /* There is only one raw data type in a volume scan file. */
131 radar = RSL_new_radar(MAX_RADAR_VOLUMES);
133 perror("RSL_new_radar returned NUL to RSL_rainbow_to_radar");
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;
154 /* Read the data portion of the file into the radar structure. */
156 if (rainbow_data_to_radar(radar, rainbow_hdr, fp) < 1)
162 /**********************************************************/
164 /* rainbow_data_to_radar */
166 /**********************************************************/
168 int rainbow_data_to_radar(Radar *radar, Rainbow_hdr rainbow_hdr, FILE *fp)
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.
178 int iray, isweep, nread, nsweeps, nrays, nbins, vol_index;
179 unsigned char *rainbow_ray;
184 float azim_rate, beam_width, dz, elev_angle, prf, unam_rng;
186 beam_width = 1.0; /* for now */
188 switch (rainbow_hdr.datatype) {
189 /* TODO: Add f and invf for each field */
191 vol_index = VR_INDEX;
196 vol_index = DZ_INDEX;
201 vol_index = SW_INDEX;
204 vol_index = ZT_INDEX;
207 vol_index = DR_INDEX;
210 /* TODO: remove the following if-statement once the code for other data
211 * types has been implemented. Currently only handles reflectivity (DZ).
213 if (vol_index != DZ_INDEX) {
214 fprintf(stderr, "RSL_rainbow_to_radar: currently only handles "
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);
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;
227 fprintf(stderr,"WARNING: number of rays computed is not the number "
229 fprintf(stderr,"Computed = nrays: azstart = %d, az_stop = %d, "
231 fprintf(stderr,"Expected 360\n");
233 radar->v[vol_index] = RSL_new_volume(nsweeps);
234 v = radar->v[vol_index];
235 v->h.nsweeps = nsweeps;
238 if (vol_index == DZ_INDEX) v->h.type_str = strdup("Reflectivity");
239 rainbow_ray = (unsigned char *) malloc(nbins);
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;
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 "
257 fprintf(stderr, "Sweep = %d, ray = %d, number read = %d\n",
258 isweep, iray, nread);
261 ray = RSL_new_ray(nbins);
263 /* TODO: Add code for other fields. */
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;
269 ray->range[i] = invf(BADVAL);
271 ray->range[i] = invf(dz);
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.
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;
286 ray->h.unam_rng = unam_rng;
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;
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;
305 sweep->h.invf = invf;
306 v->sweep[isweep] = sweep;