vol2bird
libvol2bird.h
1 /*
2  * Copyright 2015 Adriaan Dokter & Netherlands eScience Centre
3  * If you want to use this software, please contact me at a.m.dokter@uva.nl
4  *
5  * This program calculates Vertical Profiles of Birds (VPBs) as described in
6  *
7  * Bird migration flight altitudes studied by a network of operational weather radars
8  * Dokter A.M., Liechti F., Stark H., Delobbe L., Tabary P., Holleman I.
9  * J. R. Soc. Interface, 8, 30–43, 2011
10  * DOI: 10.1098/rsif.2010.0116
11  *
12  */
13 
14 #include <confuse.h>
15 #include <polarvolume.h>
16 #include <vertical_profile.h>
17 
18 // ****************************************************************************
19 // Definition of standard parameters.
20 // ****************************************************************************
21 
22 #define DEG2RAD (0.017453293) // Degrees to radians.
23 #define RAD2DEG (57.29578) // Radians to degrees.
24 
25 // ****************************************************************************
26 // Definition of general macros:
27 // ****************************************************************************
28 
29 #define XABS(x) (((x) < 0) ? (-(x)) : (x))
30 #define ROUND(x) (((x) > 0) ? (int)((x) + 0.5) : (int)((x)-0.5))
31 #define SQUARE(x) ((x) * (x))
32 
33 // ****************************************************************************
34 // Defined (default) parameters.
35 // ****************************************************************************
36 
37 #ifndef PI
38 #define PI (3.14159265358979323846)
39 #endif
40 
41 #ifndef TRUE
42 #define TRUE 1
43 #endif
44 
45 #ifndef FALSE
46 #define FALSE 0
47 #endif
48 
49 // ****************************************************************************
50 // Structure for containing SCAN metadata:
51 // ****************************************************************************
52 
53 struct cellprop {
54  int iRangOfMax;
55  int iAzimOfMax;
56  float dbzAvg;
57  float texAvg;
58  float cv;
59  int nGates;
60  int nGatesClutter;
61  double area;
62  float dbzMax;
63  int index;
64  int drop;
65 };
66 
67 struct scanmeta {
68  float heig; // Height of radar antenna in km.
69  float elev; // Elevation of scan in deg.
70  int nRang; // Number of range bins in scan.
71  int nAzim; // Number of azimuth rays in scan.
72  float rangeScale; // Size of range bins in scan in km.
73  float azimScale; // Size of azimuth steps in scan in deg.
74  float valueOffset; // Offset value of quantity contained by scan.
75  float valueScale; // Scale of value of quantity contained by scan.
76  float missing; // Missing value of quantity contained by scan.
77  double nyquist; // Nyquist velocity of the scan
78 };
79 
80 typedef struct cellprop CELLPROP;
81 typedef struct scanmeta SCANMETA;
82 
83 // *****************************************************************************
84 // Structures for internal use
85 // *****************************************************************************
86 
87 // ------------------------------------------------------------- //
88 // vol2bird options from options.conf //
89 // ------------------------------------------------------------- //
90 
92  int nLayers; /* the number of layers in an altitude profile */
93  float layerThickness; /* the width/thickness of a layer [m] */
94  float rangeMin; /* the minimum range [m] used for constructing the bird density profile */
95  float rangeMax; /* the maximum range [m] used for constructing the bird density profile */
96  float azimMin; /* the minimum azimuth [degrees] used for constructing the bird density profile */
97  float azimMax; /* the maximum azimuth [degrees] used for constructing the bird density profile */
98  float elevMin; /* the minimum scan elevation [degrees] used for constructing the bird density profile */
99  float elevMax; /* the maximum scan elevation [degrees] used for constructing the bird density profile */
100  float radarWavelength; /* the default wavelength [cm] of the radar if it is not included in the metadata */
101  int useClutterMap; /* whether a static clutter map is used */
102  char clutterMap[1000]; /* path and filename of static cluttermap / beam occultation map to use */
103  float clutterValueMin; /* positions in static clutter map with value above this value are excluded as clutter */
104  int printOptions; /* print options to stderr */
105  int printDbz; /* print dbz to stderr */
106  int printDealias; /* print aliased and dealiased vrad pairs to stderr */
107  int printVrad; /* print vrad to stderr */
108  int printRhohv; /* print rhohv to stderr */
109  int printCell; /* print cell to stderr */
110  int printCellProp; /* print cell properties to stderr */
111  int printTex; /* print texture to stderr */
112  int printClut; /* print clutter to stderr */
113  int printProfileVar; /* print profile data to stderr */
114  int printPointsArray; /* whether or not to print the 'points' array */
115  int fitVrad; /* Whether or not to fit a model to the observed vrad */
116  int exportBirdProfileAsJSONVar; /* whether you want to export the vertical bird profile as JSON */
117  float minNyquist; /* Minimum Nyquist velocity [m/s] to include a scan; */
118  float maxNyquistDealias; /* When all scans (except those excluded by minNyquist) have nyquist velocity */
119  /* higher than this value, dealiasing is suppressed; */
120  float birdRadarCrossSection; /* Bird radar cross section [cm^2] */
121  float etaMax; /* Maximum reflectivity factor of reflectivity gates containing birds */
122  float cellEtaMin; /* Maximum mean reflectivity [cm^2/km^3] of cells of birds */
123  float cellStdDevMax; /* When analyzing cells, only cells for which the stddev of vrad */
124  /* (aka the texture) is less than cellStdDevMax are considered in the */
125  /* rest of the analysis*/
126  float stdDevMinBird; /* Minimum VVP radial velocity standard deviation for layer containing birds*/
127  char dbzType[10]; /* Preferred dBZ quantity to use */
128  int requireVrad; /* require range gates to have a valid radial velocity measurement */
129  int dealiasVrad; /* dealias radial velocities using torus mapping method by Haase et al. */
130  int dealiasRecycle; /* whether we should dealias once, or separately for each profile type */
131  int dualPol; /* whether to use dual-polarization moments for filtering meteorological echoes */
132  int singlePol; /* whether to use single-polarization moments for filtering meteorological echoes */
133  float dbzThresMin; /* reflectivities above this threshold will be checked as potential precipitation */
134  float rhohvThresMin; /* correlation coefficients above this threshold will be removed as precipitation */
135  int resample; /* whether to resample the input polar volume */
136  float resampleRscale; /* resampled range gate length in m */
137  int resampleNbins; /* resampled number of range bins */
138  int resampleNrays; /* resampled number of azimuth bins */
139  float mistNetElevs[100]; /* array of elevation angles in degrees to use in Cartesian projection*/
140  int mistNetNElevs; /* array of elevation angles in degrees to use in Cartesian projection*/
141  int mistNetElevsOnly; /* use only the specified elevation scans for mistnet to calculate profile if TRUE */
142  /* otherwise, use all available elevation scans*/
143  int useMistNet; /* whether to use MistNet segmentation model */
144  char mistNetPath[1000]; /* path and filename of the MistNet segmentation model to use, expects libtorch format */
145 
146 };
147 typedef struct vol2birdOptions vol2birdOptions_t;
148 
149 // ------------------------------------------------------------- //
150 // vol2bird options from constants.h //
151 // ------------------------------------------------------------- //
152 
154  // after fitting the vrad data, throw out any vrad observations that are more that VDIFMAX away
155  // from the fitted value, since these are likely outliers
156  float absVDifMax;
157  // when analyzing cells, areaCellMin determines the minimum size of a
158  // cell in km^2 to be considered in the rest of the analysis
159  float areaCellMin;
160  // cells with clutter fractions above this value are likely not birds
161  float cellClutterFractionMax;
162  // minimum standard deviation of the VVP fit
163  float chisqMin;
164  // threshold dbz value for excluding gates as clutter (static clutter only)
165  float clutterValueMin;
166  // maximum dbz used in calculation of profile dbzAvg
167  float dbzMax;
168  // minimum dbz for inclusion in a cell
169  float dbzThresMin;
170  // each weather cell identified by findWeatherCells() is grown by a distance
171  // equal to 'fringeDist' using a region-growing approach
172  float fringeDist;
173  // the refractive index of water
174  float refracIndex;
175  // When analyzing cells, radial velocities lower than VRADMIN are treated as clutter
176  float vradMin;
177  // when determining whether there are enough vrad observations in
178  // each direction, use NBINSGAP sectors
179  int nBinsGap;
180  // when calculating the altitude-layer averaged dbz, there should
181  // be at least NDBZMIN valid data points
182  int nPointsIncludedMin;
183  // the minimum number of direct neighbors with dbz value above
184  // dbzThresMin as used in findWeatherCells()
185  int nNeighborsMin;
186  // there should be at least NOBSGAPMIN vrad observations in each
187  // sector
188  int nObsGapMin;
189  // vrad's texture is calculated based on the local neighborhood. The
190  // neighborhood size in the azimuth direction is equal to NTEXBINAZIM
191  // static int nAzimNeighborhood;
192  int nAzimNeighborhood;
193  // vrad's texture is calculated based on the local neighborhood. The
194  // neighborhood size in the range direction is equal to NTEXBINRANG
195  // static int nRangNeighborhood;
196  int nRangNeighborhood;
197  // the minimum number of neighbors for the texture value to be
198  // considered valid, as used in calcTexture()
199  int nCountMin;
200 };
201 
203 
204 // ------------------------------------------------------------- //
205 // information about the 'points' array //
206 // ------------------------------------------------------------- //
207 
208 // The data needed for calculating bird densities are collected
209 // in one big array, 'points'. Although this array is one
210 // variable, it is partitioned into 'nLayers' parts. The parts
211 // are not equal in size, therefore we need to keep track of
212 // where the data pertaining to a certain altitude bin can be
213 // written. The valid range of indexes into 'points' are stored
214 // in arrays 'indexFrom' and 'indexTo'.
215 
217  // the 'points' array has this many pseudo-columns
218  int nColsPoints;
219  // the 'points' array has this many rows
220  int nRowsPoints;
221  // the psuedo-column in 'points' that holds the azimuth angle
222  int rangeCol;
223  // the psuedo-column in 'points' that holds the range
224  int azimAngleCol;
225  // the psuedo-column in 'points' that holds the elevation angle
226  int elevAngleCol;
227  // the psuedo-column in 'points' that holds the dbz value
228  int dbzValueCol;
229  // the psuedo-column in 'points' that holds the vrad value
230  int vradValueCol;
231  // the psuedo-column in 'points' that holds the cell value
232  int cellValueCol;
233  // the psuedo-column in 'points' that holds the gate classification code
234  int gateCodeCol;
235  // the psuedo-column in 'points' that holds the nyquist velocity
236  int nyquistCol;
237  // the psuedo-column in 'points' that holds the dealiased vrad value
238  int vraddValueCol;
239  // the psuedo-column in 'points' that holds the static clutter map value
240  int clutValueCol;
241  // the 'points' array itself
242  float* points; // Is allocated in vol2birdSetUp() and freed in vol2birdTearDown()
243  // for a given altitude layer in the profile, only part of the 'points'
244  // array is relevant. The 'indexFrom' and 'indexTo' arrays keep track
245  // which rows in 'points' pertains to a given layer
246  int* indexFrom; // Is allocated in vol2birdSetUp() and freed in vol2birdTearDown()
247  int* indexTo; // Is allocated in vol2birdSetUp() and freed in vol2birdTearDown()
248  // nPointsWritten stores the number of points that was copied from one
249  // of the scan elevations to the 'points' array; it should therefore
250  // never exceed indexTo[i]-indexFrom[i]
251  int* nPointsWritten; // Is allocated in vol2birdSetUp() and freed in vol2birdTearDown()
252 };
253 typedef struct vol2birdPoints vol2birdPoints_t;
254 
255 // ------------------------------------------------------------- //
256 // information about the flagfields of 'gateCode' //
257 // ------------------------------------------------------------- //
258 
260  // the bit in 'gateCode' that says whether this gate is true in the static
261  // clutter map (which we don't have yet TODO)
262  int flagPositionStaticClutter;
263  // the bit in 'gateCode' that says whether this gate is part of the
264  // calculated cluttermap (without fringe)
265  int flagPositionDynamicClutter;
266  // the bit in 'gateCode' that says whether this gate is part of the
267  // fringe of the calculated cluttermap
268  int flagPositionDynamicClutterFringe;
269  // the bit in 'gateCode' that says whether this gate has reflectivity data
270  // but no corresponding radial velocity data
271  int flagPositionVradMissing;
272  // the bit in 'gateCode' the psuedo-columnsays whether this gate's dbz value is too
273  // high to be due to birds, it must be caused by something else
274  int flagPositionDbzTooHighForBirds;
275  // the bit in 'gateCode' the psuedo-columnsays whether this gate's radial velocity is
276  // close to zero. These gates are all discarded to exclude ground
277  // clutter, which often has a radial velocity near zero.
278  int flagPositionVradTooLow;
279  // the bit in 'gateCode' that says whether this gate passed the VDIFMAX test
280  int flagPositionVDifMax;
281  // the bit in 'gateCode' that says whether the gate's azimuth angle was too low
282  int flagPositionAzimTooLow;
283  // the bit in 'gateCode' that says whether the gate's azimuth angle was too high
284  int flagPositionAzimTooHigh;
285 };
286 typedef struct vol2birdFlags vol2birdFlags_t;
287 
288 // ------------------------------------------------------------- //
289 // information about the 'profile' array //
290 // ------------------------------------------------------------- //
291 
293  // the number of different types of profile we're making
294  int nProfileTypes;
295  // how many rows there are in a profile
296  int nRowsProfile;
297  // columns in profile contain
298  // [altmin,altmax,u,v,w,hSpeed,hDir,chi,hasGap,dbzAvg,nPointsCopied,reflectivity,birdDensity]
299  int nColsProfile;
300  // the profile array itself
301  float* profile; // Is allocated in vol2birdSetUp() and freed in vol2birdTearDown()
302  // these next 3 profile arrays are an ugly way to make sure
303  // vol2birdGetProfile() can deliver its data
304  float* profile1;
305  float* profile2;
306  float* profile3;
307  // the type of profile that was last calculated
308  int iProfileTypeLast;
309 };
310 typedef struct vol2birdProfiles vol2birdProfiles_t;
311 
312 // ------------------------------------------------------------- //
313 // some other variables //
314 // ------------------------------------------------------------- //
315 
316 struct vol2birdMisc {
317  // rCellMax is defined as rangeMax + 5000.0f in order to avoid
318  // edge effects when calculating the fringe
319  float rCellMax;
320  // the number of dimensions to describe the location of an echo
321  // (azimuth and elevAngle) as used in the 'pointsSelection' array
322  // that is passed to svdfit
323  int nDims;
324  // how many parameters are fitted by the svdfit procedure
325  int nParsFitted;
326  // the factor that is used when converting from Z to eta, calculated from radar wavelength
327  float dbzFactor;
328  //Maximum mean reflectivity factor of cells of birds (conversion of cellEtaMin)
329  float cellDbzMin;
330  //Maximum reflectivity factor of reflectivity factor gates containing birds (conversion of cellEtaMax)
331  float dbzMax;
332  // whether the vol2bird module has been initialized
333  int initializationSuccessful;
334  // whether vol2bird calculated a valid bird profile
335  int vol2birdSuccessful;
336  // number of scans used to calculate the profile
337  int nScansUsed;
338  // lowest Nyquist velocity of scans present
339  double nyquistMin;
340  // lowest Nyquist velocity of scans used
341  double nyquistMinUsed;
342  // highest Nyquist velocity of scans used
343  double nyquistMax;
344  // whether configuration was loaded successfully
345  int loadConfigSuccessful;
346  // during calculation of iProfileType == 3, use this array to store the
347  // result of (chi < stdDevMinBird), such that it can be used later during
348  // calculation of iProfileType == 1
349  int* scatterersAreNotBirds; // Is allocated in vol2birdSetUp() and freed in vol2birdTearDown()
350  // this string contains all the user options and constants, for storage in ODIM task_args attribute
351  char task_args[3000];
352  // the polar volume input file name
353  char filename_pvol[1000];
354  // the vertical profile output file name
355  char filename_vp[1000];
356  // the volume coverage pattern of the polar volume input file (NEXRAD specific)
357  int vcp;
358 };
359 typedef struct vol2birdMisc vol2birdMisc_t;
360 
361 // structure for storing scan properties
363  // whether to use this scan in calculation of the profiles
364  int useScan;
365  // the reflectivity quantity used for this scan
366  char dbzName[10];
367  // the radial velocity quantity used for this scan
368  char vradName[10];
369  // the spectrum width quantity used for this scan
370  char wradName[10];
371  // the correlation coefficient quantity used for this scan
372  char rhohvName[10];
373  // the texture field quantity used for this scan
374  char texName[10];
375  // the raincell masking quantity used for this scan
376  char cellName[10];
377  // the static clutter map quantity used for this scan
378  char clutName[10];
379 };
380 typedef struct vol2birdScanUse vol2birdScanUse_t;
381 
382 // root structure, containing all data
383 struct vol2bird {
384  vol2birdOptions_t options;
385  vol2birdConstants_t constants;
386  vol2birdPoints_t points;
387  vol2birdFlags_t flags;
388  vol2birdProfiles_t profiles;
389  vol2birdMisc_t misc;
390  VerticalProfile_t* vp;
391  cfg_t* cfg;
392 };
393 typedef struct vol2bird vol2bird_t;
394 
395 typedef enum radarDataFormat {
396  radarDataFormat_UNKNOWN = 0,
397  radarDataFormat_ODIM = 1,
398  radarDataFormat_RSL = 2,
399  radarDataFormat_IRIS = 3
400 } radarDataFormat;
401 
402 
403 // *****************************************************************************
404 // Public function prototypes
405 // *****************************************************************************
406 
407 radarDataFormat determineRadarFormat(char* filename);
408 
409 int isRegularFile(const char *path);
410 
411 void vol2birdCalcProfiles(vol2bird_t* alldata);
412 
413 float* vol2birdGetProfile(int iProfileType, vol2bird_t* alldata);
414 
415 PolarVolume_t* vol2birdGetVolume(char* filenames[], int nInputFiles, float rangeMax, int small);
416 
417 PolarVolume_t* PolarVolume_resample(PolarVolume_t* volume, double rscale_proj, long nbins_proj, long nrays_proj);
418 
419 PolarScanParam_t* PolarScanParam_project_on_scan(PolarScanParam_t* param, PolarScan_t* scan, double rscale);
420 
421 PolarScanParam_t* PolarScan_newParam(PolarScan_t *scan, const char *quantity, RaveDataType type);
422 
423 int vol2birdGetNColsProfile(vol2bird_t* alldata);
424 
425 int vol2birdGetNRowsProfile(vol2bird_t* alldata);
426 
427 int vol2birdLoadClutterMap(PolarVolume_t* volume, char* file, float rangeMax);
428 
429 void vol2birdPrintIndexArrays(vol2bird_t* alldata);
430 
431 void vol2birdPrintOptions(vol2bird_t* alldata);
432 
433 void vol2birdPrintPointsArray(vol2bird_t* alldata);
434 
435 void vol2birdPrintPointsArraySimple(vol2bird_t* alldata);
436 
437 int vol2birdLoadConfig(vol2bird_t* alldata);
438 
439 int vol2birdSetUp(PolarVolume_t* volume, vol2bird_t* alldata);
440 
441 void vol2birdTearDown(vol2bird_t* alldata);
442 
443 int mapDataToRave(PolarVolume_t* volume, vol2bird_t* alldata);
444 
445 float nanify(float value);
446 
447 int saveToODIM(RaveCoreObject* object, const char* filename);
448 
449 const char* libvol2bird_version(void);
int isRegularFile(const char *path)
Function name: isRegularFile Intent: determines whether the given path is to a regular file Note: als...
Definition: libvol2bird.c:2694
Definition: libvol2bird.h:53
Definition: libvol2bird.h:67
Definition: libvol2bird.h:153
Definition: libvol2bird.h:259
Definition: libvol2bird.h:316
Definition: libvol2bird.h:91
Definition: libvol2bird.h:216
Definition: libvol2bird.h:292
Definition: libvol2bird.h:362
Definition: libvol2bird.h:383