/*
* dorade.c --
*
* This file defines functions that access and manage data in DORADE sweep
* files.
*
* The struct's are based on those found in the soloii source distribution
* from National Center for Atmospheric Research (NCAR), Earth Observing
* Laboratory, Research Data Program (RDP), downloaded from
* ftp.atd.ucar.edu.
*
* Copyright (c) 2007 Gordon D. Carrie
*
* Licensed under the Open Software License version 2.1
*
* Please send feedback to user0@tkgeomap.org
*
* @(#) $Id: dorade_lib.c,v 1.1 2008/08/29 22:46:28 ywang Exp $
*
**********************************************************************
*
*/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <time.h>
#include "errMsg.h"
#include "getVals.h"
#include "dorade.h"
/*
* This macro adjusts a float value so that when it truncates, value rounds
* to the nearest integer.
*/
#define N_INT(f) ((f) > 0.0 ? (f) + 0.5 : (f) - 0.5)
/*
* Macros needed for decompression
*/
#define MASK15 0x7fff
#define SIGN16 0x8000
/*
* Declarations for local functions.
*/
static int angle_cmp(const void *a1, const void *a2);
/*
* This array temporarily stores information for new command sets.
*/
static struct Hash_Info *info;
/*
* Input buffer
*/
static char *inBufP; /* Input buffer */
static size_t in_sz; /* Size of allocation at inBufP */
/*
*------------------------------------------------------------------------
*
* Dorade_InitSweep --
*
* This function initializes a new DORADE sweep structure.
*
* Arguments:
* struct Dorade_Sweep *swpP - Sweep structure. The structure
* should already be allocated. Its
* contents should be garbage.
*
* Results:
* None
*
* Side effects:
* The structure is filled in with bogus values.
*
*------------------------------------------------------------------------
*/
void Dorade_InitSweep(struct Dorade_Sweep *swpP)
{
char blank[22] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
strncpy(swpP->radar_name, blank, 9);
strncpy(swpP->proj_name, blank, 21);
swpP->n_parms = 0;
swpP->n_use_parms = 0;
swpP->vol_num = 0;
swpP->time.day = 0;
swpP->time.second = 0;
swpP->n_sensors = 0;
swpP->radar_const = 0.0;
swpP->peak_power = 0.0;
swpP->noise_power = 0.0;
swpP->receiver_gain = 0.0;
swpP->antenna_gain = 0.0;
swpP->system_gain = 0.0;
swpP->horz_beam_width = 0;
swpP->vert_beam_width = 0;
swpP->radar_type = 0;
swpP->scan_mode = DORADE_CALIBRATION;
swpP->req_rotat_vel = 0.0;
swpP->data_reduction = 1;
swpP->data_red_parm0 = 0.0;
swpP->data_red_parm1 = 0.0;
swpP->radar_location = GeoPtNowhere();
swpP->radar_altitude = 0.0;
swpP->eff_unamb_vel = 0.0;
swpP->eff_unamb_range = 0.0;
swpP->num_freq_trans = 1;
swpP->num_ipps_trans = 1;
swpP->freq1 = 0.0;
swpP->freq2 = 0.0;
swpP->freq3 = 0.0;
swpP->freq4 = 0.0;
swpP->freq5 = 0.0;
swpP->interpulse_per1 = 0.0;
swpP->interpulse_per2 = 0.0;
swpP->interpulse_per3 = 0.0;
swpP->interpulse_per4 = 0.0;
swpP->interpulse_per5 = 0.0;
swpP->n_cells = 0;
swpP->distP = NULL;
swpP->parmP = NULL;
Hash_InitTable(&swpP->parm_tbl);
swpP->azimuth_corr = AngleFmDeg(0.0);
swpP->elevation_corr = AngleFmDeg(0.0);
swpP->range_delay_corr = 0.0;
swpP->longitude_corr = AngleFmDeg(0.0);
swpP->latitude_corr = AngleFmDeg(0.0);
swpP->pressure_alt_corr = 0.0;
swpP->radar_alt_corr = 0.0;
swpP->ew_gndspd_corr = 0.0;
swpP->ns_gndspd_corr = 0.0;
swpP->vert_vel_corr = 0.0;
swpP->heading_corr = AngleFmDeg(0.0);
swpP->roll_corr = AngleFmDeg(0.0);
swpP->pitch_corr = AngleFmDeg(0.0);
swpP->drift_corr = AngleFmDeg(0.0);
swpP->rot_angle_corr = AngleFmDeg(0.0);
swpP->tilt_corr = AngleFmDeg(0.0);
swpP->sweep_num = 0;
swpP->n_rays = 0;
swpP->n_good_rays = 0;
swpP->start_angle = 0;
swpP->stop_angle = 0;
swpP->fixed_angle = 0;
swpP->filter_flag = 0;
swpP->rayHdrP = NULL;
swpP->dat = NULL;
swpP->interpolated = 0;
}
/*
*------------------------------------------------------------------------
*
* Dorade_AllocDat --
*
* This function allocates memory for the dat member of
* a Dorade_Sweep structure.
*
* Arguments:
* long n_parms - number of parameters
* long n_rays - number of rays
* unsigned n_cells - number of cells per ray
*
* Results:
* Return value is a three dimensional array of float values.
*
* Side effects:
* Memory is allocated. It will be freed with a call to Dorade_FreeSweep.
* If something goes wrong, an error message is stored with a call to
* ErrMsg_Append.
*
*------------------------------------------------------------------------
*/
float ***Dorade_AllocDat(long n_parms, long n_rays, unsigned n_cells)
{
float ***dat = NULL;
unsigned p, r;
size_t ray_psz, cell_psz;
dat = (float ***)MALLOC(n_parms * sizeof(float **));
for (p = 0; p < n_parms; p++) {
dat[p] = NULL;
}
ray_psz = n_rays * sizeof(float *);
cell_psz = n_rays * n_cells * sizeof(float);
for (p = 0; p < n_parms; p++) {
dat[p] = (float **)MALLOC(ray_psz);
dat[p][0] = (float *)MALLOC(cell_psz);
for (r = 1; r < n_rays; r++) {
dat[p][r] = dat[p][r - 1] + n_cells;
}
}
return dat;
}
/*
*------------------------------------------------------------------------
*
* Dorade_FreeSweep --
*
* This function frees internal allocations in a DORADE sweep structure.
*
* Arguments:
* struct Dorade_Sweep *swpP - Sweep structure initialized with
* Dorade_InitSweep
* Results:
* None
*
* Side effects:
* Dynamic memory associated with the structure, if any, is freed.
* The space for structure itself remains allocated.
* The sweep structure is filled in with bogus values.
*
*------------------------------------------------------------------------
*/
void Dorade_FreeSweep(struct Dorade_Sweep *swpP)
{
int p;
if ( !swpP ) {
return;
}
FREE(swpP->distP);
FREE(swpP->parmP);
FREE(swpP->rayHdrP);
if (swpP->dat) {
for (p = 0; p < swpP->n_parms; p++) {
if (swpP->dat[p]) {
FREE(swpP->dat[p][0]);
}
FREE(swpP->dat[p]);
}
FREE(swpP->dat);
}
Hash_ClearTable(&swpP->parm_tbl);
Dorade_InitSweep(swpP);
}
/*
*------------------------------------------------------------------------
*
* Dorade_InitParm --
*
* This function initializes a new Dorade_ParmDesc structure.
*
* Arguments:
* struct Dorade_ParmDesc *parmP - Parameter descriptor structure.
* The structure should already be
* allocated. Its contents should
* be garbage.
* Results:
* None
*
* Side effects:
* The structure is filled in with bogus values.
*
*------------------------------------------------------------------------
*/
void Dorade_InitParm(struct Dorade_ParmDesc *parmP)
{
char blank[42] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
parmP->use = 0;
strncpy(parmP->name, blank, 9);
strncpy(parmP->description, blank, 41);
strncpy(parmP->units, blank, 9);
parmP->interpulse_time = 0;
parmP->xmitted_freq = 0;
parmP->recvr_bandwidth = 0.0;
parmP->pulse_width = 0;
parmP->polarization = 0;
parmP->num_samples = 0;
parmP->binary_format = 0;
strncpy(parmP->threshold_field, "NONE", 9);
parmP->threshold_value = 0.0;
parmP->scale = 0.0;
parmP->bias = 0.0;
parmP->bad_data = 0;
parmP->min = 0.0;
}
/*
*------------------------------------------------------------------------
*
* Dorade_InitRayHdr --
*
* This function initializes a new Dorade ray header structure.
*
* Arguments:
* struct Dorade_RayHdr *rayHdrP - ray header to initialize.
* The structure should already be
* allocated. Its contents should
* be garbage.
* Results:
* None
*
* Side effec