#include <time.h>
#include <stdlib.h>
+#define USE_RSL_VARS
#include "rsl.h"
extern int radar_verbose_flag;
/* Missing data flag : -32768 when a signed short. */
#define UF_NO_DATA 0X8000
-/* Any convensions may be observed. */
+/* Field names. Any convensions may be observed. */
/* Typically:
* DZ = Reflectivity (dBZ).
* VR = Radial Velocity.
* KD = KDP wavelength*deg/km
* TI = TIME (units unknown).
* These fields may appear in any order in the UF file.
+ * There are more fields than appear here. See rsl.h.
*/
-char *UF_field_name[] = {"DZ", "VR", "SW", "CZ", "ZT", "DR", "LR",
- "ZD", "DM", "RH", "PH", "XZ", "CD", "MZ",
- "MD", "ZE", "VE", "KD", "TI", "DX", "CH",
- "AH", "CV", "AV", "SQ"
-};
-
-typedef short UF_buffer[16384]; /* Bigger than documented 4096. */
+/* Changed old buffer size (16384) for larger dualpol files. BLK 5/20/2011 */
+typedef short UF_buffer[20000]; /* Bigger than documented 4096. */
void swap_uf_buffer(UF_buffer uf);
void swap2(short *buf, int n);
+Radar *wsr88d_align_split_cut_rays(Radar *radar);
+
/**********************************************************************/
/* */
int rec_len, save_rec_len;
int nfield;
float vr_az;
+ int max_field_names;
struct tm *tm;
time_t the_time;
int degree, minute;
float second;
+ int uf_sweep_mode = 1; /* default PPI */
/* Here are the arrays for each field type. Each dimension is the number
* of fields in the radar structure. I do this because the radar organization
int sweep_num, ray_num, rec_num;
float x;
+ Radar *r_save = NULL;
+
if (r == NULL) {
- fprintf(stderr, "radar_to_uf_fp: radar pointer NULL\n");
- return;
+ fprintf(stderr, "radar_to_uf_fp: radar pointer NULL\n");
+ return;
}
+ /* If this is WSR-88D data, reorder VR and SW rays in split cuts so that
+ * their azimuths agree with DZ rays.
+ */
+ if (r->h.vcp > 0) {
+ if (wsr88d_merge_split_cuts_is_set()) {
+ /* Save a copy of the input radar; we'll restore it later. */
+ r_save = r;
+ r = wsr88d_align_split_cut_rays(r);
+ }
+ }
/* Do all the headers first time around. Then, prune OP and LU. */
q_op = q_lu = q_dh = q_fh = 1;
sweep_num = ray_num = rec_num = 0;
true_nvolumes = nvolumes = maxsweeps = nrays = 0;
+ /* PPI and RHI are enum constants defined in rsl.h */
+ if (r->h.scan_mode == PPI) uf_sweep_mode = 1;
+ else if (r->h.scan_mode == RHI) uf_sweep_mode = 3;
+
/*
* The organization of the Radar structure is by volumes, then sweeps, then
* rays, then gates. This is different from the UF file organization.
* the main controlling loop variable.
*/
for (i=0; i<nvolumes; i++) {
- volume[i] = r->v[i];
- if(volume[i]) {
- nsweeps[i] = volume[i]->h.nsweeps;
- if (nsweeps[i] > maxsweeps) maxsweeps = nsweeps[i];
- true_nvolumes++;
- }
+ volume[i] = r->v[i];
+ if(volume[i]) {
+ nsweeps[i] = volume[i]->h.nsweeps;
+ if (nsweeps[i] > maxsweeps) maxsweeps = nsweeps[i];
+ true_nvolumes++;
+ }
}
if (radar_verbose_flag) {
- fprintf(stderr,"True number of volumes for UF is %d\n", true_nvolumes);
- fprintf(stderr,"Maximum # of volumes for UF is %d\n", nvolumes);
+ fprintf(stderr,"True number of volumes for UF is %d\n", true_nvolumes);
+ fprintf(stderr,"Maximum # of volumes for UF is %d\n", nvolumes);
}
+
+ max_field_names = sizeof(RSL_ftype) / 4;
+
/*--------
* LOOP for all sweeps (typically 11 or 16 for wsr88d data.
*
*/
for (i=0; i<maxsweeps; i++) {
/* Get the array of volume and sweep pointers; one for each field type. */
- nrays = 0;
- for (k=0; k<nvolumes; k++) {
- if (volume[k]) sweep[k] = volume[k]->sweep[i];
-
- /* Check if we really can access this sweep. Paul discovered that
- * if the actual number of sweeps is less than the maximum that we
- * could be chasing a bad pointer (a NON-NULL garbage pointer).
- */
- if (i >= nsweeps[k]) sweep[k] = NULL;
-
- if (sweep[k]) if (sweep[k]->h.nrays > nrays) nrays = sweep[k]->h.nrays;
- }
-
- sweep_num++; /* I guess it will be ok to count NULL sweeps. */
- ray_num = 0;
+ nrays = 0;
+ for (k=0; k<nvolumes; k++) {
+ if (volume[k]) sweep[k] = volume[k]->sweep[i];
+
+ /* Check if we really can access this sweep. Paul discovered that
+ * if the actual number of sweeps is less than the maximum that we
+ * could be chasing a bad pointer (a NON-NULL garbage pointer).
+ */
+ if (i >= nsweeps[k]) sweep[k] = NULL;
+
+ if (sweep[k]) if (sweep[k]->h.nrays > nrays) nrays = sweep[k]->h.nrays;
+ }
+
+ sweep_num++; /* I guess it will be ok to count NULL sweeps. */
+ ray_num = 0;
if (radar_verbose_flag)
- fprintf(stderr,"Processing sweep %d for %d rays.", i, nrays);
+ fprintf(stderr,"Processing sweep %d for %d rays.", i, nrays);
if (radar_verbose_flag)
- if (little_endian()) fprintf(stderr," ... On Little endian.\n");
- else fprintf(stderr,"\n");
+ if (little_endian()) fprintf(stderr," ... On Little endian.\n");
+ else fprintf(stderr,"\n");
/* Now LOOP for all rays within this particular sweep (i).
* Get all the field types together for the ray, see ray[k], and
* fill the UF data buffer appropriately.
*/
- for (j=0; j<nrays; j++) {
- memset(uf, 0, sizeof(uf));
- nfield = 0;
- ray_num++; /* And counting, possibly, NULL rays. */
- current_fh_index = 0;
-
-
- /* Find any ray for header information. It does not matter which
- * ray, since the information for the MANDITORY, OPTIONAL, and LOCAL
- * USE headers is common to any field type ray.
- */
- ray = NULL;
- for (k=0; k<nvolumes; k++) {
- if (sweep[k])
- if (j < sweep[k]->h.nrays)
- if (sweep[k]->ray)
- if ((ray = sweep[k]->ray[j])) break;
- }
-
- /* If there is no such ray, then continue on to the next ray. */
- if (ray) {
+ for (j=0; j<nrays; j++) {
+ memset(uf, 0, sizeof(uf));
+ nfield = 0;
+ ray_num++; /* And counting, possibly, NULL rays. */
+ current_fh_index = 0;
+
+
+ /* Find any ray for header information. It does not matter which
+ * ray, since the information for the MANDITORY, OPTIONAL, and LOCAL
+ * USE headers is common to any field type ray.
+ */
+ ray = NULL;
+ for (k=0; k<nvolumes; k++) {
+ if (sweep[k])
+ if (j < sweep[k]->h.nrays)
+ if (sweep[k]->ray)
+ if ((ray = sweep[k]->ray[j])) break;
+ }
+
+ /* If there is no such ray, then continue on to the next ray. */
+ if (ray) {
/*
- fprintf(stderr,"Ray: %.4d, Time: %2.2d:%2.2d:%f %.2d/%.2d/%.4d\n", ray_num, ray->h.hour, ray->h.minute, ray->h.sec, ray->h.month, ray->h.day, ray->h.year);
+ fprintf(stderr,"Ray: %.4d, Time: %2.2d:%2.2d:%f %.2d/%.2d/%.4d\n", ray_num, ray->h.hour, ray->h.minute, ray->h.sec, ray->h.month, ray->h.day, ray->h.year);
*/
- /*
- * ---- Begining of MANDITORY HEADER BLOCK.
- */
- uf_ma = uf;
- memcpy(&uf_ma[0], "UF", 2);
- if (little_endian()) memcpy(&uf_ma[0], "FU", 2);
- uf_ma[1] = 0; /* Not known yet. */
- uf_ma[2] = 0; /* Not known yet. Really, I do. */
- uf_ma[3] = 0; /* Not known yet. */
- uf_ma[4] = 0; /* Not known yet. */
-
- uf_ma[6] = 1;
- uf_ma[7] = ray_num;
- uf_ma[8 ] = 1;
- uf_ma[9 ] = sweep_num;
- memcpy(&uf_ma[10], r->h.radar_name, 8);
- if (little_endian()) swap2(&uf_ma[10], 8/2);
- memcpy(&uf_ma[14], r->h.name, 8);
- if (little_endian()) swap2(&uf_ma[14], 8/2);
- /* Convert decimal lat/lon to d:m:s */
-
- if (ray->h.lat != 0.0) {
- degree = (int)ray->h.lat;
- minute = (int)((ray->h.lat - degree) * 60);
- second = (ray->h.lat - degree - minute/60.0) * 3600.0;
- } else {
- degree = r->h.latd;
- minute = r->h.latm;
- second = r->h.lats;
- }
- uf_ma[18] = degree;
- uf_ma[19] = minute;
- if (second > 0.0) uf_ma[20] = second*64 + 0.5;
- else uf_ma[20] = second*64 - 0.5;
-
- if (ray->h.lon != 0.0) {
- degree = (int)ray->h.lon;
- minute = (int)((ray->h.lon - degree) * 60);
- second = (ray->h.lon - degree - minute/60.0) * 3600.0;
- } else {
- degree = r->h.lond;
- minute = r->h.lonm;
- second = r->h.lons;
- }
- uf_ma[21] = degree;
- uf_ma[22] = minute;
- if (second > 0.0) uf_ma[23] = second*64 + 0.5;
- else uf_ma[23] = second*64 - 0.5;
- if (ray->h.alt != 0)
- uf_ma[24] = ray->h.alt;
- else
- uf_ma[24] = r->h.height;
-
- uf_ma[25] = ray->h.year % 100; /* By definition: not year 2000 compliant. */
- uf_ma[26] = ray->h.month;
- uf_ma[27] = ray->h.day;
- uf_ma[28] = ray->h.hour;
- uf_ma[29] = ray->h.minute;
- uf_ma[30] = ray->h.sec;
- memcpy(&uf_ma[31], "UT", 2);
- if (little_endian()) memcpy(&uf_ma[31], "TU", 2);
- if (ray->h.azimuth > 0) uf_ma[32] = ray->h.azimuth*64 + 0.5;
- else uf_ma[32] = ray->h.azimuth*64 - 0.5;
- uf_ma[33] = ray->h.elev*64 + 0.5;
- uf_ma[34] = 1; /* Sweep mode: PPI = 1 */
- if (ray->h.fix_angle != 0.)
- uf_ma[35] = ray->h.fix_angle*64.0 + 0.5;
- else uf_ma[35] = sweep[k]->h.elev*64.0 + 0.5;
- uf_ma[36] = ray->h.sweep_rate*(360.0/60.0)*64.0 + 0.5;
-
- the_time = time(NULL);
- tm = gmtime(&the_time);
-
- uf_ma[37] = tm->tm_year % 100; /* Same format as data year */
- uf_ma[38] = tm->tm_mon+1;
- uf_ma[39] = tm->tm_mday;
- memcpy(&uf_ma[40], "RSL" RSL_VERSION_STR, 8);
- if (little_endian()) swap2(&uf_ma[40], 8/2);
- uf_ma[44] = (signed short)UF_NO_DATA;
- len_ma = 45;
- uf_ma[2] = len_ma+1;
- /*
- * ---- End of MANDITORY HEADER BLOCK.
- */
-
- /* ---- Begining of OPTIONAL HEADER BLOCK. */
- len_op = 0;
- if (q_op) {
- q_op = 0; /* Only once. */
- uf_op = uf+len_ma;
- memcpy(&uf_op[0], "TRMMGVUF", 8);
- if (little_endian()) swap2(&uf_op[0], 8/2);
- uf_op[4] = (signed short)UF_NO_DATA;
- uf_op[5] = (signed short)UF_NO_DATA;
- uf_op[6] = ray->h.hour;
- uf_op[7] = ray->h.minute;
- uf_op[8] = ray->h.sec;
- memcpy(&uf_op[9], "RADAR_UF", 8);
- if (little_endian()) swap2(&uf_op[9], 8/2);
- uf_op[13] = 2;
- len_op = 14;
- }
- /* ---- End of OPTIONAL HEADER BLOCK. */
-
- /* ---- Begining of LOCAL USE HEADER BLOCK. */
- /* If we have DZ and VR, check to see if their azimuths are
- * different. If they are, we store VR azimuth in Local Use
- * Header. These differences occur with WSR-88D radars, which
- * run separate sweeps for DZ and VR at low elevations.
- */
- q_lu = 0;
- if (sweep[DZ_INDEX] && sweep[VR_INDEX]) {
- if (sweep[DZ_INDEX]->ray[j] && sweep[VR_INDEX]->ray[j]) {
- vr_az = sweep[VR_INDEX]->ray[j]->h.azimuth;
- if (sweep[DZ_INDEX]->ray[j]->h.azimuth != vr_az)
- q_lu = 1; /* Set to use Local Use Header block. */
- }
- }
- len_lu = 0;
- if (q_lu) {
- /* Store azimuth for WSR-88D VR ray in Local Use Header. */
- uf_lu = uf+len_ma+len_op;
- memcpy(&uf_lu[0], "AZ", 2);
- if (little_endian()) memcpy(&uf_lu[0], "ZA", 2);
- if (vr_az > 0) uf_lu[1] = vr_az*64 + 0.5;
- else uf_lu[1] = vr_az*64 - 0.5;
- len_lu = 2;
- }
- /* ---- End of LOCAL USE HEADER BLOCK. */
-
-
- /* Here is where we loop on each field type. We need to keep
- * track of how many FIELD HEADER and FIELD DATA sections, one
- * for each field type, we fill. The variable that tracks this
- * index into 'uf' is 'current_fh_index'. It is bumped by
- * the length of the FIELD HEADER and FIELD DATA for each field
- * type encountered. Field types expected are: Reflectivity,
- * Velocity, and Spectrum width; this is a typicial list but it
- * is not restricted to it.
- */
-
- for (k=0; k<nvolumes; k++) {
- if (sweep[k])
- if (sweep[k]->ray)
- ray = sweep[k]->ray[j];
- else
- ray = NULL;
- else ray = NULL;
-
- if (k >= sizeof(UF_field_name)) {
- ray = NULL;
- fprintf(stderr,"RSL_uf_to_radar: Unknown field type encountered.\n");
- fprintf(stderr,"The field type index in Radar exceeds the number of known UF field types.\n");
- }
-
- if (ray) {
- /* ---- Begining of DATA HEADER. */
- nfield++;
- if (q_dh) {
- len_dh = 2*true_nvolumes + 3;
- uf_dh = uf+len_ma+len_op+len_lu;
- uf_dh[0] = nfield;
- uf_dh[1] = 1;
- uf_dh[2] = nfield;
- /* 'nfield' indexes the field number.
- * 'k' indexes the particular field from the volume.
- */
- memcpy(&uf_dh[3+2*(nfield-1)], UF_field_name[k], 2);
- if (little_endian()) swap2(&uf_dh[3+2*(nfield-1)], 2/2);
- if (current_fh_index == 0) current_fh_index = len_ma+len_op+len_lu+len_dh;
- uf_dh[4+2*(nfield-1)] = current_fh_index + 1;
- }
- /* ---- End of DATA HEADER. */
-
- /* ---- Begining of FIELD HEADER. */
- if (q_fh) {
- uf_fh = uf+current_fh_index;
- uf_fh[1] = scale_factor = 100;
- uf_fh[2] = ray->h.range_bin1/1000.0;
- uf_fh[3] = ray->h.range_bin1 - (1000*uf_fh[2]);
- uf_fh[4] = ray->h.gate_size;
- uf_fh[5] = ray->h.nbins;
- uf_fh[6] = ray->h.pulse_width*(RSL_SPEED_OF_LIGHT/1.0e6);
- uf_fh[7] = sweep[k]->h.beam_width*64.0 + 0.5;
- uf_fh[8] = sweep[k]->h.beam_width*64.0 + 0.5;
- uf_fh[9] = ray->h.frequency*64.0 + 0.5; /* Bandwidth (mHz). */
- uf_fh[10] = 0; /* Horizontal polarization. */
- uf_fh[11] = ray->h.wavelength*64.0*100.0; /* m to cm. */
- uf_fh[12] = ray->h.pulse_count;
- memcpy(&uf_fh[13], " ", 2);
- uf_fh[14] = (signed short)UF_NO_DATA;
- uf_fh[15] = (signed short)UF_NO_DATA;
- if (k == DZ_INDEX || k == ZT_INDEX) {
- uf_fh[16] = volume[k]->h.calibr_const*100.0 + 0.5;
- }
- else {
- memcpy(&uf_fh[16], " ", 2);
- }
- if (ray->h.prf != 0)
- uf_fh[17] = 1.0/ray->h.prf*1000000.0; /* Pulse repetition time(msec) = 1/prf */
- else
- uf_fh[17] = (signed short)UF_NO_DATA; /* Pulse repetition time = 1/prf */
- uf_fh[18] = 16;
- if (VR_INDEX == k || VE_INDEX == k) {
- uf_fh[19] = scale_factor*ray->h.nyq_vel;
- uf_fh[20] = 1;
- len_fh = 21;
- } else {
- len_fh = 19;
- }
-
- uf_fh[0] = current_fh_index + len_fh + 1;
- /* ---- End of FIELD HEADER. */
-
- /* ---- Begining of FIELD DATA. */
- uf_data = uf+len_fh+current_fh_index;
- len_data = ray->h.nbins;
- for (m=0; m<len_data; m++) {
- x = ray->h.f(ray->range[m]);
- if (x == BADVAL || x == RFVAL || x == APFLAG || x == NOECHO)
- uf_data[m] = (signed short)UF_NO_DATA;
- else
- uf_data[m] = scale_factor * x;
- }
-
- current_fh_index += (len_fh+len_data);
- }
- }
- /* ---- End of FIELD DATA. */
- }
- /* Fill in some infomation we didn't know. Like, buffer length,
- * record number, etc.
- */
- rec_num++;
- uf_ma[1] = current_fh_index;
- uf_ma[3] = len_ma + len_op + 1;
- uf_ma[4] = len_ma + len_op + len_lu + 1;
- uf_ma[5] = rec_num;
-
- /* WRITE the UF buffer. */
- rec_len =(int)uf_ma[1]*2;
- save_rec_len = rec_len; /* We destroy 'rec_len' when making it
- big endian on a little endian machine. */
- if (little_endian()) swap_4_bytes(&rec_len);
- (void)fwrite(&rec_len, sizeof(int), 1, fp);
- if (little_endian()) swap_uf_buffer(uf);
- (void)fwrite(uf, sizeof(char), save_rec_len, fp);
- (void)fwrite(&rec_len, sizeof(int), 1, fp);
- } /* if (ray) */
- }
+ /*
+ * ---- Begining of MANDITORY HEADER BLOCK.
+ */
+ uf_ma = uf;
+ memcpy(&uf_ma[0], "UF", 2);
+ if (little_endian()) memcpy(&uf_ma[0], "FU", 2);
+ uf_ma[1] = 0; /* Not known yet. */
+ uf_ma[2] = 0; /* Not known yet. Really, I do. */
+ uf_ma[3] = 0; /* Not known yet. */
+ uf_ma[4] = 0; /* Not known yet. */
+
+ uf_ma[6] = 1;
+ uf_ma[7] = ray_num;
+ uf_ma[8 ] = 1;
+ uf_ma[9 ] = sweep_num;
+ memcpy(&uf_ma[10], r->h.radar_name, 8);
+ if (little_endian()) swap2(&uf_ma[10], 8/2);
+ memcpy(&uf_ma[14], r->h.name, 8);
+ if (little_endian()) swap2(&uf_ma[14], 8/2);
+ /* Convert decimal lat/lon to d:m:s */
+
+ if (ray->h.lat != 0.0) {
+ degree = (int)ray->h.lat;
+ minute = (int)((ray->h.lat - degree) * 60);
+ second = (ray->h.lat - degree - minute/60.0) * 3600.0;
+ } else {
+ degree = r->h.latd;
+ minute = r->h.latm;
+ second = r->h.lats;
+ }
+ uf_ma[18] = degree;
+ uf_ma[19] = minute;
+ if (second > 0.0) uf_ma[20] = second*64 + 0.5;
+ else uf_ma[20] = second*64 - 0.5;
+
+ if (ray->h.lon != 0.0) {
+ degree = (int)ray->h.lon;
+ minute = (int)((ray->h.lon - degree) * 60);
+ second = (ray->h.lon - degree - minute/60.0) * 3600.0;
+ } else {
+ degree = r->h.lond;
+ minute = r->h.lonm;
+ second = r->h.lons;
+ }
+ uf_ma[21] = degree;
+ uf_ma[22] = minute;
+ if (second > 0.0) uf_ma[23] = second*64 + 0.5;
+ else uf_ma[23] = second*64 - 0.5;
+ if (ray->h.alt != 0)
+ uf_ma[24] = ray->h.alt;
+ else
+ uf_ma[24] = r->h.height;
+
+ uf_ma[25] = ray->h.year % 100; /* By definition: not year 2000 compliant. */
+ uf_ma[26] = ray->h.month;
+ uf_ma[27] = ray->h.day;
+ uf_ma[28] = ray->h.hour;
+ uf_ma[29] = ray->h.minute;
+ uf_ma[30] = ray->h.sec;
+ memcpy(&uf_ma[31], "UT", 2);
+ if (little_endian()) memcpy(&uf_ma[31], "TU", 2);
+ if (ray->h.azimuth > 0) uf_ma[32] = ray->h.azimuth*64 + 0.5;
+ else uf_ma[32] = ray->h.azimuth*64 - 0.5;
+ uf_ma[33] = ray->h.elev*64 + 0.5;
+ uf_ma[34] = uf_sweep_mode;
+ if (ray->h.fix_angle != 0.)
+ uf_ma[35] = ray->h.fix_angle*64.0 + 0.5;
+ else uf_ma[35] = sweep[k]->h.elev*64.0 + 0.5;
+ uf_ma[36] = ray->h.sweep_rate*(360.0/60.0)*64.0 + 0.5;
+
+ the_time = time(NULL);
+ tm = gmtime(&the_time);
+
+ uf_ma[37] = tm->tm_year % 100; /* Same format as data year */
+ uf_ma[38] = tm->tm_mon+1;
+ uf_ma[39] = tm->tm_mday;
+ memcpy(&uf_ma[40], "RSL" RSL_VERSION_STR, 8);
+ if (little_endian()) swap2(&uf_ma[40], 8/2);
+ uf_ma[44] = (signed short)UF_NO_DATA;
+ len_ma = 45;
+ uf_ma[2] = len_ma+1;
+ /*
+ * ---- End of MANDITORY HEADER BLOCK.
+ */
+
+ /* ---- Begining of OPTIONAL HEADER BLOCK. */
+ len_op = 0;
+ if (q_op) {
+ q_op = 0; /* Only once. */
+ uf_op = uf+len_ma;
+ memcpy(&uf_op[0], "TRMMGVUF", 8);
+ if (little_endian()) swap2(&uf_op[0], 8/2);
+ uf_op[4] = (signed short)UF_NO_DATA;
+ uf_op[5] = (signed short)UF_NO_DATA;
+ uf_op[6] = r->h.hour;
+ uf_op[7] = r->h.minute;
+ uf_op[8] = r->h.sec;
+ memcpy(&uf_op[9], "RADAR_UF", 8);
+ if (little_endian()) swap2(&uf_op[9], 8/2);
+ uf_op[13] = 2;
+ len_op = 14;
+ }
+ /* ---- End of OPTIONAL HEADER BLOCK. */
+
+ /* ---- Begining of LOCAL USE HEADER BLOCK. */
+ q_lu = 0;
+ len_lu = 0;
+ if (q_lu) {
+ uf_lu = uf+len_ma+len_op;
+ q_lu = 0; /* Only once. */
+ len_lu = 0; /* I don't have anything yet. */
+ }
+ /* ---- End of LOCAL USE HEADER BLOCK. */
+
+
+ /* Here is where we loop on each field type. We need to keep
+ * track of how many FIELD HEADER and FIELD DATA sections, one
+ * for each field type, we fill. The variable that tracks this
+ * index into 'uf' is 'current_fh_index'. It is bumped by
+ * the length of the FIELD HEADER and FIELD DATA for each field
+ * type encountered. Field types expected are: Reflectivity,
+ * Velocity, and Spectrum width; this is a typicial list but it
+ * is not restricted to it.
+ */
+
+ for (k=0; k<nvolumes; k++) {
+ if (sweep[k])
+ if (j < sweep[k]->h.nrays && sweep[k]->ray[j])
+ ray = sweep[k]->ray[j];
+ else
+ ray = NULL;
+ else ray = NULL;
+
+ if (ray) {
+ /* ---- Begining of DATA HEADER. */
+ nfield++;
+ if (q_dh) {
+ len_dh = 2*true_nvolumes + 3;
+ uf_dh = uf+len_ma+len_op+len_lu;
+ uf_dh[0] = nfield;
+ uf_dh[1] = 1;
+ uf_dh[2] = nfield;
+ /* 'nfield' indexes the field number.
+ * 'k' indexes the particular field from the volume.
+ * RSL_ftype contains field names and is defined in rsl.h.
+ */
+ if (k > max_field_names-1) {
+ fprintf(stderr,
+ "RSL_uf_to_radar: No field name for volume index %d\n", k);
+ fprintf(stderr,"RSL_ftype must be updated in rsl.h for new field.\n");
+ fprintf(stderr,"Quitting now.\n");
+ return;
+ }
+ memcpy(&uf_dh[3+2*(nfield-1)], RSL_ftype[k], 2);
+ if (little_endian()) swap2(&uf_dh[3+2*(nfield-1)], 2/2);
+ if (current_fh_index == 0) current_fh_index = len_ma+len_op+len_lu+len_dh;
+ uf_dh[4+2*(nfield-1)] = current_fh_index + 1;
+ }
+ /* ---- End of DATA HEADER. */
+
+ /* ---- Begining of FIELD HEADER. */
+ if (q_fh) {
+ uf_fh = uf+current_fh_index;
+ if (k != PH_INDEX) scale_factor = 100;
+ else scale_factor = 10;
+ uf_fh[1] = scale_factor;
+ uf_fh[2] = ray->h.range_bin1/1000.0;
+ uf_fh[3] = ray->h.range_bin1 - (1000*uf_fh[2]);
+ uf_fh[4] = ray->h.gate_size;
+ uf_fh[5] = ray->h.nbins;
+ uf_fh[6] = ray->h.pulse_width*(RSL_SPEED_OF_LIGHT/1.0e6);
+ uf_fh[7] = sweep[k]->h.beam_width*64.0 + 0.5;
+ uf_fh[8] = sweep[k]->h.beam_width*64.0 + 0.5;
+ uf_fh[9] = ray->h.frequency * 1000.; /* Bandwidth (mHz). */
+ uf_fh[10] = 0; /* Horizontal polarization. */
+ uf_fh[11] = ray->h.wavelength*64.0*100.0; /* m to cm. */
+ uf_fh[12] = ray->h.pulse_count;
+ memcpy(&uf_fh[13], " ", 2);
+ uf_fh[14] = (signed short)UF_NO_DATA;
+ uf_fh[15] = (signed short)UF_NO_DATA;
+ if (k == DZ_INDEX || k == ZT_INDEX) {
+ uf_fh[16] = volume[k]->h.calibr_const*100.0 + 0.5;
+ }
+ else {
+ memcpy(&uf_fh[16], " ", 2);
+ }
+ if (ray->h.prf != 0)
+ uf_fh[17] = 1.0/ray->h.prf*1000000.0; /* Pulse repetition time(msec) = 1/prf */
+ else
+ uf_fh[17] = (signed short)UF_NO_DATA; /* Pulse repetition time = 1/prf */
+ uf_fh[18] = 16;
+ if (VR_INDEX == k || VE_INDEX == k) {
+ uf_fh[19] = scale_factor*ray->h.nyq_vel;
+ uf_fh[20] = 1;
+ len_fh = 21;
+ } else {
+ len_fh = 19;
+ }
+
+ uf_fh[0] = current_fh_index + len_fh + 1;
+ /* ---- End of FIELD HEADER. */
+
+ /* ---- Begining of FIELD DATA. */
+ uf_data = uf+len_fh+current_fh_index;
+ len_data = ray->h.nbins;
+ for (m=0; m<len_data; m++) {
+ x = ray->h.f(ray->range[m]);
+ if (x == BADVAL || x == RFVAL || x == APFLAG || x == NOECHO)
+ uf_data[m] = (signed short)UF_NO_DATA;
+ else
+ uf_data[m] = scale_factor * x;
+ }
+
+ current_fh_index += (len_fh+len_data);
+ }
+ }
+ /* ---- End of FIELD DATA. */
+ }
+ /* Fill in some infomation we didn't know. Like, buffer length,
+ * record number, etc.
+ */
+ rec_num++;
+ uf_ma[1] = current_fh_index;
+ uf_ma[3] = len_ma + len_op + 1;
+ uf_ma[4] = len_ma + len_op + len_lu + 1;
+ uf_ma[5] = rec_num;
+
+ /* WRITE the UF buffer. */
+ rec_len =(int)uf_ma[1]*2;
+ save_rec_len = rec_len; /* We destroy 'rec_len' when making it
+ big endian on a little endian machine. */
+ if (little_endian()) swap_4_bytes(&rec_len);
+ (void)fwrite(&rec_len, sizeof(int), 1, fp);
+ if (little_endian()) swap_uf_buffer(uf);
+ (void)fwrite(uf, sizeof(char), save_rec_len, fp);
+ (void)fwrite(&rec_len, sizeof(int), 1, fp);
+ } /* if (ray) */
+ }
}
+
+ /* If Radar argument "r" was modified (WSR-88D), restore the saved copy. */
+ if (r_save != NULL) r = r_save;
}
/**********************************************************************/
{
FILE *fp;
if (r == NULL) {
- fprintf(stderr, "radar_to_uf: radar pointer NULL\n");
- return;
+ fprintf(stderr, "radar_to_uf: radar pointer NULL\n");
+ return;
}
if ((fp = fopen(outfile, "w")) == NULL) {
- perror(outfile);
- return;
+ perror(outfile);
+ return;
}
RSL_radar_to_uf_fp(r, fp);
{
FILE *fp;
if (r == NULL) {
- fprintf(stderr, "radar_to_uf_gzip: radar pointer NULL\n");
- return;
+ fprintf(stderr, "radar_to_uf_gzip: radar pointer NULL\n");
+ return;
}
if ((fp = fopen(outfile, "w")) == NULL) {
- perror(outfile);
- return;
+ perror(outfile);
+ return;
}
fp = compress_pipe(fp);